【调整】增加edgeone,证书管理执行历史批量删除,修复bug

This commit is contained in:
cai
2026-01-14 16:25:58 +08:00
parent 49486297f8
commit 1e167b7351
322 changed files with 427 additions and 74319 deletions

View File

@@ -114,3 +114,11 @@ export const enableWorkflow = (
*/
export const stopWorkflow = (params?: StopWorkflowParams): useAxiosReturn<AxiosResponseData, StopWorkflowParams> =>
useApi<AxiosResponseData, StopWorkflowParams>('/v1/workflow/stop', params)
/**
* @description 删除执行历史
* @param {string} params - 工作流ID
* @returns {useAxiosReturn<void, void>} 删除执行历史的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
*/
export const deleteExistingHistory = (params: any): useAxiosReturn<void, void> =>
useApi<void, void>(`/v1/workflow/del_workflow_history`, params)

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="128px" height="128px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
<g><path style="opacity:0.976" fill="#01d3fe" d="M 51.5,-0.5 C 52.5,-0.5 53.5,-0.5 54.5,-0.5C 53.4566,2.05616 51.7899,4.22283 49.5,6C 34.8742,17.6237 20.5408,29.6237 6.5,42C 4.92209,43.0945 3.25542,43.9278 1.5,44.5C 10.0062,20.3223 26.6729,5.32233 51.5,-0.5 Z"/></g>
<g><path style="opacity:0.968" fill="#02c9fc" d="M 54.5,-0.5 C 61.5,-0.5 68.5,-0.5 75.5,-0.5C 75.5,-0.166667 75.5,0.166667 75.5,0.5C 64.8709,9.12698 54.5376,18.127 44.5,27.5C 37.3294,29.417 29.9961,30.5837 22.5,31C 21.2312,34.6179 19.8979,38.1179 18.5,41.5C 11.8981,46.0953 5.56476,51.0953 -0.5,56.5C -0.5,54.8333 -0.5,53.1667 -0.5,51.5C 0.611848,49.4006 1.27852,47.0673 1.5,44.5C 3.25542,43.9278 4.92209,43.0945 6.5,42C 20.5408,29.6237 34.8742,17.6237 49.5,6C 51.7899,4.22283 53.4566,2.05616 54.5,-0.5 Z"/></g>
<g><path style="opacity:0.968" fill="#03bafb" d="M 75.5,0.5 C 80.2637,0.768868 84.597,2.1022 88.5,4.5C 80.9059,11.3162 73.2392,18.1495 65.5,25C 64.552,25.4828 63.552,25.6495 62.5,25.5C 63.6664,23.834 63.6664,22.1673 62.5,20.5C 56.7015,23.4011 50.7015,25.7345 44.5,27.5C 54.5376,18.127 64.8709,9.12698 75.5,0.5 Z"/></g>
<g><path style="opacity:0.976" fill="#04b2fa" d="M 88.5,4.5 C 91.721,4.89612 94.3877,6.22946 96.5,8.5C 84.1857,18.4766 71.8524,28.4766 59.5,38.5C 60.3434,34.1266 61.3434,29.7933 62.5,25.5C 63.552,25.6495 64.552,25.4828 65.5,25C 73.2392,18.1495 80.9059,11.3162 88.5,4.5 Z"/></g>
<g><path style="opacity:0.984" fill="#04abfa" d="M 96.5,8.5 C 98.4341,9.11028 100.101,10.1103 101.5,11.5C 87.7062,22.7891 74.0396,34.2891 60.5,46C 59.255,46.7914 57.9217,47.2914 56.5,47.5C 57.3456,44.4518 58.3456,41.4518 59.5,38.5C 71.8524,28.4766 84.1857,18.4766 96.5,8.5 Z"/></g>
<g><path style="opacity:0.988" fill="#05a3f8" d="M 101.5,11.5 C 105.12,13.4528 108.12,16.1195 110.5,19.5C 106.121,22.8925 101.787,26.2258 97.5,29.5C 94.1501,29.335 90.8168,29.5017 87.5,30C 85.7804,34.3768 84.4471,38.8768 83.5,43.5C 82.0783,43.7086 80.745,44.2086 79.5,45C 70.2937,53.0444 60.9604,60.8777 51.5,68.5C 53.0104,61.4587 54.677,54.4587 56.5,47.5C 57.9217,47.2914 59.255,46.7914 60.5,46C 74.0396,34.2891 87.7062,22.7891 101.5,11.5 Z"/></g>
<g><path style="opacity:0.982" fill="#0698f8" d="M 110.5,19.5 C 114.107,21.8743 115.44,25.041 114.5,29C 108.843,29.4994 103.176,29.6661 97.5,29.5C 101.787,26.2258 106.121,22.8925 110.5,19.5 Z"/></g>
<g><path style="opacity:0.979" fill="#02c0fc" d="M 18.5,41.5 C 17.8641,44.1062 17.8641,46.6062 18.5,49C 21.4816,49.498 24.4816,49.6646 27.5,49.5C 19.0875,56.0639 10.7542,62.8972 2.5,70C 1.55198,70.4828 0.551975,70.6495 -0.5,70.5C -0.5,65.8333 -0.5,61.1667 -0.5,56.5C 5.56476,51.0953 11.8981,46.0953 18.5,41.5 Z"/></g>
<g><path style="opacity:0.991" fill="#0698f8" d="M 83.5,43.5 C 82.1523,46.1647 81.819,48.8313 82.5,51.5C 71.4633,61.2043 60.13,70.5376 48.5,79.5C 49.0364,75.6861 50.0364,72.0194 51.5,68.5C 60.9604,60.8777 70.2937,53.0444 79.5,45C 80.745,44.2086 82.0783,43.7086 83.5,43.5 Z"/></g>
<g><path style="opacity:0.977" fill="#04b8fb" d="M 27.5,49.5 C 29.5,49.5 31.5,49.5 33.5,49.5C 33.7678,51.099 33.4345,52.4324 32.5,53.5C 32.5654,53.0618 32.3988,52.7284 32,52.5C 21.9177,61.7561 11.4177,70.4227 0.5,78.5C 0.737305,77.209 0.403972,76.209 -0.5,75.5C -0.5,73.8333 -0.5,72.1667 -0.5,70.5C 0.551975,70.6495 1.55198,70.4828 2.5,70C 10.7542,62.8972 19.0875,56.0639 27.5,49.5 Z"/></g>
<g><path style="opacity:0.986" fill="#0792f7" d="M 82.5,51.5 C 85.5,51.5 88.5,51.5 91.5,51.5C 76.1262,64.8432 60.7929,78.1766 45.5,91.5C 46.0966,87.3811 47.0966,83.3811 48.5,79.5C 60.13,70.5376 71.4633,61.2043 82.5,51.5 Z"/></g>
<g><path style="opacity:0.99" fill="#078cf6" d="M 91.5,51.5 C 95.1667,51.5 98.8333,51.5 102.5,51.5C 82.8803,67.4426 63.2136,83.4426 43.5,99.5C 43.5651,96.5718 44.2318,93.9052 45.5,91.5C 60.7929,78.1766 76.1262,64.8432 91.5,51.5 Z"/></g>
<g><path style="opacity:0.979" fill="#0886f6" d="M 102.5,51.5 C 105.167,51.5 107.833,51.5 110.5,51.5C 100.205,59.7932 90.2046,68.4599 80.5,77.5C 74.9845,77.3493 71.9845,80.0159 71.5,85.5C 61.1547,93.1116 50.8214,101.445 40.5,110.5C 40.7424,106.521 41.7424,102.854 43.5,99.5C 63.2136,83.4426 82.8803,67.4426 102.5,51.5 Z"/></g>
<g><path style="opacity:0.984" fill="#0980f5" d="M 110.5,51.5 C 114.167,51.5 117.833,51.5 121.5,51.5C 111.205,59.7932 101.205,68.4599 91.5,77.5C 87.8333,77.5 84.1667,77.5 80.5,77.5C 90.2046,68.4599 100.205,59.7932 110.5,51.5 Z"/></g>
<g><path style="opacity:0.981" fill="#0979f4" d="M 121.5,51.5 C 123.621,51.3253 125.621,51.6586 127.5,52.5C 127.5,53.1667 127.5,53.8333 127.5,54.5C 118.181,61.8211 109.181,69.4878 100.5,77.5C 97.5,77.5 94.5,77.5 91.5,77.5C 101.205,68.4599 111.205,59.7932 121.5,51.5 Z"/></g>
<g><path style="opacity:0.977" fill="#04b1fa" d="M 32.5,53.5 C 31.8084,57.5999 30.8084,61.5999 29.5,65.5C 28.0783,65.7086 26.745,66.2086 25.5,67C 18.1379,73.6635 10.4713,79.8302 2.5,85.5C 1.9853,83.1055 1.31863,80.7722 0.5,78.5C 11.4177,70.4227 21.9177,61.7561 32,52.5C 32.3988,52.7284 32.5654,53.0618 32.5,53.5 Z"/></g>
<g><path style="opacity:0.985" fill="#0a71f3" d="M 127.5,54.5 C 127.5,61.5 127.5,68.5 127.5,75.5C 118.765,77.4279 109.765,78.0946 100.5,77.5C 109.181,69.4878 118.181,61.8211 127.5,54.5 Z"/></g>
<g><path style="opacity:0.985" fill="#06aaf9" d="M 29.5,65.5 C 27.9856,71.892 26.3189,78.2253 24.5,84.5C 18.9023,88.0909 13.569,92.0909 8.5,96.5C 6.26187,93.0283 4.26187,89.3617 2.5,85.5C 10.4713,79.8302 18.1379,73.6635 25.5,67C 26.745,66.2086 28.0783,65.7086 29.5,65.5 Z"/></g>
<g><path style="opacity:0.969" fill="#089ef8" d="M 24.5,84.5 C 22.8868,91.7875 20.8868,98.9541 18.5,106C 17.1667,106.667 15.8333,106.667 14.5,106C 11.8539,103.198 9.85391,100.032 8.5,96.5C 13.569,92.0909 18.9023,88.0909 24.5,84.5 Z"/></g>
<g><path style="opacity:0.973" fill="#0a7ff5" d="M 71.5,85.5 C 71.2576,89.479 70.2576,93.1456 68.5,96.5C 59.3732,103.789 50.3732,111.289 41.5,119C 40.255,119.791 38.9217,120.291 37.5,120.5C 38.1301,116.952 39.1301,113.619 40.5,110.5C 50.8214,101.445 61.1547,93.1116 71.5,85.5 Z"/></g>
<g><path style="opacity:0.965" fill="#0b69f2" d="M 76.5,99.5 C 84.1667,99.5 91.8333,99.5 99.5,99.5C 99.9175,100.222 100.584,100.722 101.5,101C 90.723,109.377 80.3897,118.211 70.5,127.5C 64.5,127.5 58.5,127.5 52.5,127.5C 52.1583,126.662 51.4916,126.328 50.5,126.5C 60.644,117.864 70.9773,109.364 81.5,101C 79.6183,100.802 77.9516,100.302 76.5,99.5 Z"/></g>
<g><path style="opacity:0.994" fill="#0a75f4" d="M 68.5,96.5 C 68.5,97.5 68.5,98.5 68.5,99.5C 71.1667,99.5 73.8333,99.5 76.5,99.5C 77.9516,100.302 79.6183,100.802 81.5,101C 70.9773,109.364 60.644,117.864 50.5,126.5C 47.1012,125.984 43.7679,125.15 40.5,124C 38.5743,123.578 37.5743,122.411 37.5,120.5C 38.9217,120.291 40.255,119.791 41.5,119C 50.3732,111.289 59.3732,103.789 68.5,96.5 Z"/></g>
<g><path style="opacity:0.967" fill="#0c60f2" d="M 99.5,99.5 C 103.846,99.3343 108.179,99.501 112.5,100C 114.82,101.488 114.987,103.321 113,105.5C 102.637,116.594 90.1366,123.927 75.5,127.5C 73.8333,127.5 72.1667,127.5 70.5,127.5C 80.3897,118.211 90.723,109.377 101.5,101C 100.584,100.722 99.9175,100.222 99.5,99.5 Z"/></g>
</svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@@ -288,6 +288,15 @@ export const ApiProjectConfig: Record<string, ApiProjectType> = {
},
sort: 33,
},
edgeone: {
name: "Edgeone",
icon: "edgeone",
type: ["host", "dns"],
hostRelated: {
sslcenter: { name: "Edgeone" }
},
sort: 38,
},
plugin: {
name: "插件",
icon: "plugin",

View File

@@ -183,6 +183,32 @@
.n-data-table .n-empty__description .n-button__content {
color: #f4d1b4;
}
.n-data-table {
.n-checkbox {
&.n-checkbox--checked,
&.n-checkbox--indeterminate {
.n-checkbox-box {
background-color: #f4d1b4;
}
.n-checkbox-box__border {
border-color: #f4d1b4;
box-shadow: none;
}
}
&:hover,
&:active,
&:focus {
.n-checkbox-box__border {
border-color: #f4d1b4;
}
}
&:focus {
.n-checkbox-box__border {
box-shadow: 0 0 0 2px rgba(244, 209, 180, 0.3)
}
}
}
}
.n-base-select-menu {
background-color: #1c1c1c;
.n-base-select-option--pending::before {

View File

@@ -5,6 +5,7 @@ export interface CertListParams {
p?: number
limit?: number
search?: string
status?: number
}
/** 证书项 */

View File

@@ -1341,6 +1341,18 @@ export const useApiFormController = (
}),
);
break;
case "edgeone":
items.push(
useFormInput("SecretId", "config.secret_id", {
allowInput: noSideSpace,
}),
useFormInput("SecretKey", "config.secret_key", {
type: "password",
showPasswordOn: "click",
allowInput: noSideSpace,
})
);
break;
case "plugin":
// 插件名称选择器
items.push(
@@ -1416,9 +1428,13 @@ export const useApiFormController = (
if (pluginConfig.config === undefined || pluginConfig.config === null) {
pluginConfig.config = '';
} else if (typeof pluginConfig.config === 'object') {
// 空对象直接设为空字符串否则尝试JSON序列化过滤回车和空格
if (Object.keys(pluginConfig.config).length === 0) {
pluginConfig.config = '';
// 空对象时,根据插件配置生成默认的空值对象
if (Object.keys(pluginConfig.config).length === 0 && selectedPlugin?.config) {
const defaultConfig: Record<string, string> = {};
selectedPlugin.config.forEach(configItem => {
defaultConfig[configItem.name] = '';
});
pluginConfig.config = JSON.stringify(defaultConfig);
} else {
try {
// 不使用缩进生成紧凑的JSON字符串
@@ -1869,29 +1885,36 @@ export const useApiFormController = (
param: UpdateAccessParams | AddAccessParams
): Promise<void> => {
try {
// 调整config格式移除mode字段保持与原始格式一致
let finalConfig;
if (typeof param.config.config === 'string') {
// 自定义模式直接使用字符串形式的config避免双重序列化
finalConfig = {
name: param.config.name,
config: JSON.parse(param.config.config) // 先解析字符串为对象
};
let data: UpdateAccessParams<string> | AddAccessParams<string>;
if (param.type === "plugin") {
let finalConfig;
if (typeof param.config.config === 'string') {
finalConfig = {
name: param.config.name,
config: JSON.parse(param.config.config)
};
} else {
finalConfig = {
name: param.config.name,
config: param.config.config
};
}
data = {
...param,
config: JSON.stringify(finalConfig),
} as UpdateAccessParams<string>;
} else {
// 默认模式正常处理对象形式的config
finalConfig = {
name: param.config.name,
config: param.config.config
};
data = {
...param,
config: JSON.stringify(param.config),
} as UpdateAccessParams<string>;
}
const data = {
...param,
config: JSON.stringify(finalConfig),
} as UpdateAccessParams<string>;
if ("id" in param) {
const { id, name, config } = data; // 解构出 id, name, config
if ("id" in data) {
const { id, name, config } = data;
await updateExistingAccess({
id: id.toString(),
name,

View File

@@ -467,6 +467,27 @@ export default defineComponent({
},
)
// 监听 provider 变化,重置配置模式和跳过选项
watch(
() => param.value.provider,
(newProvider, oldProvider) => {
if (newProvider !== oldProvider) {
// 重置配置模式为默认
configMode.value = 'default'
param.value.configMode = 'default'
// 重置跳过选项为 true (1)
param.value.skip = 1
// 如果是插件类型,清空插件相关字段
if (newProvider !== 'plugin') {
param.value.action = ''
param.value.params = {}
currentDynamicParams.value = []
pluginActionOptions.value = []
}
}
},
)
// 监听配置模式变化处理params数据格式转换
watch(
() => configMode.value,

View File

@@ -1,7 +1,11 @@
import { useHistoryController } from '@autoDeploy/useController'
import BaseComponent from '@components/BaseLayout'
import { $t } from '@locales/index'
import { NButton } from 'naive-ui'
import { NButton, NSelect } from 'naive-ui'
const batchActionOptions = [
{ label: '删除', value: 'delete' },
]
/**
* 工作流执行历史模态框组件
@@ -15,7 +19,7 @@ export default defineComponent({
},
},
setup(props) {
const { TableComponent, PageComponent, fetch } = useHistoryController(props.id)
const { TableComponent, PageComponent, fetch, checkedRowKeysRef, handleCheck, batchActionRef, handleBatchAction } = useHistoryController(props.id)
onMounted(() => {
fetch()
})
@@ -30,8 +34,30 @@ export default defineComponent({
</NButton>
</div>
),
content: () => <TableComponent />,
content: () => <TableComponent
checkedRowKeys={checkedRowKeysRef.value}
onUpdateCheckedRowKeys={handleCheck}
rowKey={(row: any) => row.id.toString()}
/>,
footerRight: () => <PageComponent />,
footerLeft: () => (
<div class="flex items-center gap-3">
<NSelect
v-model:value={batchActionRef.value}
options={batchActionOptions}
style={{ width: '120px' }}
disabled={checkedRowKeysRef.value.length === 0}
size="small"
/>
<NButton
size="small"
class="gradient-primary-btn"
disabled={checkedRowKeysRef.value.length === 0} type="primary" onClick={handleBatchAction}>
</NButton>
<span class="text-gray-500"> {checkedRowKeysRef.value.length} </span>
</div>
),
}}
></BaseComponent>
</div>

View File

@@ -51,6 +51,8 @@ const {
deleteExistingEab,
resetCaForm,
copyExistingWorkflow,
deleteExistingHistoryHandle,
deleteBatchHistory,
} = useStore();
const {
isEdit,
@@ -548,6 +550,35 @@ export const useAddWorkflowController = () => {
* @returns {Object} 返回工作流历史记录业务逻辑控制器实例
*/
export const useHistoryController = (id: string) => {
const checkedRowKeysRef = ref<(string | number)[]>([])
const batchActionRef = ref<string>('delete')
const handleCheck: (rowKeys: (string | number)[]) => void = (rowKeys) => {
checkedRowKeysRef.value = rowKeys
}
const handleBatchAction = async () => {
if (checkedRowKeysRef.value.length === 0) {
return
}
if (batchActionRef.value === 'delete') {
useDialog({
title: '批量删除执行历史',
content: `确定要删除选中的 ${checkedRowKeysRef.value.length} 条执行历史吗?`,
onPositiveClick: async () => {
try {
const ids_param = checkedRowKeysRef.value.join(',')
await deleteBatchHistory(ids_param)
checkedRowKeysRef.value = []
await fetch()
} catch (error) {
handleError(error)
}
},
})
}
}
/**
* @description 工作流历史详情
* @param {number} workflowId - 工作流ID
@@ -561,6 +592,20 @@ export const useHistoryController = (id: string) => {
});
};
const handleViewHistoryDel = async (workflowId: string) => {
useDialog({
title: '删除执行历史',
content: '确认删除选中的执行历史吗?此操作不可恢复。',
onPositiveClick: async () => {
try {
await deleteExistingHistoryHandle(workflowId)
await fetch()
} catch (error) {
handleError(error)
}
},
})
};
/**
* @description 停止工作流执行
* @param {WorkflowHistoryItem} historyItem - 工作流历史记录项
@@ -583,6 +628,9 @@ export const useHistoryController = (id: string) => {
* @returns {DataTableColumn<WorkflowHistoryItem>[]} 返回表格列配置数组
*/
const createColumns = (): DataTableColumn<WorkflowHistoryItem>[] => [
{
type: 'selection',
},
{
title: $t("t_4_1745227838558"),
key: "create_time",
@@ -648,6 +696,16 @@ export const useHistoryController = (id: string) => {
>
{$t("t_12_1745227838814")}
</NButton>
<NButton
size="tiny"
strong
secondary
type="error"
class="table-action-btn"
onClick={() => handleViewHistoryDel(row.id.toString())}
>
</NButton>
</NSpace>
),
},
@@ -671,6 +729,11 @@ export const useHistoryController = (id: string) => {
PageComponent,
loading,
fetch,
checkedRowKeysRef,
handleCheck,
batchActionRef,
handleBatchAction,
deleteBatchHistory
};
};

View File

@@ -7,6 +7,7 @@ import {
enableWorkflow,
stopWorkflow,
addWorkflow,
deleteExistingHistory
} from '@/api/workflow'
import { getEabList, addEab, deleteEab, updateEab } from '@/api/access'
import { useError } from '@baota/hooks/error'
@@ -135,6 +136,38 @@ export const useWorkflowStore = defineStore('workflow-store', () => {
}
}
/**
* 删除执行历史
* @description 删除指定ID的执行历史
* @param {string} workflowId - 工作流ID
* @returns {Promise<boolean>} 是否删除成功
*/
const deleteExistingHistoryHandle = async (workflowId: string) => {
try {
const { message, fetch } = deleteExistingHistory({ id: workflowId })
message.value = true
await fetch()
} catch (error) {
handleError(error)
}
}
/**
* 批量删除执行历史
* @description 批量删除指定ID的执行历史
* @param {string[]} ids - 执行历史ID数组
* @returns {Promise<void>}
*/
const deleteBatchHistory = async (ids: any) => {
try {
const { message, fetch } = deleteExistingHistory({ id: ids })
message.value = true
await fetch()
} catch (error) {
handleError(error)
throw error
}
}
/**
* 复制工作流
* @description 复制指定的工作流配置
@@ -277,6 +310,8 @@ export const useWorkflowStore = defineStore('workflow-store', () => {
updateExistingEab,
deleteExistingEab,
resetCaForm,
deleteExistingHistoryHandle,
deleteBatchHistory,
}
})

View File

@@ -1,4 +1,4 @@
import { NInput, NButton } from 'naive-ui'
import { NInput, NButton, NSelect } from 'naive-ui'
import { useTheme, useThemeCssVar } from '@baota/naive-ui/theme'
import { Search } from '@vicons/carbon'
import { $t } from '@locales/index'
@@ -7,16 +7,26 @@ import { useController } from './useController'
import BaseComponent from '@components/BaseLayout'
import EmptyState from '@components/TableEmptyState'
const batchActionOptions = [
{ label: '删除', value: 'delete' },
]
/**
* 证书管理组件
*/
export default defineComponent({
name: 'CertManage',
setup() {
const { TableComponent, PageComponent, SearchComponent, openUploadModal, getRowClassName } = useController()
const { TableComponent, PageComponent, SearchComponent, openUploadModal, getRowClassName, checkedRowKeysRef, handleCheck, batchActionRef, handleBatchAction, statusFilterRef } = useController()
const cssVar = useThemeCssVar(['contentPadding', 'borderColor', 'headerHeight', 'iconColorHover'])
const handleFiltersChange = (filters: any, column: any) => {
if (column.key === 'end_day') {
statusFilterRef.value = filters.end_day || null
}
}
return () => (
<div class="h-full flex flex-col" style={cssVar.value}>
<div class="mx-auto max-w-[1600px] w-full p-6">
@@ -31,8 +41,11 @@ export default defineComponent({
content: () => (
<div class="rounded-lg">
<TableComponent
size="medium"
checkedRowKeys={checkedRowKeysRef.value}
onUpdateCheckedRowKeys={handleCheck}
rowClassName={getRowClassName}
rowKey={(row: any) => row.id.toString()}
onUpdateFilters={handleFiltersChange}
v-slots={{
empty: () => <EmptyState addButtonText={$t('t_1_1747047213009')} onAddClick={openUploadModal} />,
}}
@@ -44,6 +57,23 @@ export default defineComponent({
<PageComponent />
</div>
),
footerLeft: () => (
<div class="mt-4 flex items-center gap-3">
<NSelect
v-model:value={batchActionRef.value}
options={batchActionOptions}
style={{ width: '120px' }}
disabled={checkedRowKeysRef.value.length === 0}
size="small"
/>
<NButton
size="small"
disabled={checkedRowKeysRef.value.length === 0} type="primary" onClick={handleBatchAction}>
</NButton>
<span class="text-gray-500"> {checkedRowKeysRef.value.length} </span>
</div>
),
}}
></BaseComponent>
</div>

View File

@@ -20,7 +20,7 @@ import type { CertItem, CertListParams } from '@/types/cert'
const { handleError } = useError()
const { useFormTextarea } = useFormHooks()
const { fetchCertList, downloadExistingCert, deleteExistingCert, uploadNewCert, uploadForm, resetUploadForm } =
const { fetchCertList, downloadExistingCert, deleteExistingCert, uploadNewCert, uploadForm, resetUploadForm, deleteBatchCerts } =
useStore()
const { confirm } = useModalHooks()
/**
@@ -64,11 +64,43 @@ const calculateRemainingDays = (cert: CertItem): number | null => {
* @returns {object} 返回controller对象
*/
export const useController = () => {
const checkedRowKeysRef = ref<(string | number)[]>([])
const batchActionRef = ref<string>('delete')
const statusFilterRef = ref<number | null>(null)
const handleCheck: (rowKeys: (string | number)[]) => void = (rowKeys) => {
checkedRowKeysRef.value = rowKeys
}
const handleBatchAction = async () => {
if (checkedRowKeysRef.value.length === 0) {
return
}
if (batchActionRef.value === 'delete') {
useDialog({
title: '批量删除证书',
content: `确定要删除选中的 ${checkedRowKeysRef.value.length} 个证书吗?`,
onPositiveClick: async () => {
try {
await deleteBatchCerts(checkedRowKeysRef.value)
checkedRowKeysRef.value = []
await fetch()
} catch (error) {
handleError(error)
}
},
})
}
}
/**
* @description 创建表格列配置
* @returns {DataTableColumns<CertItem>} 返回表格列配置数组
*/
const createColumns = (): DataTableColumns<CertItem> => [
{
type: 'selection',
},
{
title: $t('t_17_1745227838561'),
key: 'domains',
@@ -95,6 +127,20 @@ export const useController = () => {
title: $t('t_19_1745227839107'),
key: 'end_day',
width: 100,
filterOptions: [
{ label: '已过期', value: -1 },
{ label: '即将过期', value: 1 },
{ label: '正常', value: 2 },
],
filterMultiple: false,
filter: (value: number, row: CertItem) => {
const endDay = calculateRemainingDays(row)
if (endDay === null) return false
if (value === -1) return endDay <= 0
if (value === 1) return endDay > 0 && endDay < 30
if (value === 2) return endDay >= 30
return true
},
render: (row: CertItem) => {
const endDay = calculateRemainingDays(row)
@@ -186,10 +232,11 @@ export const useController = () => {
const { TableComponent, PageComponent, loading, param, data, fetch } = useTable<CertItem, CertListParams>({
config: createColumns(),
request: fetchCertList,
defaultValue: { p: 1, limit: 10, search: '' },
defaultValue: { p: 1, limit: 10, search: '', status: 0 },
alias: { page: 'p', pageSize: 'limit' },
watchValue: ['p', 'limit'],
watchValue: ['p', 'limit', 'status'],
storage: 'certManagePageSize',
rowKey: (row) => row.id.toString(),
})
// 搜索实例
@@ -200,6 +247,14 @@ export const useController = () => {
},
})
// 监听筛选状态变化
watch(
() => statusFilterRef.value,
(newStatus) => {
param.value.status = newStatus === null ? 0 : newStatus
}
)
/**
* @description 打开上传证书弹窗
*/
@@ -264,6 +319,11 @@ export const useController = () => {
getRowClassName,
openUploadModal,
openViewModal,
checkedRowKeysRef,
handleCheck,
batchActionRef,
handleBatchAction,
statusFilterRef,
}
}

View File

@@ -90,6 +90,24 @@ export const useCertManageStore = defineStore('cert-manage-store', () => {
}
}
/**
* 批量删除证书
* @description 批量删除指定ID的证书
* @param {string[]} ids - 证书ID数组
* @returns {Promise<void>}
*/
const deleteBatchCerts = async (ids: any) => {
try {
const ids_param = ids.join(',')
const { message, fetch } = deleteCert({ id: ids_param })
message.value = true
await fetch()
} catch (error) {
handleError(error)
throw error
}
}
/**
* @description 重置上传证书表单
*/
@@ -108,6 +126,7 @@ export const useCertManageStore = defineStore('cert-manage-store', () => {
downloadExistingCert,
uploadNewCert,
deleteExistingCert,
deleteBatchCerts,
resetUploadForm,
}
})