164 lines
4.3 KiB
TypeScript

import { unreachable } from '.';
import { getTeam } from '../../data/team';
import { icon } from '../../utils/components';
import { isMobile } from '../../utils/device';
import { duration } from '../../utils/format';
import { ColumnField, Tab } from './types';
type JobPageTypes = 'Site' | 'Bench' | 'Server' | 'Release Group';
// 英文 job_type 到中文的映射
const jobTypeI18nMap: Record<string, string> = {
'Update Site Status': '更新站点状态',
'Update Site Configuration': '更新站点配置',
'Install App on Site': '安装应用到站点',
'Uninstall App from Site': '从站点卸载应用',
'Backup Site': '备份站点',
'Restore Site': '恢复站点',
'Create Server': '创建服务器',
'Update In Place': '原地升级',
// 可按需补充更多
};
function jobTypeI18n(type: string) {
return jobTypeI18nMap[type] || type;
}
const statusI18nMap: Record<string, string> = {
'Pending': '待处理',
'Running': '运行中',
'Success': '成功',
'Failure': '失败',
};
function statusI18n(status: string) {
return statusI18nMap[status] || status;
}
export function getJobsTab(pagetype: JobPageTypes) {
const jobRoute = getJobRoute(pagetype);
return {
label: '任务',
icon: icon('truck'),
childrenRoutes: [jobRoute],
route: 'jobs',
type: 'list',
list: {
pagetype: 'Agent Job',
filters: res => {
if (pagetype === 'Site') return { site: res.name };
else if (pagetype === 'Bench') return { bench: res.name };
else if (pagetype === 'Server') return { server: res.name };
else if (pagetype === 'Release Group') return { group: res.name };
throw unreachable;
},
route: undefined,
orderBy: 'creation desc',
searchField: 'job_type',
fields: ['end', 'job_id'],
filterControls() {
return [
{
type: 'select',
label: '状态',
fieldname: 'status',
class: !isMobile() ? 'w-24' : '',
options: ['', 'Pending', 'Running', 'Success', 'Failure']
},
{
type: 'link',
label: '类型',
fieldname: 'job_type',
options: {
pagetype: 'Agent Job Type',
orderBy: 'name asc',
pageLength: 100
}
}
];
},
rowActions: ({ row }) => [
{
label: '在桌面查看',
condition: () => getTeam()?.pg?.is_desk_user,
onClick() {
window.open(
`${window.location.protocol}//${window.location.host}/app/agent-job/${row.name}`,
'_blank'
);
}
}
],
columns: getJobTabColumns(pagetype)
}
} satisfies Tab as Tab;
}
function getJobRoute(pagetype: JobPageTypes) {
if (pagetype === 'Site') return 'Site Job';
else if (pagetype === 'Bench') return 'Bench Job';
else if (pagetype === 'Server') return 'Server Job';
else if (pagetype === 'Release Group') return 'Release Group Job';
throw unreachable;
}
function getJobTabColumns(pagetype: JobPageTypes) {
const columns: ColumnField[] = [
{
label: '任务类型',
fieldname: 'job_type',
class: 'font-medium',
format: jobTypeI18n
},
{
label: '状态',
fieldname: 'status',
type: 'Badge',
width: 0.5,
format: statusI18n
},
{
label: '站点',
fieldname: 'site',
width: 1.2
},
{
label: '持续时间',
fieldname: 'duration',
width: 0.35,
format: (value, row) => {
if (row.job_id === 0 || !row.end) return;
return duration(value);
}
},
{
label: '创建者',
fieldname: 'owner'
},
{
label: '',
fieldname: 'creation',
type: 'Timestamp',
width: 0.75,
align: 'right',
format: (value) => formatTimeZh(value)
}
];
if (pagetype !== 'Site') return columns;
return columns.filter(c => c.fieldname !== 'site');
}
// 中文时间格式化函数
function formatTimeZh(time: string | Date) {
if (!time) return '';
const date = typeof time === 'string' ? new Date(time) : time;
const now = new Date();
const diff = (now.getTime() - date.getTime()) / 1000;
if (diff < 60) return '刚刚';
if (diff < 3600) return Math.floor(diff / 60) + '分钟前';
if (diff < 86400) return Math.floor(diff / 3600) + '小时前';
if (diff < 2592000) return Math.floor(diff / 86400) + '天前';
return date.toLocaleDateString('zh-CN');
}