2025-04-12 17:39:38 +08:00

180 lines
4.5 KiB
TypeScript

import { toast } from 'vue-sonner';
import { getTeam } from '../../data/team';
import { confirmDialog, icon, renderDialog } from '../../utils/components';
import { h } from 'vue';
import PatchAppDialog from '../../components/group/PatchAppDialog.vue';
import { ColumnField, FilterField, Tab } from './types';
import { isMobile } from '../../utils/device';
const statusTheme = {
Applied: 'green',
'Not Applied': 'gray',
'In Process': 'orange',
Failure: 'red'
};
type Status = keyof typeof statusTheme;
export function getPatchesTab(forBench: boolean) {
return {
label: '补丁',
icon: icon('hash'),
route: 'patches',
type: 'list',
list: {
experimental: true, // If removing this, uncheck App Patch pagetype beta flag.
documentation: 'https://jingrow.com/docs/benches/app-patches',
pagetype: 'App Patch',
filters: res => ({ [forBench ? 'bench' : 'group']: res.name }),
searchField: 'filename',
filterControls: r =>
[
{
type: 'select',
label: '状态',
fieldname: 'status',
options: ['', 'Not Applied', 'In Process', 'Failed', 'Applied']
},
{
type: 'select',
label: '应用',
fieldname: 'app',
class: !isMobile() ? 'w-24' : '',
options: [
'',
...new Set(r.listResource.data?.map(i => String(i.app)) || [])
]
}
] satisfies FilterField[],
columns: getPatchesTabColumns(forBench),
primaryAction({ listResource: apps, documentResource: pg }) {
return {
label: '应用补丁',
slots: {
prefix: icon('plus')
},
onClick() {
const group = pg.pagetype === 'Bench' ? pg.pg.group : pg.name;
renderDialog(h(PatchAppDialog, { group: group, app: '' }));
}
};
},
rowActions({ row, listResource }) {
let team = getTeam();
return [
{
label: '在桌面查看',
condition: () => team.pg?.is_desk_user,
onClick() {
window.open(
`${window.location.protocol}//${window.location.host}/app/app-patch/${row.name}`,
'_blank'
);
}
},
{
label: '应用补丁',
condition: () => row.status !== 'In Process',
onClick: () => {
toast.promise(
listResource.runDocMethod.submit({
method: 'apply_patch',
name: String(row.name)
}),
{
loading: '正在创建应用补丁的任务',
success: () => '补丁应用正在进行中',
error: () => '应用补丁失败'
}
);
}
},
{
label: '回滚补丁',
condition: () => row.status !== 'In Process',
onClick: () => {
toast.promise(
listResource.runDocMethod.submit({
method: 'revert_patch',
name: String(row.name)
}),
{
loading: '正在创建回滚补丁的任务',
success: () => '补丁回滚正在进行中',
error: () => '回滚补丁失败'
}
);
}
},
{
label: '删除',
condition: () => row.status === 'Not Applied',
onClick: () => {
confirmDialog({
title: '删除补丁',
message: '确定要删除此补丁吗?',
onSuccess: ({ hide }) => {
toast.promise(
listResource.delete.submit(row.name, {
onSuccess: () => hide()
}),
{
loading: '正在删除...',
success: () => '补丁已删除',
error: () => '删除补丁失败'
}
);
}
});
}
}
];
}
}
} satisfies Tab;
}
function getPatchesTabColumns(forBench: boolean) {
const columns: ColumnField[] = [
{
label: '文件名',
fieldname: 'filename',
width: forBench ? '400px' : '300px'
},
{
label: '应用',
fieldname: 'app',
width: 0.4
},
{
label: '状态',
type: 'Badge',
fieldname: 'status',
theme: value => statusTheme[value as Status],
width: 0.4
},
{
label: '工作台',
fieldname: 'bench',
width: 0.8
},
{
label: '补丁链接',
fieldname: 'url',
width: forBench ? undefined : '300px',
format(value) {
if (!value) {
return '-';
}
const url = new URL(value);
return url.hostname + url.pathname;
},
link: value => String(value)
}
];
if (forBench) return columns.filter(f => f.fieldname !== 'bench');
return columns;
}