From f6f66196f3ca377eda0afd320e64005c28204c76 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 15 十月 2026 15:44:37 +0800
Subject: [PATCH] fix(crm): 客户分析页表格与图表数据展示问题
---
src/views/crm/statistics/customer/index.vue | 103 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 98 insertions(+), 5 deletions(-)
diff --git a/src/views/crm/statistics/customer/index.vue b/src/views/crm/statistics/customer/index.vue
index a0c39c4..4aa5437 100644
--- a/src/views/crm/statistics/customer/index.vue
+++ b/src/views/crm/statistics/customer/index.vue
@@ -8,12 +8,18 @@
import { ContentWrap, Page } from '@vben/common-ui';
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
+import { erpCalculatePercentage } from '@vben/utils';
import { Tabs } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
-import { getChartDatas } from '#/api/crm/statistics/customer';
+import {
+ getChartDatas,
+ getCustomerDealCycleByDate,
+ getCustomerSummaryByDate,
+ getDatas,
+} from '#/api/crm/statistics/customer';
import { $t } from '#/locales';
import { getChartOptions } from './chartOptions';
@@ -43,7 +49,9 @@
const [Grid, gridApi] = useVbenVxeGrid({
gridOptions: {
columns: useGridColumns(activeTabName.value),
- height: 'auto',
+ // height: 'auto' 鏃惰〃鏍艰窡鐖跺鍣ㄩ珮搴﹁蛋锛屾湰椤靛浘琛ㄥ崰浜嗕笂闈竴澶у潡锛岃〃鏍煎氨琚帇寰楀緢鐭紱
+ // 杩欓噷缁欎釜鍥哄畾楂樺害锛�8 涓〉绛惧叡鐢ㄨ繖涓�涓〃鏍硷紝涓�鏀瑰叏楂樸�傚珜楂�/瀚岀煯鏀硅繖涓�澶勫嵆鍙��
+ height: '600px',
keepSource: true,
pagerConfig: {
enabled: false,
@@ -58,6 +66,56 @@
} as VxeTableGridOptions<CrmStatisticsCustomerApi.CustomerSummaryByUserRespVO>,
});
+/** 瓒呯骇绠$悊鍛橈紙鐢ㄦ埛 ID 1锛変笉鏄笟鍔′汉鍛橈紝缁熻琛ㄩ噷涓嶈鍑虹幇浠栧悕涓嬬殑閭h */
+const ADMIN_USER_ID = 1;
+
+function excludeAdminRows(rows: unknown[]) {
+ return (rows as Array<Record<string, unknown>>).filter(
+ (row) => Number(row.ownerUserId) !== ADMIN_USER_ID,
+ );
+}
+
+/**
+ * 鎸夊憳宸ョ粺璁$殑椤电锛屽悗绔細鎶婇儴闂ㄩ噷姣忎釜鍛樺伐閮藉垪涓�琛岋紙娌℃暟鎹殑琛� 0锛夛紝鎸夌敤鎴� ID 鍗囧簭鎺� 鈫� 鏈夋暟鎹殑鍛樺伐寰�寰�鍦ㄦ渶鍚庝竴琛岋紝
+ * 600px 涓�灞忓彧鏄剧ず鍗佸嚑琛岋紝缈诲墠鍑犲睆鐪嬪埌鐨勫叏鏄� 0锛岀湅鐫�灏卞儚"娌℃暟鎹�"銆傝繖閲屾寜涓绘寚鏍囧�掑簭锛屾湁鏁版嵁鐨勬帓鍓嶉潰锛�0 琛屼笉鍒犮��
+ */
+const USER_TAB_METRIC: Record<string, string[]> = {
+ customerSummary: ['customerDealCount', 'customerCreateCount'],
+ dealCycleByUser: ['customerDealCount', 'customerDealCycle'],
+ followUpSummary: ['followUpRecordCount', 'followUpCustomerCount'],
+ poolSummary: ['customerPutCount', 'customerTakeCount'],
+};
+
+function sortByMetric(key: string, rows: unknown[]) {
+ const fields = USER_TAB_METRIC[key];
+ if (!fields) {
+ return rows;
+ }
+ return [...(rows as Array<Record<string, number>>)].sort((a, b) => {
+ for (const field of fields) {
+ const diff = (Number(b[field]) || 0) - (Number(a[field]) || 0);
+ if (diff !== 0) {
+ return diff;
+ }
+ }
+ return 0;
+ });
+}
+
+/**
+ * 璺熻繘鏂瑰紡鍒嗘瀽鐨勨�滃崰姣�(%)鈥濆垪鍦� data.ts 閲屾棦娌℃湁 formatter锛屽悗绔� FollowUpSummaryByTypeRespVO 涔熶笉杩斿洖璇ュ瓧娈碉紝
+ * 鎵�浠ユ暣鍒楁案杩滄槸绌虹殑锛涜繖閲屾寜璺熻繘娆℃暟鍦ㄦ湰鍦拌ˉ绠楋紙鍙e緞涓庡悗绔叾瀹冨崰姣斾竴鑷达細value / total * 100锛屼繚鐣欎袱浣嶏級銆�
+ */
+function fillFollowUpPortion(rows: unknown[]) {
+ // getDatas 鐨勮繑鍥炵被鍨嬫槸鍚勯〉绛剧殑鑱斿悎绫诲瀷锛岃繖閲屾寜璋冪敤鏂逛繚璇佺殑椤哄簭鏀剁獎鎴愯窡杩涙柟寮忕殑鍝嶅簲
+ const list = rows as CrmStatisticsCustomerApi.FollowUpSummaryByTypeRespVO[];
+ const total = list.reduce((sum, row) => sum + (row.followUpRecordCount ?? 0), 0);
+ return list.map((row) => ({
+ ...row,
+ portion: erpCalculatePercentage(row.followUpRecordCount ?? 0, total),
+ }));
+}
+
/** tab 鍒囨崲 */
async function handleTabChange(key: any) {
activeTabName.value = key;
@@ -65,9 +123,44 @@
columns: useGridColumns(key),
});
const queryParams = await formApi.getValues();
- const res = await getChartDatas(activeTabName.value, queryParams);
- await renderEcharts(getChartOptions(activeTabName.value, res));
- await gridApi.grid.reloadData(res);
+ // 鍥捐〃鍜岃〃鏍兼槸涓や釜鍙e緞鐨勬帴鍙o細鍥捐〃瑕�"鎸夋棩鏈�"鐨勬椂搴忔暟鎹紝琛ㄦ牸瑕�"鎸夊憳宸�/鍦板尯/浜у搧"鐨勬槑缁嗘暟鎹��
+ // 鍘熸潵鍙皟 getChartDatas 鍙堟妸瀹冪殑杩斿洖鍊煎杺缁欒〃鏍硷紝鍑℃槸涓よ�呭彛寰勪笉鍚岀殑鏍囩椤碉紙瀹㈡埛姹囨�汇�佽窡杩涙眹鎬汇�佸鎴锋睜銆佽浆鍖栫粺璁★級
+ // 琛ㄦ牸閲屽氨浼氬ぇ鐗囩┖瀛楁鈥斺�斿浘琛ㄨ繑鍥炵殑鏃ユ湡/鏁伴噺瀛楁鍦ㄨ〃鏍煎垪閲屽苟涓嶅瓨鍦ㄣ��
+ const [chartData, tableData] = await Promise.all([
+ getChartDatas(key, queryParams),
+ getDatas(key, queryParams),
+ ]);
+ // 銆屽憳宸ュ鎴锋垚浜ゅ懆鏈熷垎鏋愩�嶇殑鍥捐〃閫夐」璇荤殑鏄� res.customerDealCycleByDate / res.customerDealCycleByUser 涓や釜鏁扮粍
+ // 锛坈hartOptions.ts 閲屽彧鏈夎繖涓�涓〉绛炬槸鎸夊璞″彇鐨勶級锛屼絾 getChartDatas 瀵硅繖涓〉绛惧彧杩斿洖涓�涓暟缁勶紝
+ // res.customerDealCycleByDate 鏄� undefined 鈫� 鍦ㄥ浘琛ㄩ噷 .map 鐩存帴鎶涢敊锛屽悗闈㈢殑琛ㄦ牸 reloadData 姘歌繙涓嶄細鎵ц锛�
+ // 琛ㄦ牸灏变竴鐩村仠鍦ㄤ笂涓�涓〉绛剧殑鏁版嵁涓婏紙鐪嬬潃灏辨槸"鎴愪氦鍛ㄦ湡/鎴愪氦瀹㈡埛鏁版病鏈夋暟鎹�"锛夈��
+ // 杩欓噷鎸夊浘琛ㄨ鐨勫舰鐘惰ˉ榻愪袱涓�"鎸夋棩鏈�"搴忓垪锛氭垚浜ゅ懆鏈熺敤鎴愪氦鍛ㄦ湡(鎸夋棩鏈�)鎺ュ彛锛屾垚浜ゅ鎴锋暟鐢ㄥ鎴锋�婚噺(鎸夋棩鏈�)鎺ュ彛锛�
+ // 涓や釜鎺ュ彛閮芥寜鏌ヨ鍖洪棿鍒嗘《锛宼ime 涓�鑷达紙瀹炴祴 2026-10-08(绗� 41 鍛�) / 2026-10-12(绗� 42 鍛�)锛夈��
+ let chartPayload: any = chartData;
+ if (key === 'dealCycleByUser') {
+ const params = queryParams as CrmStatisticsCustomerApi.CustomerSummaryReqVO;
+ const [dealCycleByDate, summaryByDate] = await Promise.all([
+ getCustomerDealCycleByDate(params),
+ getCustomerSummaryByDate(params),
+ ]);
+ chartPayload = {
+ customerDealCycleByDate: dealCycleByDate,
+ customerDealCycleByUser: summaryByDate,
+ };
+ }
+ // 鍥捐〃鐢讳笉鍑烘潵涓嶈兘杩炵疮琛ㄦ牸锛氬閿欏寘涓�灞傦紝寮傚父鍙鏃ュ織
+ try {
+ await renderEcharts(getChartOptions(key, chartPayload));
+ } catch (error) {
+ console.error('[瀹㈡埛鍒嗘瀽] 鍥捐〃娓叉煋澶辫触', key, error);
+ }
+ const rows = sortByMetric(
+ key,
+ excludeAdminRows(Array.isArray(tableData) ? tableData : []),
+ );
+ await gridApi.grid.reloadData(
+ key === 'followUpType' ? fillFollowUpPortion(rows) : rows,
+ );
}
onMounted(() => {
--
Gitblit v1.9.3