From 9edad91dcace9be4a81b7692fbc9d1547eabb2db Mon Sep 17 00:00:00 2001 From: chenghuan Date: Wed, 4 Feb 2026 16:04:03 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E8=B4=A2=E5=8A=A1=E7=BB=9F=E8=AE=A1):=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=9C=88=E5=BA=A6=E8=B4=A2=E5=8A=A1=E6=8A=A5?= =?UTF-8?q?=E8=A1=A8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加月度财务报表页面及相关工具函数和类型定义 修改统计接口参数类型以支持字符串格式的月份 调整空状态显示样式 --- apps/finance/src/api/statistics/index.ts | 42 +- .../src/router/routes/modules/statistics.ts | 9 + .../statistics/common/MonthReportView.vue | 2 +- .../statistics/summary-month/report-utils.ts | 127 +++++ .../views/statistics/summary-month/report.vue | 530 ++++++++++++++++++ .../views/statistics/summary-month/types.d.ts | 40 ++ 6 files changed, 739 insertions(+), 11 deletions(-) create mode 100644 apps/finance/src/views/statistics/summary-month/report-utils.ts create mode 100644 apps/finance/src/views/statistics/summary-month/report.vue create mode 100644 apps/finance/src/views/statistics/summary-month/types.d.ts diff --git a/apps/finance/src/api/statistics/index.ts b/apps/finance/src/api/statistics/index.ts index 7206ae3..5d9415c 100644 --- a/apps/finance/src/api/statistics/index.ts +++ b/apps/finance/src/api/statistics/index.ts @@ -9,7 +9,7 @@ export const statisticsApi = { * @param data.year 年份 * @returns 天医币报表数据 */ - getReportTianyibi: (data: { month?: string; year: number }) => { + getReportTianyibi: (data: { month: string; year: number | string }) => { return requestClient.post('common/statistics/pointStatistics', data); }, @@ -20,7 +20,7 @@ export const statisticsApi = { * @param data.year 年份 * @returns 实物报表数据 */ - getPhysicalStatistics: (data: { month?: string; year: number }) => { + getPhysicalStatistics: (data: { month: string; year: number | string }) => { return requestClient.post('common/statistics/physicalStatistics', data); }, @@ -31,7 +31,7 @@ export const statisticsApi = { * @param data.year 年份 * @returns 培训班报表数据 */ - getTrainingClassStatistics: (data: { month?: string; year: number }) => { + getTrainingClassStatistics: (data: { month: string; year: number | string }) => { return requestClient.post('common/statistics/trainingClassStatistics', data); }, @@ -42,7 +42,7 @@ export const statisticsApi = { * @param data.year 年份 * @returns VIP报表数据 */ - getVipStatistics: (data: { month?: string; year: number }) => { + getVipStatistics: (data: { month: string; year: number | string }) => { return requestClient.post('common/statistics/vipStatistics', data); }, @@ -53,7 +53,7 @@ export const statisticsApi = { * @param data.year 年份 * @returns 课程报表数据 */ - getCourseStatistics: (data: { month?: string; year: number }) => { + getCourseStatistics: (data: { month: string; year: number | string }) => { return requestClient.post('common/statistics/courseStatistics', data); }, @@ -64,7 +64,7 @@ export const statisticsApi = { * @param data.year 年份 * @returns 天医币报表数据 */ - downloadReportTianyibi: (data: { month?: string; year: number }) => { + downloadReportTianyibi: (data: { month: string; year: number | string }) => { return defaultRequestClient.download('common/statistics/pointInfoExport', { data, }); @@ -76,7 +76,7 @@ export const statisticsApi = { * @param data.year 年份 * @returns 实物报表数据 */ - downloadReportPhysical: (data: { month?: string; year: number }) => { + downloadReportPhysical: (data: { month: string; year: number | string }) => { return defaultRequestClient.download('common/statistics/physicalInfoExport', { data, }); @@ -88,7 +88,7 @@ export const statisticsApi = { * @param data.year 年份 * @returns 培训班报表数据 */ - downloadReportTrainingClass: (data: { month?: string; year: number }) => { + downloadReportTrainingClass: (data: { month: string; year: number | string }) => { return defaultRequestClient.download('common/statistics/trainingClassInfoExport', { data, }); @@ -100,7 +100,7 @@ export const statisticsApi = { * @param data.year 年份 * @returns VIP报表数据 */ - downloadReportVip: (data: { month?: string; year: number }) => { + downloadReportVip: (data: { month: string; year: number | string }) => { return defaultRequestClient.download('common/statistics/vipInfoExport', { data, }); @@ -112,9 +112,31 @@ export const statisticsApi = { * @param data.year 年份 * @returns 课程报表数据 */ - downloadReportCourse: (data: { month?: string; year: number }) => { + downloadReportCourse: (data: { month: string; year: number | string }) => { return defaultRequestClient.download('common/statistics/courseInfoExport', { data, }); }, + + /** + * 获取月总结 + * @param data 月份 格式为YYYY-MM + * @returns 月总结数据 + */ + getSumMonthStatistics: (data: string) => { + return requestClient.post('common/statistics/getStatistics', { orderTime: data }); + }, + + /** + * 汇总导出 + * @param data 月份 格式为YYYY-MM + * @param data.month 月份 + * @param data.year 年份 + * @returns 月总结数据 + */ + downloadSumMonthStatistics: (data: { month: string; year: number | string }) => { + return defaultRequestClient.download('common/statistics/statisticsInfoExport', { + data, + }); + }, }; diff --git a/apps/finance/src/router/routes/modules/statistics.ts b/apps/finance/src/router/routes/modules/statistics.ts index b3fa133..58ea7e1 100644 --- a/apps/finance/src/router/routes/modules/statistics.ts +++ b/apps/finance/src/router/routes/modules/statistics.ts @@ -56,6 +56,15 @@ const routes: RouteRecordRaw[] = [ path: '/statistics/course-report', component: () => import('#/views/statistics/course/report.vue'), }, + { + meta: { + title: '月度财务报表', + keepAlive: true, + }, + name: 'FinanceMonthReport', + path: '/statistics/finance-month-report', + component: () => import('#/views/statistics/summary-month/report.vue'), + }, ], }, ]; diff --git a/apps/finance/src/views/statistics/common/MonthReportView.vue b/apps/finance/src/views/statistics/common/MonthReportView.vue index 3ce832f..464c533 100644 --- a/apps/finance/src/views/statistics/common/MonthReportView.vue +++ b/apps/finance/src/views/statistics/common/MonthReportView.vue @@ -81,7 +81,7 @@ const handleDownloadMonth = async (index: number) => {
diff --git a/apps/finance/src/views/statistics/summary-month/report-utils.ts b/apps/finance/src/views/statistics/summary-month/report-utils.ts new file mode 100644 index 0000000..7cb5eeb --- /dev/null +++ b/apps/finance/src/views/statistics/summary-month/report-utils.ts @@ -0,0 +1,127 @@ +import type { IncomeItem, VipAndCourseMonthStatistics } from './types'; + +// 处理收款汇总数据以及实物和培训班数据 +export function handleSumAndNoNeedAmortizateMonthData( + responseData: any[], + options: { + childDictArr: { title: string; type: string }[]; + typeDictArr: string[]; + typeKey: string; + }, +) { + let sumMonthTotal = 0; + const resultData = [] as any[]; + const { childDictArr, typeDictArr, typeKey } = options; + typeDictArr.forEach((type) => { + // 查找接口返回数据中是否有当前支付平台的数据 + const index = responseData.findIndex((item) => item[typeKey] === type); + // 取得当前支付平台的数据项,若不存在则用空对象代替 + const resItem = index === -1 ? {} : responseData[index]; + // 组装页面渲染需要的数据格式 + resultData.push({ + type, + sumFee: resItem.sumFee || 0, + children: childDictArr.map((childType) => ({ + title: childType.title, + fee: resItem[childType.type] || 0, + })), + }); + // 累加总金额 + // 使用 toFixed 避免精度丢失 + sumMonthTotal = Number.parseFloat((sumMonthTotal + (resItem.sumFee || 0)).toFixed(3)); + }); + return { + sumMonthTotal, + resultData, + }; +} + +// 获取当前月份和上一个月份的数据 +async function getTwoMonthData( + requestMethod: (params: { month: string; year: number | string }) => Promise, + date: string, +) { + // 处理日期格式,将YYYY-MM转换为year: YYYY, month: MM + const [year = '', month = ''] = date.split('-'); + const params = { + year, + month, + }; + // 处理跨年情况 + const lastMonthParams = { + year: params.month === '01' ? Number(params.year) - 1 : params.year, + month: params.month === '01' ? '12' : (Number(params.month) - 1).toString().padStart(2, '0'), + }; + // 调用接口 查询当前月份数据和上一个月数据 + // 同时发送两次请求 + const [currentMonthData, lastMonthData] = await Promise.all([ + requestMethod(params), + requestMethod(lastMonthParams), + ]); + return { + currentMonthData, + lastMonthData, + }; +} + +// 处理VIP、课程数据的公共方法 +export async function handleVipAndCourseMonthData( + requestMethod: (params: { + month: string; + year: number | string; + }) => Promise, + date: string, + incomeTypes: string[], +) { + const { currentMonthData, lastMonthData } = await getTwoMonthData(requestMethod, date); + return { + ...currentMonthData, + incomes: incomeTypes.map((type) => ({ + type, + fee: currentMonthData.incomes.find((item: IncomeItem) => item.type === type)?.fee || 0, + })), + lastNotyet: lastMonthData?.notyet || 0, + incomesTotal: Number.parseFloat( + currentMonthData.incomes + .reduce((acc: number, cur: IncomeItem) => acc + cur.fee, 0) + .toFixed(3), + ), + }; +} + +// 处理天医币明细数据 +export async function handleTianyibiDetailData( + requestMethod: (params: { + month: string; + year: number | string; + }) => Promise, + date: string, + incomeTypes: string[], + consumesTypes: string[], +) { + const { currentMonthData, lastMonthData } = await getTwoMonthData(requestMethod, date); + return { + ...currentMonthData.map, + incomes: incomeTypes.map((type) => ({ + type, + fee: currentMonthData.map.incomes.find((item: IncomeItem) => item?.type === type)?.fee || 0, + point: + currentMonthData.map.incomes.find((item: IncomeItem) => item?.type === type)?.point || 0, + })), + consumes: consumesTypes.map((type) => ({ + type, + fee: currentMonthData.map.consumes.find((item: IncomeItem) => item?.type === type)?.fee || 0, + })), + lastSurplus: lastMonthData?.map.surplus || 0, + incomesTotal: Number.parseFloat( + currentMonthData.map.incomes + .reduce((acc: number, cur: IncomeItem) => acc + cur.fee, 0) + .toFixed(3), + ), + consumesTotal: Number.parseFloat( + currentMonthData.map.consumes + .reduce((acc: number, cur: IncomeItem) => acc + cur.fee, 0) + .toFixed(3), + ), + }; +} diff --git a/apps/finance/src/views/statistics/summary-month/report.vue b/apps/finance/src/views/statistics/summary-month/report.vue new file mode 100644 index 0000000..07c2a5c --- /dev/null +++ b/apps/finance/src/views/statistics/summary-month/report.vue @@ -0,0 +1,530 @@ + + + + + diff --git a/apps/finance/src/views/statistics/summary-month/types.d.ts b/apps/finance/src/views/statistics/summary-month/types.d.ts new file mode 100644 index 0000000..5839d84 --- /dev/null +++ b/apps/finance/src/views/statistics/summary-month/types.d.ts @@ -0,0 +1,40 @@ +export interface NoNeedAmortizateMonthStatistics { + wx: number; + bank: number; + zfb: number; + tianyibi: number; + sumFee: number; + type: string; +} + +export interface SumAndNoNeedAmortizateMonthDataItem { + type: string; + sumFee: number; + children: Array<{ + fee: number; + title: string; + }>; +} + +export interface SumMonthStatistics { + peixun: number; + shiwu: number; + kecheng: number; + tianyibi: number; + plat: string; + sumFee: number; + vip: number; +} + +export interface IncomeItem { + fee: number; + type: string; + point?: number; +} + +export interface VipAndCourseMonthStatistics { + incomes: IncomeItem[]; + notyet: number; + already: number; + now: number; +}