From 63e3792e6d27c89e01983570c28d833a223071cd Mon Sep 17 00:00:00 2001 From: caiyuchao Date: Wed, 10 Sep 2025 17:05:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8A=A5=E8=A1=A8=E4=B8=AD=E5=BF=83?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/locales/langs/en-US/menu.json | 4 +- .../src/locales/langs/zh-CN/menu.json | 4 +- apps/web-antd/src/views/report/expire/data.ts | 144 +------------- .../src/views/report/expire/index.vue | 21 +- .../views/report/expire/modules/expiring.vue | 3 +- .../web-antd/src/views/report/expired/data.ts | 157 +++++++++++++++ .../src/views/report/expired/index.vue | 11 ++ .../{expire => expired}/modules/expired.vue | 3 +- apps/web-antd/src/views/report/member/data.ts | 164 ++++++++++++++++ .../src/views/report/member/index.vue | 11 ++ .../{progress => member}/modules/staff.vue | 4 +- .../src/views/report/progress/data.ts | 179 +++--------------- .../src/views/report/progress/index.vue | 21 +- .../views/report/progress/modules/project.vue | 2 + 14 files changed, 391 insertions(+), 337 deletions(-) create mode 100644 apps/web-antd/src/views/report/expired/data.ts create mode 100644 apps/web-antd/src/views/report/expired/index.vue rename apps/web-antd/src/views/report/{expire => expired}/modules/expired.vue (95%) create mode 100644 apps/web-antd/src/views/report/member/data.ts create mode 100644 apps/web-antd/src/views/report/member/index.vue rename apps/web-antd/src/views/report/{progress => member}/modules/staff.vue (96%) diff --git a/apps/web-antd/src/locales/langs/en-US/menu.json b/apps/web-antd/src/locales/langs/en-US/menu.json index c35e2be..88d5bcd 100644 --- a/apps/web-antd/src/locales/langs/en-US/menu.json +++ b/apps/web-antd/src/locales/langs/en-US/menu.json @@ -89,6 +89,8 @@ "report": { "base": "Report Center", "progress": "Project Progress", - "license": "License Expire" + "member": "Member Progress", + "expire": "License Expiring", + "expired": "License Expired" } } diff --git a/apps/web-antd/src/locales/langs/zh-CN/menu.json b/apps/web-antd/src/locales/langs/zh-CN/menu.json index 979aafc..536bdab 100644 --- a/apps/web-antd/src/locales/langs/zh-CN/menu.json +++ b/apps/web-antd/src/locales/langs/zh-CN/menu.json @@ -89,6 +89,8 @@ "report": { "base": "报表中心", "progress": "项目进展", - "license": "License到期" + "member": "成员进展", + "expire": "License即将到期", + "expired": "License已到期" } } diff --git a/apps/web-antd/src/views/report/expire/data.ts b/apps/web-antd/src/views/report/expire/data.ts index ad9a7c8..586bbcf 100644 --- a/apps/web-antd/src/views/report/expire/data.ts +++ b/apps/web-antd/src/views/report/expire/data.ts @@ -89,6 +89,15 @@ export function useExpiringGridColumns(): VxeTableGridOptions - option.name.toLowerCase().includes(input.toLowerCase()), - }, - }, - { - fieldName: 'projectId', - label: $t('license.project'), - component: 'ApiSelect', - componentProps: { - api: getProjectList, - allowClear: true, - fieldNames: { label: 'name', value: 'id' }, - showSearch: true, - filterOption: (input: string, option: any) => - option.name.toLowerCase().includes(input.toLowerCase()), - }, - }, - { - fieldName: 'serialNo', - label: 'SN', - component: 'Input', - componentProps: { - allowClear: true, - }, - }, - { - fieldName: 'expiryDate', - label: '到期时间', - component: 'RangePicker', - defaultValue: [dayjs().subtract(7, 'days'), dayjs()], - componentProps: { - ...getRangePickerDefaultProps(), - format: 'YYYY-MM-DD', - showTime: false, - }, - }, - ]; -} - -/** 列表的字段 */ -export function useExpiredGridColumns(): VxeTableGridOptions['columns'] { - return [ - { - field: 'customerName', - title: '客户名称', - showOverflow: false, - minWidth: 60, - }, - { - field: 'projectName', - title: '项目名称', - showOverflow: false, - minWidth: 80, - }, - { - field: 'status', - title: $t('project.status'), - minWidth: 40, - cellRender: { - name: 'CellDict', - props: { type: DICT_TYPE.LIC_PROJECT_STATUS }, - }, - }, - { - field: 'serialNo', - title: 'SN', - showOverflow: false, - minWidth: 40, - }, - { - field: 'businessOwnerName', - title: '业务负责人', - minWidth: 40, - }, - { - field: 'technicalOwnerAName', - title: '技术负责人1', - minWidth: 40, - }, - { - field: 'technicalOwnerBName', - title: '技术负责人2', - visible: false, - minWidth: 40, - }, - { - field: 'startTime', - title: '项目开始时间', - minWidth: 80, - visible: false, - formatter: 'formatDateTime', - }, - { - field: 'expiryDate', - title: '到期时间', - minWidth: 80, - formatter: 'formatDateTime', - }, - { - field: 'expiryDateFormat', - title: '已到期', - minWidth: 80, - formatter: ({ cellValue }) => { - if (!cellValue) return ''; - // const days = dayjs(cellValue).diff(dayjs(), 'day'); - // if (days > 0) { - // return `${days} 天`; - // } - // if (days === 0) { - // return '今天到期'; - // } - return dayjs(cellValue).fromNow(true); - }, - }, - { - field: 'applicationTime', - title: '申请时间', - minWidth: 80, - formatter: 'formatDateTime', - }, - ]; -} diff --git a/apps/web-antd/src/views/report/expire/index.vue b/apps/web-antd/src/views/report/expire/index.vue index 7ba60cd..797026b 100644 --- a/apps/web-antd/src/views/report/expire/index.vue +++ b/apps/web-antd/src/views/report/expire/index.vue @@ -1,30 +1,11 @@ diff --git a/apps/web-antd/src/views/report/expire/modules/expiring.vue b/apps/web-antd/src/views/report/expire/modules/expiring.vue index c849742..5f3b2a5 100644 --- a/apps/web-antd/src/views/report/expire/modules/expiring.vue +++ b/apps/web-antd/src/views/report/expire/modules/expiring.vue @@ -35,6 +35,7 @@ const [Grid] = useVbenVxeGrid({ search: true, // export: true, }, + height: 'auto', rowConfig: { keyField: 'id', isHover: false, @@ -56,5 +57,5 @@ const [Grid] = useVbenVxeGrid({ diff --git a/apps/web-antd/src/views/report/expired/data.ts b/apps/web-antd/src/views/report/expired/data.ts new file mode 100644 index 0000000..0eb441c --- /dev/null +++ b/apps/web-antd/src/views/report/expired/data.ts @@ -0,0 +1,157 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { ProgressApi } from '#/api/report/progress'; + +import dayjs from 'dayjs'; +import relativeTime from 'dayjs/plugin/relativeTime'; + +import { getCustomerList } from '#/api/license/customer'; +import { getProjectList } from '#/api/license/project'; +import { $t } from '#/locales'; +import { DICT_TYPE, getRangePickerDefaultProps } from '#/utils'; + +dayjs.extend(relativeTime); + +// ==================== 已过期 ==================== +export function useExpiredGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'customerId', + label: $t('license.customer'), + component: 'ApiSelect', + componentProps: { + api: getCustomerList, + allowClear: true, + fieldNames: { label: 'name', value: 'id' }, + showSearch: true, + filterOption: (input: string, option: any) => + option.name.toLowerCase().includes(input.toLowerCase()), + }, + }, + { + fieldName: 'projectId', + label: $t('license.project'), + component: 'ApiSelect', + componentProps: { + api: getProjectList, + allowClear: true, + fieldNames: { label: 'name', value: 'id' }, + showSearch: true, + filterOption: (input: string, option: any) => + option.name.toLowerCase().includes(input.toLowerCase()), + }, + }, + { + fieldName: 'serialNo', + label: 'SN', + component: 'Input', + componentProps: { + allowClear: true, + }, + }, + { + fieldName: 'expiryDate', + label: '到期时间', + component: 'RangePicker', + defaultValue: [dayjs().subtract(7, 'days'), dayjs()], + componentProps: { + ...getRangePickerDefaultProps(), + format: 'YYYY-MM-DD', + showTime: false, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useExpiredGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'customerName', + title: '客户名称', + showOverflow: false, + minWidth: 60, + }, + { + field: 'projectName', + title: '项目名称', + showOverflow: false, + minWidth: 80, + }, + { + field: 'status', + title: $t('project.status'), + minWidth: 40, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.LIC_PROJECT_STATUS }, + }, + }, + { + field: 'businessStatus', + title: $t('project.businessStatus'), + minWidth: 40, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.LIC_BUSINESS_STATUS }, + }, + }, + { + field: 'serialNo', + title: 'SN', + showOverflow: false, + minWidth: 40, + }, + { + field: 'businessOwnerName', + title: '业务负责人', + minWidth: 40, + }, + { + field: 'technicalOwnerAName', + title: '技术负责人1', + minWidth: 40, + }, + { + field: 'technicalOwnerBName', + title: '技术负责人2', + visible: false, + minWidth: 40, + }, + { + field: 'startTime', + title: '项目开始时间', + minWidth: 80, + visible: false, + formatter: 'formatDateTime', + }, + { + field: 'expiryDate', + title: '到期时间', + minWidth: 80, + formatter: 'formatDateTime', + }, + { + field: 'expiryDateFormat', + title: '已到期', + minWidth: 80, + formatter: ({ cellValue }) => { + if (!cellValue) return ''; + // const days = dayjs(cellValue).diff(dayjs(), 'day'); + // if (days > 0) { + // return `${days} 天`; + // } + // if (days === 0) { + // return '今天到期'; + // } + return dayjs(cellValue).fromNow(true); + }, + }, + { + field: 'applicationTime', + title: '申请时间', + minWidth: 80, + formatter: 'formatDateTime', + }, + ]; +} diff --git a/apps/web-antd/src/views/report/expired/index.vue b/apps/web-antd/src/views/report/expired/index.vue new file mode 100644 index 0000000..3ddbc20 --- /dev/null +++ b/apps/web-antd/src/views/report/expired/index.vue @@ -0,0 +1,11 @@ + + + diff --git a/apps/web-antd/src/views/report/expire/modules/expired.vue b/apps/web-antd/src/views/report/expired/modules/expired.vue similarity index 95% rename from apps/web-antd/src/views/report/expire/modules/expired.vue rename to apps/web-antd/src/views/report/expired/modules/expired.vue index 5c77f8b..5c7e218 100644 --- a/apps/web-antd/src/views/report/expire/modules/expired.vue +++ b/apps/web-antd/src/views/report/expired/modules/expired.vue @@ -35,6 +35,7 @@ const [Grid] = useVbenVxeGrid({ search: true, // export: true, }, + height: 'auto', rowConfig: { keyField: 'id', isHover: false, @@ -56,5 +57,5 @@ const [Grid] = useVbenVxeGrid({ diff --git a/apps/web-antd/src/views/report/member/data.ts b/apps/web-antd/src/views/report/member/data.ts new file mode 100644 index 0000000..3d4db73 --- /dev/null +++ b/apps/web-antd/src/views/report/member/data.ts @@ -0,0 +1,164 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { ProgressApi } from '#/api/report/progress'; + +import dayjs from 'dayjs'; + +import { getCustomerList } from '#/api/license/customer'; +import { getProjectList } from '#/api/license/project'; +import { getSimpleUserList } from '#/api/system/user'; +import { $t } from '#/locales'; +import { DICT_TYPE, getRangePickerDefaultProps } from '#/utils'; + +// ==================== 项目进展(项目维度) ==================== +/** 列表的搜索表单 */ +export function useStaffGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'authorId', + label: '处理人', + component: 'ApiSelect', + componentProps: { + allowClear: true, + api: async () => { + const data = await getSimpleUserList(); + return data.filter((item) => item.nickname !== '管理员'); + }, + fieldNames: { label: 'nickname', value: 'id' }, + showSearch: true, + filterOption: (input: string, option: any) => + option.nickname.toLowerCase().includes(input.toLowerCase()), + }, + }, + { + fieldName: 'customerId', + label: $t('license.customer'), + component: 'ApiSelect', + componentProps: { + api: getCustomerList, + allowClear: true, + fieldNames: { label: 'name', value: 'id' }, + showSearch: true, + filterOption: (input: string, option: any) => + option.name.toLowerCase().includes(input.toLowerCase()), + }, + }, + { + fieldName: 'projectId', + label: $t('license.project'), + component: 'ApiSelect', + componentProps: { + api: getProjectList, + allowClear: true, + fieldNames: { label: 'name', value: 'id' }, + showSearch: true, + filterOption: (input: string, option: any) => + option.name.toLowerCase().includes(input.toLowerCase()), + }, + }, + { + fieldName: 'serialNo', + label: 'SN', + component: 'Input', + componentProps: { + allowClear: true, + }, + }, + { + fieldName: 'updateTime', + label: '更新时间', + component: 'RangePicker', + defaultValue: [dayjs().subtract(7, 'days'), dayjs()], + componentProps: { + ...getRangePickerDefaultProps(), + format: 'YYYY-MM-DD', + showTime: false, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useStaffGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'author', + title: '处理人', + minWidth: 60, + }, + { + field: 'customerName', + title: '客户名称', + showOverflow: false, + minWidth: 80, + }, + { + field: 'projectName', + title: '项目名称', + showOverflow: false, + minWidth: 80, + }, + { + field: 'status', + title: $t('project.status'), + minWidth: 60, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.LIC_PROJECT_STATUS }, + }, + }, + { + field: 'businessStatus', + title: $t('project.businessStatus'), + minWidth: 60, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.LIC_BUSINESS_STATUS }, + }, + }, + { + field: 'serialNo', + title: 'SN', + showOverflow: false, + minWidth: 70, + }, + { + field: 'businessOwnerName', + title: '业务负责人', + minWidth: 60, + }, + { + field: 'technicalOwnerAName', + title: '技术负责人1', + minWidth: 60, + }, + { + field: 'technicalOwnerBName', + title: '技术负责人2', + visible: false, + minWidth: 60, + }, + { + field: 'startTime', + title: '项目开始时间', + minWidth: 130, + visible: false, + formatter: 'formatDateTime', + }, + { + field: 'content', + title: '进展记录', + type: 'html', + showOverflow: false, + align: 'left', + // headerAlign: 'center', + minWidth: 600, + }, + { + field: 'updateTime', + title: '更新时间', + minWidth: 130, + formatter: 'formatDateTime', + }, + ]; +} diff --git a/apps/web-antd/src/views/report/member/index.vue b/apps/web-antd/src/views/report/member/index.vue new file mode 100644 index 0000000..ae2602e --- /dev/null +++ b/apps/web-antd/src/views/report/member/index.vue @@ -0,0 +1,11 @@ + + + diff --git a/apps/web-antd/src/views/report/progress/modules/staff.vue b/apps/web-antd/src/views/report/member/modules/staff.vue similarity index 96% rename from apps/web-antd/src/views/report/progress/modules/staff.vue rename to apps/web-antd/src/views/report/member/modules/staff.vue index 8696a70..07d3564 100644 --- a/apps/web-antd/src/views/report/progress/modules/staff.vue +++ b/apps/web-antd/src/views/report/member/modules/staff.vue @@ -34,6 +34,7 @@ const [Grid] = useVbenVxeGrid({ search: true, // export: true, }, + height: 'auto', rowConfig: { keyField: 'id', isHover: false, @@ -56,6 +57,7 @@ const [Grid] = useVbenVxeGrid({ const mergeFields = [ 'serialNo', 'status', + 'businessStatus', 'businessOwnerName', 'technicalOwnerAName', 'technicalOwnerBName', @@ -93,5 +95,5 @@ const [Grid] = useVbenVxeGrid({ diff --git a/apps/web-antd/src/views/report/progress/data.ts b/apps/web-antd/src/views/report/progress/data.ts index bdd8314..6573b39 100644 --- a/apps/web-antd/src/views/report/progress/data.ts +++ b/apps/web-antd/src/views/report/progress/data.ts @@ -86,7 +86,7 @@ export function useProjectGridColumns(): VxeTableGridOptions { - const data = await getSimpleUserList(); - return data.filter((item) => item.nickname !== '管理员'); - }, - fieldNames: { label: 'nickname', value: 'id' }, - showSearch: true, - filterOption: (input: string, option: any) => - option.nickname.toLowerCase().includes(input.toLowerCase()), - }, - }, - { - fieldName: 'customerId', - label: $t('license.customer'), - component: 'ApiSelect', - componentProps: { - api: getCustomerList, - allowClear: true, - fieldNames: { label: 'name', value: 'id' }, - showSearch: true, - filterOption: (input: string, option: any) => - option.name.toLowerCase().includes(input.toLowerCase()), - }, - }, - { - fieldName: 'projectId', - label: $t('license.project'), - component: 'ApiSelect', - componentProps: { - api: getProjectList, - allowClear: true, - fieldNames: { label: 'name', value: 'id' }, - showSearch: true, - filterOption: (input: string, option: any) => - option.name.toLowerCase().includes(input.toLowerCase()), - }, - }, - { - fieldName: 'serialNo', - label: 'SN', - component: 'Input', - componentProps: { - allowClear: true, - }, - }, - { - fieldName: 'updateTime', - label: '更新时间', - component: 'RangePicker', - defaultValue: [dayjs().subtract(7, 'days'), dayjs()], - componentProps: { - ...getRangePickerDefaultProps(), - format: 'YYYY-MM-DD', - showTime: false, - }, - }, - ]; -} - -/** 列表的字段 */ -export function useStaffGridColumns(): VxeTableGridOptions['columns'] { - return [ - { - field: 'author', - title: '处理人', - minWidth: 40, - }, - { - field: 'customerName', - title: '客户名称', - showOverflow: false, minWidth: 60, }, - { - field: 'projectName', - title: '项目名称', - showOverflow: false, - minWidth: 80, - }, - { - field: 'status', - title: $t('project.status'), - minWidth: 40, - cellRender: { - name: 'CellDict', - props: { type: DICT_TYPE.LIC_PROJECT_STATUS }, - }, - }, - { - field: 'serialNo', - title: 'SN', - showOverflow: false, - minWidth: 40, - }, - { - field: 'businessOwnerName', - title: '业务负责人', - minWidth: 40, - }, { field: 'technicalOwnerAName', title: '技术负责人1', - minWidth: 40, + minWidth: 60, }, { field: 'technicalOwnerBName', title: '技术负责人2', visible: false, - minWidth: 40, + minWidth: 60, }, { field: 'startTime', title: '项目开始时间', - minWidth: 80, + minWidth: 130, visible: false, formatter: 'formatDateTime', }, + { + field: 'author', + title: '处理人', + minWidth: 60, + }, { field: 'content', title: '进展记录', @@ -288,12 +153,12 @@ export function useStaffGridColumns(): VxeTableGridOptions showOverflow: false, align: 'left', // headerAlign: 'center', - minWidth: 800, + minWidth: 600, }, { field: 'updateTime', title: '更新时间', - minWidth: 80, + minWidth: 130, formatter: 'formatDateTime', }, ]; diff --git a/apps/web-antd/src/views/report/progress/index.vue b/apps/web-antd/src/views/report/progress/index.vue index afc6943..253db46 100644 --- a/apps/web-antd/src/views/report/progress/index.vue +++ b/apps/web-antd/src/views/report/progress/index.vue @@ -1,30 +1,11 @@ diff --git a/apps/web-antd/src/views/report/progress/modules/project.vue b/apps/web-antd/src/views/report/progress/modules/project.vue index fa15f79..6f20302 100644 --- a/apps/web-antd/src/views/report/progress/modules/project.vue +++ b/apps/web-antd/src/views/report/progress/modules/project.vue @@ -34,6 +34,7 @@ const [Grid] = useVbenVxeGrid({ search: true, // export: true, }, + height: 'auto', rowConfig: { keyField: 'id', isHover: false, @@ -56,6 +57,7 @@ const [Grid] = useVbenVxeGrid({ const mergeFields = [ 'serialNo', 'status', + 'businessStatus', 'businessOwnerName', 'technicalOwnerAName', 'technicalOwnerBName',