From 6ca7fb0a69427dff472f9c64d37a3bfef1dbd232 Mon Sep 17 00:00:00 2001 From: caiyuchao Date: Thu, 4 Sep 2025 17:16:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E4=BF=AE=E6=94=B9lic?= =?UTF-8?q?ense=E7=94=B3=E8=AF=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/license/license/data.ts | 24 +++++--- .../views/license/license/generate/index.vue | 6 +- .../src/views/license/license/index.vue | 20 +++++-- .../views/license/license/modules/form.vue | 56 ++++++++++++------- .../src/views/license/project/data.ts | 6 +- 5 files changed, 71 insertions(+), 41 deletions(-) diff --git a/apps/web-antd/src/views/license/license/data.ts b/apps/web-antd/src/views/license/license/data.ts index 3297dde..f03031f 100644 --- a/apps/web-antd/src/views/license/license/data.ts +++ b/apps/web-antd/src/views/license/license/data.ts @@ -7,6 +7,7 @@ import type { DescriptionItemSchema } from '#/components/description'; import { h, ref } from 'vue'; +import { useAccess } from '@vben/access'; import { formatDate, formatDateTime } from '@vben/utils'; import dayjs, { Dayjs } from 'dayjs'; @@ -20,6 +21,7 @@ import { DictTag } from '#/components/dict-tag'; import { $t } from '#/locales'; import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils'; +const { hasAccessByRoles } = useAccess(); const customerList = ref([]); const projectList = ref([]); export const formData = ref(); @@ -105,7 +107,7 @@ export function useFormSchema(): VbenFormSchema[] { label: 'SN', component: 'Input', componentProps: { - disabled: true, + // disabled: true, }, dependencies: { trigger(values, form) { @@ -125,15 +127,19 @@ export function useFormSchema(): VbenFormSchema[] { }, // 只有指定的字段改变时,才会触发 triggerFields: ['customerId', 'projectId', 'id'], + disabled: () => !hasAccessByRoles(['license_admin']), }, - rules: z.string().refine( - async (value: string) => { - return await isLicenseSnUnique(value, formData.value?.id); - }, - (value) => ({ - message: $t('ui.formRules.alreadyExists', ['SN', value]), - }), - ), + rules: z + .string() + .max(8, $t('ui.formRules.maxLength', ['SN', 8])) + .refine( + async (value: string) => { + return await isLicenseSnUnique(value, formData.value?.id); + }, + (value) => ({ + message: $t('ui.formRules.alreadyExists', ['SN', value]), + }), + ), }, { fieldName: 'expiryDate', diff --git a/apps/web-antd/src/views/license/license/generate/index.vue b/apps/web-antd/src/views/license/license/generate/index.vue index f19158d..023603b 100644 --- a/apps/web-antd/src/views/license/license/generate/index.vue +++ b/apps/web-antd/src/views/license/license/generate/index.vue @@ -106,10 +106,6 @@ async function onDownload() { if (!formData.value?.fileUrl) { return; } - const fileName = `${formData.value.fileUrl?.slice( - Math.max(0, formData.value.fileUrl.lastIndexOf('/') + 1), - formData.value.fileUrl.lastIndexOf('_'), - )}.tar.gz`; const hideLoading = message.loading({ content: '下载中...', @@ -121,7 +117,7 @@ async function onDownload() { const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; - link.download = fileName; + link.download = formData.value.fileUrl; link.click(); window.URL.revokeObjectURL(url); } finally { diff --git a/apps/web-antd/src/views/license/license/index.vue b/apps/web-antd/src/views/license/license/index.vue index 251462b..58d3da3 100644 --- a/apps/web-antd/src/views/license/license/index.vue +++ b/apps/web-antd/src/views/license/license/index.vue @@ -73,11 +73,6 @@ function onHistory(row: LicenseApi.License) { /** 下载License */ async function onDownload(row: LicenseApi.License) { - const fileName = `${row.fileUrl?.slice( - Math.max(0, row.fileUrl.lastIndexOf('/') + 1), - row.fileUrl.lastIndexOf('_'), - )}.tar.gz`; - const hideLoading = message.loading({ content: '下载中...', key: 'action_key_msg', @@ -88,7 +83,7 @@ async function onDownload(row: LicenseApi.License) { const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; - link.download = fileName; + link.download = row.fileUrl; link.click(); window.URL.revokeObjectURL(url); } finally { @@ -101,6 +96,11 @@ function onReapply(row: LicenseApi.License) { formModalApi.setData(row).open(); } +/** 修改License */ +function onEdit(row: LicenseApi.License) { + formModalApi.setData({ ...row, action: 1 }).open(); +} + /** 删除License */ async function onDelete(row: LicenseApi.License) { const hideLoading = message.loading({ @@ -253,6 +253,14 @@ const [Grid, gridApi] = useVbenVxeGrid({ auth: ['license:license:query'], onClick: onHistory.bind(null, row), }, + { + label: $t('common.edit'), + type: 'link', + ifShow: + row.status === 4 || row.status === 1 || row.dataType === 1, + auth: ['license:license:update'], + onClick: onEdit.bind(null, row), + }, ]" /> diff --git a/apps/web-antd/src/views/license/license/modules/form.vue b/apps/web-antd/src/views/license/license/modules/form.vue index 106e5ea..283c878 100644 --- a/apps/web-antd/src/views/license/license/modules/form.vue +++ b/apps/web-antd/src/views/license/license/modules/form.vue @@ -14,6 +14,7 @@ import { createLicense, getLicense, reapplyLicense, + updateLicense, } from '#/api/license/license'; import { $t } from '#/locales'; import { DICT_TYPE, getDictOptions } from '#/utils'; @@ -34,13 +35,25 @@ const state = reactive({ const neCodeRef = ref(); const getTitle = computed(() => { - return formData.value?.id - ? $t('license.reapplyAction', ['License']) - : $t('license.applyAction', ['License']); + if (formData.value?.id) { + if (formData.value?.action === 1) { + return $t('ui.actionTitle.edit', ['License']); + } + return $t('license.reapplyAction', ['License']); + } else { + return $t('license.applyAction', ['License']); + } }); const getConfirmText = computed(() => { - return formData.value?.id ? $t('license.reapply') : $t('license.apply'); + if (formData.value?.id) { + if (formData.value?.action === 1) { + return $t('page.action.confirm'); + } + return $t('license.reapply'); + } else { + return $t('license.apply'); + } }); const [Form, formApi] = useVbenForm({ @@ -92,12 +105,19 @@ const [Modal, modalApi] = useVbenModal({ const data = (await formApi.getValues()) as LicenseApi.License; data.neList = state.checkedList; data.neCodeList = state.neCodeList; + const action = formData.value?.action || 0; try { - await (formData.value?.id ? reapplyLicense(data) : createLicense(data)); + if (formData.value?.id) { + await (action === 1 ? updateLicense(data) : reapplyLicense(data)); + } else { + await createLicense(data); + } // 关闭并提示 await modalApi.close(); emit('success'); - message.success($t('license.applySuccess'), 3); + action === 1 + ? message.success($t('ui.actionMessage.operationSuccess')) + : message.success($t('license.applySuccess'), 3); } finally { modalApi.unlock(); } @@ -114,16 +134,25 @@ const [Modal, modalApi] = useVbenModal({ } if (data.id) { modalApi.setState({ loading: true }); + const action = data.action || 0; // 确保 action 字段存在 + formData.value = { ...data, action }; data = await getLicense(data.id); + data.action = action; // 保留 action 字段 } // 处理数据 data.expiryDate = data.expiryDate ? data.expiryDate.toString() : ''; // 设置到 values formData.value = data; state.checkedList = data.neList || []; + state.neCodeList = data.neCodeList || [ { neList: [], activationCode: '', id: 1 }, ]; + if (state.neCodeList.length > 1) { + state.neCodeList = state.neCodeList.filter( + (item) => item.neList && item.neList.length > 0, + ); + } await formApi.setValues(formData.value); modalApi.setState({ loading: false }); }, @@ -165,21 +194,10 @@ const addNeCode = () => { neList: [], activationCode: '', id: nextId++, + fileUrl: '', }); }; -const availableOptions = (groupIdx: number) => { - // 其他分组已选标签 - const otherSelected = new Set( - state.neCodeList - .filter((_, idx) => idx !== groupIdx) - .flatMap((g) => g.neList), - ); - const aaaa = options.value?.map((item) => ({ - ...item, - options: item.options.filter( - (option: any) => !otherSelected.has(option.value), - ), - })); +const availableOptions = () => { return options.value; }; diff --git a/apps/web-antd/src/views/license/project/data.ts b/apps/web-antd/src/views/license/project/data.ts index 8a4a2bd..ec275c2 100644 --- a/apps/web-antd/src/views/license/project/data.ts +++ b/apps/web-antd/src/views/license/project/data.ts @@ -525,12 +525,14 @@ export function useGridColumns( { field: 'commentNum', title: $t('project.commentNum'), - minWidth: 90, + sortable: true, + minWidth: 100, }, { field: 'applyCount', title: $t('license.applyCount'), - minWidth: 120, + sortable: true, + minWidth: 130, }, { field: 'updateTime',