perf: 流水线、监控站点支持导出

This commit is contained in:
xiaojunnuo
2026-06-04 23:43:25 +08:00
parent c0df8be832
commit 99fd3083f2
8 changed files with 285 additions and 26 deletions
@@ -82,6 +82,7 @@ export default {
pipelineContent: "Pipeline Content",
scheduledTaskCount: "Scheduled Task Count",
deployTaskCount: "Deployment Task Count",
certDomains: "Certificate Domains",
remainingValidity: "Remaining Validity",
effectiveTime: "Effective time",
expiryTime: "Expiry Time",
@@ -41,6 +41,7 @@ export default {
pi: {
validTime: "Piepline Valid Time",
validTimeHelper: "Not filled in means permanent validity",
permanentValid: "Permanent",
},
types: {
certApply: "Cert Apply",
@@ -86,6 +86,7 @@ export default {
pipelineContent: "流水线内容",
scheduledTaskCount: "定时任务数",
deployTaskCount: "部署任务数",
certDomains: "证书域名",
remainingValidity: "到期剩余",
effectiveTime: "生效时间",
expiryTime: "过期时间",
@@ -41,6 +41,7 @@ export default {
pi: {
validTime: "流水线有效期",
validTimeHelper: "不填则为永久有效",
permanentValid: "永久有效",
},
types: {
certApply: "证书申请",
@@ -1,4 +1,4 @@
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, useUi } from "@fast-crud/fast-crud";
import { AddReq, ColumnProps, CreateCrudOptionsProps, CreateCrudOptionsRet, DataFormatterContext, DelReq, dict, EditReq, UserPageQuery, UserPageRes, useUi } from "@fast-crud/fast-crud";
import { Modal, notification } from "ant-design-vue";
import dayjs from "dayjs";
import { computed, ref } from "vue";
@@ -75,6 +75,17 @@ export default function ({ crudExpose, context: { selectedRowKeys, openCertApply
const projectStore = useProjectStore();
const { myProjectDict } = useDicts();
const DEFAULT_WILL_EXPIRE_DAYS = settingStore.sysPublic.defaultWillExpireDays || settingStore.sysPublic.defaultCertRenewDays || 15;
const pipelineTypeDictData = [
{ value: "cert", label: t("certd.types.certApply") },
{ value: "cert_upload", label: t("certd.types.certUpload") },
{ value: "custom", label: t("certd.types.custom") },
{ value: "template", label: t("certd.types.template") },
{ value: "cert_auto", label: t("certd.types.certApply") },
];
const disabledDictData = [
{ value: false, label: t("certd.fields.enabledLabel") },
{ value: true, label: t("certd.fields.disabledLabel") },
];
function onDialogOpen(opt: any) {
const searchForm = crudExpose.getSearchValidatedFormData();
@@ -84,6 +95,79 @@ export default function ({ crudExpose, context: { selectedRowKeys, openCertApply
};
}
function getRecordValue(row: any, key: string) {
return key.split(".").reduce((target, item) => target?.[item], row);
}
function findDictLabel(data: any[], value: any) {
return data.find(item => item.value === value)?.label ?? value;
}
function formatValidTime(value: any) {
if (!value || value <= 0) {
return t("certd.pi.permanentValid");
}
if (value < Date.now()) {
return t("certd.hasExpired");
}
return dayjs(value).format("YYYY-MM-DD");
}
function formatRemainingValidity(lastVars: any) {
const expiresTime = lastVars?.certExpiresTime;
if (!expiresTime) {
return "-";
}
const leftDays = dayjs(expiresTime).diff(dayjs(), "day");
if (leftDays < 0) {
return t("certd.hasExpired");
}
return `${leftDays}${t("certd.days")}`;
}
function formatListValue(value: any) {
if (Array.isArray(value)) {
return value.join(",");
}
return value ?? "";
}
function exportColumnFilter(col: ColumnProps) {
if (!col.key || ["_index", "_selection", "rowHandle"].includes(col.key)) {
return false;
}
if (col.key === "lastVars.certDomains") {
return true;
}
return col.show !== false;
}
function exportDataFormatter(opts: DataFormatterContext) {
const { row, originalRow, col, exportCol } = opts;
const key = col.key;
const value = getRecordValue(originalRow, key);
if (key === "validTime") {
row[key] = formatValidTime(value);
} else if (key === "lastVars") {
row[key] = formatRemainingValidity(value);
} else if (key === "lastVars.certDomains") {
row[key] = formatListValue(value);
} else if (key === "status") {
row[key] = statusUtil.get(value)?.label ?? value;
} else if (key === "disabled") {
row[key] = findDictLabel(disabledDictData, value);
} else if (key === "type") {
row[key] = findDictLabel(pipelineTypeDictData, value);
} else if (key.includes("Time") && value) {
row[key] = dayjs(value).format("YYYY-MM-DD HH:mm:ss");
}
if (col.width) {
exportCol.width = col.width / 10;
}
}
return {
crudOptions: {
request: {
@@ -178,6 +262,18 @@ export default function ({ crudExpose, context: { selectedRowKeys, openCertApply
confirmMessage: t("certd.table.confirmDeleteMessage"),
},
},
toolbar: {
buttons: {
export: {
show: true,
},
},
export: {
dataFrom: "search",
columnFilter: exportColumnFilter,
dataFormatter: exportDataFormatter,
},
},
tabs: {
name: "groupId",
show: true,
@@ -419,6 +515,19 @@ export default function ({ crudExpose, context: { selectedRowKeys, openCertApply
width: 150,
},
},
"lastVars.certDomains": {
title: t("certd.fields.certDomains"),
type: "text",
form: {
show: false,
},
column: {
width: 260,
show: false,
ellipsis: true,
showTitle: true,
},
},
"lastVars.certEffectiveTime": {
title: t("certd.fields.effectiveTime"),
search: {
@@ -503,10 +612,7 @@ export default function ({ crudExpose, context: { selectedRowKeys, openCertApply
},
},
dict: dict({
data: [
{ value: false, label: t("certd.fields.enabledLabel") },
{ value: true, label: t("certd.fields.disabledLabel") },
],
data: disabledDictData,
}),
form: {
value: false,
@@ -563,13 +669,7 @@ export default function ({ crudExpose, context: { selectedRowKeys, openCertApply
col: { span: 2 },
},
dict: dict({
data: [
{ value: "cert", label: t("certd.types.certApply") },
{ value: "cert_upload", label: t("certd.types.certUpload") },
{ value: "custom", label: t("certd.types.custom") },
{ value: "template", label: t("certd.types.template") },
{ value: "cert_auto", label: t("certd.types.certApply") },
],
data: pipelineTypeDictData,
}),
form: {
show: false,
@@ -650,7 +750,7 @@ export default function ({ crudExpose, context: { selectedRowKeys, openCertApply
align: "center",
cellRender({ value }) {
if (!value || value <= 0) {
return "-";
return t("certd.pi.permanentValid");
}
if (value < Date.now()) {
return t("certd.hasExpired");
@@ -1,5 +1,5 @@
import createCrudOptionsUser from "/@/views/sys/authority/user/crud";
import { CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { ColumnProps, CreateCrudOptionsProps, CreateCrudOptionsRet, DataFormatterContext, DelReq, dict, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { message, Modal } from "ant-design-vue";
import dayjs from "dayjs";
import { ref } from "vue";
@@ -18,6 +18,77 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
};
const selectedRowKeys = ref<number[]>([]);
const pipelineTypeDictData = [
{ value: "cert", label: "证书申请" },
{ value: "cert_upload", label: "证书上传" },
{ value: "custom", label: "自定义" },
{ value: "template", label: "模板" },
{ value: "cert_auto", label: "证书申请" },
];
const disabledDictData = [
{ label: "启用", value: false, color: "green" },
{ label: "禁用", value: true, color: "red" },
];
function findDictLabel(data: any[], value: any) {
return data.find(item => item.value === value)?.label ?? value;
}
function formatValidTime(value: any) {
if (!value || value <= 0) {
return "永久有效";
}
if (value < Date.now()) {
return "已过期";
}
return dayjs(value).format("YYYY-MM-DD");
}
function getRecordValue(row: any, key: string) {
return key.split(".").reduce((target, item) => target?.[item], row);
}
function formatListValue(value: any) {
if (Array.isArray(value)) {
return value.join(",");
}
return value ?? "";
}
function exportColumnFilter(col: ColumnProps) {
if (!col.key || ["_index", "_selection", "rowHandle"].includes(col.key)) {
return false;
}
if (col.key === "lastVars.certDomains") {
return true;
}
return col.show !== false;
}
function exportDataFormatter(opts: DataFormatterContext) {
const { row, originalRow, col, exportCol } = opts;
const key = col.key;
const value = getRecordValue(originalRow, key);
if (key === "validTime") {
row[key] = formatValidTime(value);
} else if (key === "lastVars.certDomains") {
row[key] = formatListValue(value);
} else if (key === "status") {
row[key] = statusUtil.get(value)?.label ?? value;
} else if (key === "disabled") {
row[key] = findDictLabel(disabledDictData, value);
} else if (key === "type") {
row[key] = findDictLabel(pipelineTypeDictData, value);
} else if (key.includes("Time") && value) {
row[key] = dayjs(value).format("YYYY-MM-DD HH:mm:ss");
}
if (col.width) {
exportCol.width = col.width / 10;
}
}
const handleBatchDelete = () => {
if (!selectedRowKeys.value?.length) {
message.error("请先选择要删除的记录");
@@ -54,6 +125,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
},
export: {
dataFrom: "search",
columnFilter: exportColumnFilter,
dataFormatter: exportDataFormatter,
},
},
pagination: {
@@ -185,13 +258,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
},
},
dict: dict({
data: [
{ value: "cert", label: "证书申请" },
{ value: "cert_upload", label: "证书上传" },
{ value: "custom", label: "自定义" },
{ value: "template", label: "模板" },
{ value: "cert_auto", label: "证书申请" },
],
data: pipelineTypeDictData,
}),
column: {
width: 110,
@@ -236,10 +303,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
},
},
dict: dict({
data: [
{ label: "启用", value: false, color: "green" },
{ label: "禁用", value: true, color: "red" },
],
data: disabledDictData,
}),
column: {
width: 90,
@@ -273,6 +337,18 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
show: false,
},
},
"lastVars.certDomains": {
title: "证书域名",
type: "text",
column: {
width: 260,
show: false,
ellipsis: true,
},
form: {
show: false,
},
},
lastHistoryTime: {
title: "最后执行时间",
type: "datetime",
@@ -306,7 +382,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
align: "center",
cellRender({ value }) {
if (!value || value <= 0) {
return "-";
return "永久有效";
}
if (value < Date.now()) {
return <span style={{ color: "red" }}></span>;