260 lines
6.1 KiB
JavaScript
260 lines
6.1 KiB
JavaScript
import dayjs, { dayjsLocal } from './dayjs';
|
||
import { getTeam } from '../data/team';
|
||
import { format } from 'sql-formatter';
|
||
|
||
export function bytes(bytes, decimals = 2, current = 0) {
|
||
if (bytes === 0) return '0 Bytes';
|
||
|
||
const k = 1024;
|
||
const dm = decimals < 0 ? 0 : decimals;
|
||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||
let i = Math.floor(Math.log(Math.abs(bytes)) / Math.log(k));
|
||
if (i < 0) i++;
|
||
|
||
return (
|
||
parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i + current]
|
||
);
|
||
}
|
||
|
||
export function duration(value) {
|
||
if (!value) return;
|
||
|
||
let [hours, minutes, seconds] = value.split(':');
|
||
[hours, minutes, seconds] = [
|
||
parseInt(hours),
|
||
parseInt(minutes),
|
||
parseInt(seconds),
|
||
];
|
||
|
||
let format = '';
|
||
if (hours > 0) {
|
||
format = 'H[h] m[m] s[s]';
|
||
} else if (minutes > 0) {
|
||
format = 'm[m] s[s]';
|
||
} else {
|
||
format = 's[s]';
|
||
}
|
||
return dayjs.duration({ hours, minutes, seconds }).format(format);
|
||
}
|
||
|
||
export function plural(number, singular, plural) {
|
||
if (typeof number === 'string') {
|
||
number = parseInt(number);
|
||
}
|
||
if (number === 1) {
|
||
return singular;
|
||
}
|
||
return plural;
|
||
}
|
||
|
||
export function planTitle(plan) {
|
||
if (plan === undefined) return;
|
||
const $team = getTeam();
|
||
const china = $team.pg?.currency === 'CNY';
|
||
const priceField = china ? 'price_cny' : 'price_usd';
|
||
const price =
|
||
plan?.block_monthly == 1 ? plan[priceField] * 12 : plan[priceField];
|
||
return price > 0 ? `${userCurrency(price, 0)}` : plan.plan_title;
|
||
}
|
||
|
||
export function userCurrency(value, fractions = 2) {
|
||
const $team = getTeam();
|
||
if (!$team.pg?.currency) return value;
|
||
return currency(value, $team.pg?.currency, fractions);
|
||
}
|
||
|
||
export function currency(value, currency, fractions = 2) {
|
||
return new Intl.NumberFormat('zh-CN', {
|
||
style: 'currency',
|
||
currency,
|
||
maximumFractionDigits: fractions,
|
||
}).format(value);
|
||
}
|
||
|
||
export function numberK(number) {
|
||
if (number < 1000) {
|
||
return number;
|
||
} else {
|
||
let value = Math.round(number / 1000, 1);
|
||
|
||
// To handle cases like 8.0, 9.0 etc.
|
||
if (value == number / 1000) {
|
||
value = parseInt(value);
|
||
}
|
||
// To handle cases like 8999 -> 9k and not 9.0k
|
||
else if (value - 1 == number / 1000) {
|
||
value = parseInt(value);
|
||
}
|
||
|
||
return `${value}k`;
|
||
}
|
||
}
|
||
|
||
export function pricePerDay(price, interval = 'Monthly') {
|
||
if (!price) return 0;
|
||
// 根据计费周期计算天数
|
||
const daysInPeriod = interval === 'Annually' ? 365 : 30;
|
||
return price / daysInPeriod;
|
||
}
|
||
|
||
export function date(value) {
|
||
if (!value) return '';
|
||
|
||
// 转换为YYYY-MM-DD格式,符合中国用户习惯
|
||
const date = new Date(value);
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
const day = String(date.getDate()).padStart(2, '0');
|
||
|
||
return `${year}-${month}-${day}`;
|
||
}
|
||
|
||
export function commaSeparator(arr, separator) {
|
||
let joinedString = arr.slice(0, -1).join(', ');
|
||
|
||
if (arr.length > 1) {
|
||
joinedString += ` ${separator} ${arr[arr.length - 1]}`;
|
||
} else {
|
||
joinedString += arr[0];
|
||
}
|
||
|
||
return joinedString;
|
||
}
|
||
|
||
export function commaAnd(arr) {
|
||
return commaSeparator(arr, 'and');
|
||
}
|
||
|
||
export function formatSQL(query) {
|
||
try {
|
||
return format(query, {
|
||
language: 'mariadb',
|
||
tabWidth: 2,
|
||
keywordCase: 'upper',
|
||
});
|
||
} catch (_) {
|
||
return query;
|
||
}
|
||
}
|
||
|
||
export function formatSeconds(seconds) {
|
||
if (seconds === 0) return '0s';
|
||
if (seconds <= 60) return `${seconds}s`;
|
||
|
||
const hours = Math.floor(seconds / 3600);
|
||
const minutes = Math.floor((seconds % 3600) / 60);
|
||
const remainingSeconds = seconds % 60;
|
||
|
||
let result = [];
|
||
|
||
if (hours > 0) {
|
||
result.push(`${hours}h`);
|
||
}
|
||
|
||
if (minutes > 0) {
|
||
result.push(`${minutes}m`);
|
||
}
|
||
|
||
if (remainingSeconds > 0) {
|
||
result.push(`${remainingSeconds}s`);
|
||
}
|
||
|
||
return result.join(' ');
|
||
}
|
||
|
||
export function formatCommaSeperatedNumber(number) {
|
||
let numStr = number.toString();
|
||
|
||
let lastThree = numStr.slice(-3);
|
||
let remaining = numStr.slice(0, -3);
|
||
|
||
let parts = [];
|
||
while (remaining.length > 2) {
|
||
parts.push(remaining.slice(-2));
|
||
remaining = remaining.slice(0, -2);
|
||
}
|
||
|
||
if (remaining) {
|
||
parts.push(remaining);
|
||
}
|
||
|
||
let result = parts.reverse().join(',') + ',' + lastThree;
|
||
// truncate , at start or end
|
||
result = result.replace(/^,/, '');
|
||
result = result.replace(/,$/, '');
|
||
return result;
|
||
}
|
||
|
||
export function formatMilliseconds(ms) {
|
||
if (ms < 100) {
|
||
return `${ms.toFixed(3).replace(/\.?0+$/, '')}ms`; // Keep milliseconds if less than 100 and remove unnecessary zeros
|
||
} else if (ms < 60000) {
|
||
// Less than 1 minute, convert to seconds
|
||
let seconds = ms / 1000;
|
||
return `${seconds.toFixed(1).replace(/\.?0+$/, '')}s`;
|
||
} else {
|
||
// Convert to minutes
|
||
let minutes = ms / 60000;
|
||
return `${minutes.toFixed(1).replace(/\.?0+$/, '')}m`;
|
||
}
|
||
}
|
||
|
||
export function formatValue(value, type) {
|
||
switch (type) {
|
||
case 'bytes':
|
||
return bytes(value);
|
||
case 'date':
|
||
return date(value);
|
||
case 'duration':
|
||
return duration(value);
|
||
case 'durationSeconds':
|
||
return formatSeconds(value);
|
||
case 'durationMilliseconds':
|
||
return formatMilliseconds(value);
|
||
case 'commaSeperatedNumber':
|
||
return formatCommaSeperatedNumber(value);
|
||
case 'numberK':
|
||
return numberK(value);
|
||
case 'pricePerDay':
|
||
return pricePerDay(value);
|
||
case 'sql':
|
||
return formatSQL(value);
|
||
default:
|
||
return value;
|
||
}
|
||
}
|
||
|
||
export const statusMap = {
|
||
'Active': '激活',
|
||
'Inactive': '未激活',
|
||
'Suspended': '已暂停',
|
||
'Broken': '损坏',
|
||
'Archived': '已归档',
|
||
'Pending': '待处理',
|
||
'Installing': '安装中',
|
||
'Running': '运行中',
|
||
'Success': '成功',
|
||
'Failure': '失败'
|
||
};
|
||
|
||
export const deployTypeMap = {
|
||
'Migrate': '迁移',
|
||
'Pull': '拉取',
|
||
'Update': '更新',
|
||
'Install': '安装',
|
||
'Uninstall': '卸载',
|
||
'Backup': '备份',
|
||
'Restore': '恢复',
|
||
'Upgrade': '升级',
|
||
'Downgrade': '降级',
|
||
'Rollback': '回滚',
|
||
};
|
||
|
||
export function getStatusLabel(status) {
|
||
return statusMap[status] || status;
|
||
}
|
||
|
||
export function getDeployTypeLabel(type) {
|
||
return deployTypeMap[type] || type;
|
||
}
|