diff --git a/apps/web-antd/src/api/license/license/index.ts b/apps/web-antd/src/api/license/license/index.ts index 3017399..806f4fa 100644 --- a/apps/web-antd/src/api/license/license/index.ts +++ b/apps/web-antd/src/api/license/license/index.ts @@ -16,6 +16,7 @@ export namespace LicenseApi { userNumber: number; // 用户数 ranNumber: number; // 基站数 activationCode: string; // 激活码 + fileUrl: string; // 激活码 licenseContent: string; // License内容 applicant: number; // 申请人 applicationTime: Dayjs | string; // 申请时间 @@ -54,6 +55,11 @@ export function applyLicense(data: LicenseApi.License) { return requestClient.put('/license/license/apply', data); } +/** 生成License */ +export function generateLicense(id: number) { + return requestClient.get(`/license/license/generate?id=${id}`); +} + /** 删除License */ export function deleteLicense(id: number) { return requestClient.delete(`/license/license/delete?id=${id}`); diff --git a/apps/web-antd/src/locales/langs/en-US/license.json b/apps/web-antd/src/locales/langs/en-US/license.json index 38551a0..e4cb681 100644 --- a/apps/web-antd/src/locales/langs/en-US/license.json +++ b/apps/web-antd/src/locales/langs/en-US/license.json @@ -18,5 +18,13 @@ "licenseAdminHelp": "Assigned to persons who have permission to generate licenses, and send email reminders", "apply": "Apply", "applyAction": "Apply For {0}", - "applicationTime": "Application Time" + "applicationTime": "Application Time", + "generate": "Generate", + "generating": "Generating...", + "generateSuccess": "Generation Successful", + "isDownload": "Do you want to download this file [{0}]?", + "download": "Download", + "downloadFailed": "Download failed, please try again later", + "licenseFile": "License File", + "applySuccess": "Application successful, email reminder sent, please wait for approval" } diff --git a/apps/web-antd/src/locales/langs/zh-CN/license.json b/apps/web-antd/src/locales/langs/zh-CN/license.json index 67d006f..9b83d41 100644 --- a/apps/web-antd/src/locales/langs/zh-CN/license.json +++ b/apps/web-antd/src/locales/langs/zh-CN/license.json @@ -18,5 +18,13 @@ "licenseAdminHelp": "指派给有权限生成License的人员,并且发送邮件提醒", "apply": "申请", "applyAction": "申请{0}", - "applicationTime": "申请时间" + "applicationTime": "申请时间", + "generate": "生成", + "generating": "正在生成中...", + "generateSuccess": "生成成功", + "isDownload": "是否下载该文件【{0}】?", + "download": "下载", + "downloadFailed": "下载失败,请稍后重试", + "licenseFile": "License文件", + "applySuccess": "申请成功,已发送邮件提醒,请等待审核" } diff --git a/apps/web-antd/src/views/license/license/data.ts b/apps/web-antd/src/views/license/license/data.ts index e3368cb..ae0f3e3 100644 --- a/apps/web-antd/src/views/license/license/data.ts +++ b/apps/web-antd/src/views/license/license/data.ts @@ -1,19 +1,26 @@ import type { VbenFormSchema } from '#/adapter/form'; import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { LicenseApi } from '#/api/license/license'; +import type { DescriptionItemSchema } from '#/components/description'; -import { ref } from 'vue'; +import { h, ref } from 'vue'; import { useAccess } from '@vben/access'; +import { downloadFileFromBlobPart, formatDateTime } from '@vben/utils'; + +import { Button, message } from 'ant-design-vue'; import { z } from '#/adapter/form'; import { getCustomerList } from '#/api/license/customer'; import { isLicenseSnUnique } from '#/api/license/license'; import { getProjectList } from '#/api/license/project'; import { getLicenseAdminList, getSimpleUserList } from '#/api/system/user'; +import { DictTag, DictTagGroup } from '#/components/dict-tag'; import { $t } from '#/locales'; import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils'; +// import Button from '../../../../../../packages/@core/ui-kit/shadcn-ui/src/components/button/button.vue'; + const { hasAccessByCodes } = useAccess(); let projectList = await getProjectList({}); const customerList = await getCustomerList(); @@ -474,7 +481,29 @@ export function useGridColumns( { code: 'apply', text: $t('license.apply'), - show: hasAccessByCodes(['license:license:apply']), + show: (values: LicenseApi.License) => { + return ( + hasAccessByCodes(['license:license:apply']) && + values.status === 0 + ); + }, + }, + { + code: 'generate', + text: $t('license.generate'), + show: (values: LicenseApi.License) => { + return ( + hasAccessByCodes(['license:license:generate']) && + values.status === 1 + ); + }, + }, + { + code: 'download', + text: $t('license.download'), + show: (values: LicenseApi.License) => { + return values.status === 2; + }, }, { code: 'delete', @@ -485,3 +514,123 @@ export function useGridColumns( }, ]; } + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'customerName', + label: $t('license.customer'), + }, + { + field: 'projectName', + label: $t('license.project'), + }, + { + field: 'serialNo', + label: 'SN', + }, + { + field: 'expiryDate', + label: $t('license.expiryDate'), + content: (data) => { + return formatDateTime(data?.expiryDate) as string; + }, + }, + { + field: 'neList', + label: $t('license.neList'), + content: (data) => { + return h(DictTagGroup, { + type: DICT_TYPE.LIC_NE_LIST, + value: data.neList, + }); + }, + }, + { + field: 'userNumber', + label: $t('license.userNumber'), + }, + { + field: 'ranNumber', + label: $t('license.ranNumber'), + }, + { + field: 'applicantName', + label: $t('license.applicant'), + }, + { + field: 'applicationTime', + label: $t('license.applicationTime'), + content: (data) => { + return formatDateTime(data?.applicationTime) as string; + }, + }, + { + field: 'status', + label: $t('license.status'), + content: (data) => { + return h(DictTag, { + type: DICT_TYPE.LIC_LICENSE_STATUS, + value: data.status, + }); + }, + }, + { + field: 'remark', + label: $t('license.remark'), + }, + { + field: 'fileUrl', + label: $t('license.licenseFile'), + hidden: (data) => data.status !== 2, + content: (data) => { + const fileName = `${data.fileUrl?.slice( + Math.max(0, data.fileUrl.lastIndexOf('/') + 1), + data.fileUrl.lastIndexOf('_'), + )}.ini`; + // 创建下载链接 + const link = h( + 'span', + { + style: { + marginRight: '15px', + }, + }, + fileName, + ); + + // 创建下载按钮 + const button = h( + Button, + { + onClick: async () => { + const res = await fetch(data.fileUrl); + if (!res.ok) { + message.error($t('license.downloadFailed')); + return; + } + const blob = await res.blob(); + + downloadFileFromBlobPart({ fileName, source: blob }); + }, + type: 'primary', + }, + $t('license.download'), + ); + + // 包裹容器 + return h( + 'div', + { + style: { + display: 'flex', + alignItems: 'center', + }, + }, + [link, button], + ); + }, + }, + ]; +} 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 d978529..c4c1f09 100644 --- a/apps/web-antd/src/views/license/license/generate/index.vue +++ b/apps/web-antd/src/views/license/license/generate/index.vue @@ -1,3 +1,118 @@ + + - 测试 + + + + + + + {{ $t('common.back') }} + + {{ $t('license.generate') }} + + + + diff --git a/apps/web-antd/src/views/license/license/index.vue b/apps/web-antd/src/views/license/license/index.vue index 84c2e68..509ead5 100644 --- a/apps/web-antd/src/views/license/license/index.vue +++ b/apps/web-antd/src/views/license/license/index.vue @@ -5,6 +5,8 @@ import type { } from '#/adapter/vxe-table'; import type { LicenseApi } from '#/api/license/license'; +import { useRouter } from 'vue-router'; + import { Page, useVbenModal } from '@vben/common-ui'; import { downloadFileFromBlobPart } from '@vben/utils'; @@ -21,6 +23,8 @@ import { $t } from '#/locales'; import { useGridColumns, useGridFormSchema } from './data'; import Form from './modules/form.vue'; +const router = useRouter(); + const [FormModal, formModalApi] = useVbenModal({ connectedComponent: Form, destroyOnClose: true, @@ -41,6 +45,27 @@ function onApply(row: LicenseApi.License) { formModalApi.setData({ ...row, action: 1 }).open(); } +/** 生成License */ +function onGenerate(row: LicenseApi.License) { + router.push({ name: 'LicenseGenerate', query: { id: row.id } }); +} + +/** 下载License */ +async function onDownload(row: LicenseApi.License) { + const fileName = `${row.fileUrl?.slice( + Math.max(0, row.fileUrl.lastIndexOf('/') + 1), + row.fileUrl.lastIndexOf('_'), + )}.ini`; + const res = await fetch(row.fileUrl); + if (!res.ok) { + message.error($t('license.downloadFailed')); + return; + } + const blob = await res.blob(); + + downloadFileFromBlobPart({ fileName, source: blob }); +} + /** 编辑License */ function onEdit(row: LicenseApi.License) { formModalApi.setData(row).open(); @@ -49,14 +74,14 @@ function onEdit(row: LicenseApi.License) { /** 删除License */ async function onDelete(row: LicenseApi.License) { const hideLoading = message.loading({ - content: $t('ui.actionMessage.deleting', [row.sn]), + content: $t('ui.actionMessage.deleting', [row.serialNo]), duration: 0, key: 'action_process_msg', }); try { await deleteLicense(row.id as number); hideLoading(); - message.success($t('ui.actionMessage.deleteSuccess', [row.sn])); + message.success($t('ui.actionMessage.deleteSuccess', [row.serialNo])); onRefresh(); } catch { hideLoading(); @@ -80,10 +105,18 @@ function onActionClick({ code, row }: OnActionClickParams) { onDelete(row); break; } + case 'download': { + onDownload(row); + break; + } case 'edit': { onEdit(row); break; } + case 'generate': { + onGenerate(row); + break; + } } } 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 8f4b263..cef3c0b 100644 --- a/apps/web-antd/src/views/license/license/modules/form.vue +++ b/apps/web-antd/src/views/license/license/modules/form.vue @@ -87,18 +87,21 @@ const [Modal, modalApi] = useVbenModal({ // 提交表单 const data = (await formApi.getValues()) as LicenseApi.License; data.neList = state.checkedList; + const action = formData.value?.action || 0; try { if (formData.value?.id) { - await (formData.value?.action === 1 - ? applyLicense(data) - : updateLicense(data)); + await (action === 1 ? applyLicense(data) : updateLicense(data)); } else { await createLicense(data); } // 关闭并提示 await modalApi.close(); emit('success'); - message.success($t('ui.actionMessage.operationSuccess')); + if (action === 1) { + message.success($t('license.applySuccess'), 3); + } else { + message.success($t('ui.actionMessage.operationSuccess')); + } } finally { modalApi.unlock(); }