一、模块通用功能概述本方案为通用后台数据统计联动看板标准化实现模板可适配工单审核、客户评价、任务质检、流程巡检等各类业务统计场景核心通用能力周期聚合统计默认近30天业务数据自动分组聚合按评分/等级分为三类统计维度优/达标/待优化输出各分组总量、全量数据明细卡片联动筛选顶部统计卡片点击切换筛选条件再次点击清空筛选下方列表实时匹配对应分组数据权限隔离渲染基于后台权限标识控制模块整体显隐无权限用户完全不加载组件响应式联动UI统计卡片、数据表格双向联动统一处理加载、空数据、异常报错状态二、通用分层架构与数据流页面组件层级┌─────────────────────────────────────────────────────────┐ │ DashboardPage 工作台首页 │ │ ┌──────────────────────────────────────────────────┐ │ │ │ DataStatsBar 顶部统计卡片栏 │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ │ │ 优档分组 │ │达标分组 │ │待优化分组│ │ │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ └──────────────────────────────────────────────────┘ │ │ │ onFilterChange 筛选回调 │ │ ▼ │ │ ┌──────────────────────────────────────────────────┐ │ │ │ FilteredDataTable 筛选数据表格 │ │ │ │ ┌──────┬──────┬──────┬──────┬──────┬──────┐ │ │ │ │ │编号 │名称 │等级分│备注 │操作人│时间 │ │ │ │ │ └──────┴──────┴──────┴──────┴──────┴──────┘ │ │ │ └──────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘标准数据流链路接口请求层 → 全局统计数据Hook → 顶部统计卡片组件 → 筛选数据Hook → 业务数据表格组件核心设计一次请求获取全量聚合数据明细数据前端内存筛选无需重复调接口三、接口层通用标准化设计脱敏通用命名3.1 通用TS类型定义剥离业务专属名词抽象通用数据结构适配所有评分类统计场景// src/api/business-stats.ts 通用业务统计接口// 单条业务明细通用结构exporttypeBizRecordItem{id:number;record_id:string;record_name:string;operator_uid:string;operator_name:string;score:number;// 分级评分核心字段remark:string;update_timestamp:number;};// 接口返回顶层统一结构聚合统计原始明细exporttypeBizStatsResponse{score_group_count:{score:number;count:number}[];total_record_num:number;record_list:BizRecordItem[];};// 接口请求时间区间参数exporttypeBizStatsQueryParams{start_time?:number;end_time?:number;};// 筛选分组枚举通用三级分类exporttypeScoreGroupKeyhigh|normal|low;3.2 基础统计查询接口封装通用GET统计接口统一参数拼接、信封响应解析、异常捕获逻辑统一接口前缀脱敏/v3/p/platform/v1/business/record/statistics使用URLSearchParams安全拼接时间戳参数规避字符串拼接漏洞全局统一响应信封envelope封装所有后端接口标准化返回格式数据空值主动抛出业务异常上层Hook统一捕获展示constSTATS_API_PATH/v3/p/platform/v1/business/record/statistics;exportasyncfunctionfetchBizStatsData(params?:BizStatsQueryParams):PromiseBizStatsResponse{constsearchParamsnewURLSearchParams();if(params?.start_time)searchParams.set(start_time,String(params.start_time));if(params?.end_time)searchParams.set(end_time,String(params.end_time));constqueryStrsearchParams.toString();constfinalUrlqueryStr?${STATS_API_PATH}?${queryStr}:STATS_API_PATH;// 全局统一请求封装处理token、响应拦截constresEnvelopeawaitrequestWithGlobalWrapperBizStatsResponse(finalUrl,{method:GET});if(!resEnvelope.data)thrownewError(获取业务统计数据为空);returnresEnvelope.data;}3.3 前端内存筛选封装函数不复发网络请求基于已拉取全量明细做本地过滤提升交互速度exportasyncfunctiongetFilteredRecordList(group:ScoreGroupKey){// 复用基础统计接口只请求一次全量数据constallStatsawaitfetchBizStatsData(getDefault30DayRange());// 模型层通用过滤工具处理分组constfilterListfilterRecordByScoreGroup(allStats.record_list,group);return{list:filterList,total:filterList.length};}四、通用自定义Hook分层设计4.1 useBizStats 全局统计数据Hook负责拉取周期统计基础数据封装完整UI三态加载中/数据/错误useCallback缓存请求函数避免重复渲染触发重复请求useEffect组件挂载自动请求对外暴露refresh手动刷新方法异常信息分层降级后端返回错误文案 全局默认提示// src/dashboard/hooks/use-biz-stats.tsexportfunctionuseBizStats(){const[state,setState]useState{data:BizStatsResponse|null;loading:boolean;error:string|null;}({data:null,loading:false,error:null});constloadStatsuseCallback(async(){setState(prev({...prev,loading:true,error:null}));try{constdataawaitfetchBizStatsData(getDefault30DayRange());setState({data,loading:false,error:null});}catch(err){consterrMsgerrinstanceofError?err.message:统计数据加载失败;setState(prev({...prev,loading:false,error:errMsg}));}},[]);useEffect((){voidloadStats();},[loadStats]);return{...state,refresh:loadStats};}通用30天时间范围计算工具通用工具函数统一和后端约定秒级Unix时间戳自动计算近30天起止时间兼容任意业务统计周期需求exportfunctiongetDefault30DayRange():BizStatsQueryParams{consttodaynewDate();// 结束当日23:59:59constendDatenewDate(today.getFullYear(),today.getMonth(),today.getDate(),23,59,59);// 起始往前推29天合计30天数据conststartDatenewDate(endDate);startDate.setDate(startDate.getDate()-29);return{start_time:Math.floor(startDate.getTime()/1000),end_time:Math.floor(endDate.getTime()/1000),};}4.2 useFilteredRecordList 筛选联动Hook管理当前激活筛选分组控制表格数据渲染支持开关启用、清空筛选重置activeFilter存储当前选中分组null代表无筛选提供enabled入参支持模块权限关闭时停止数据请求筛选置空时直接清空列表无需等待接口响应交互更顺滑exportfunctionuseFilteredRecordList(options?:{enabled?:boolean}){const{enabledtrue}options||{};const[activeFilterKey,setActiveFilterKey]useStateScoreGroupKey|null(null);const[tableState,setTableState]useState({list:[],loading:false,error:null,total:0});constfetchFilterDatauseCallback(async(group:ScoreGroupKey){setTableState(prev({...prev,loading:true,error:null}));try{constresawaitgetFilteredRecordList(group);setTableState({list:res.list,loading:false,error:null,total:res.total});}catch(err){constmsgerrinstanceofError?err.message:筛选数据加载失败;setTableState(prev({...prev,loading:false,error:msg}));}},[]);// 监听筛选标识变化自动重新过滤useEffect((){if(!enabled||!activeFilterKey){setTableState({list:[],loading:false,error:null,total:0});return;}voidfetchFilterData(activeFilterKey);},[activeFilterKey,enabled,fetchFilterData]);// 封装筛选切换方法对外暴露constchangeFilter(key:ScoreGroupKey|null)setActiveFilterKey(key);return{...tableState,activeFilterKey,changeFilter};}五、通用模型层与工具函数业务解耦核心完全抽离分组规则、文案、过滤逻辑实现业务可配置、快速扩展不侵入组件与接口// src/models/business/score-group.ts// 1. 分组分值区间配置可全局配置修改exportconstSCORE_GROUP_RANGE_MAP:RecordScoreGroupKey,[number,number]{high:[5,5],// 高分优档normal:[3,4],// 达标中档low:[1,2],// 低分待优化};// 2. 分组展示文案映射支持国际化抽取exportconstSCORE_GROUP_LABEL_MAP:RecordScoreGroupKey,string{high:优档,normal:达标,low:待优化,};// 3. 分组数组循环渲染卡片使用exportconstALL_SCORE_GROUPS:ScoreGroupKey[][high,normal,low];// 泛型通用过滤函数只要包含score字段的数组均可复用exportfunctionfilterRecordByScoreGroupTextends{score:number}(list:T[],group:ScoreGroupKey):T[]{const[min,max]SCORE_GROUP_RANGE_MAP[group];returnlist.filter(itemitem.scoreminitem.scoremax);}// 泛型通用计数函数exportfunctioncountRecordByScoreGroupTextends{score:number}(list:T[],group:ScoreGroupKey):number{const[min,max]SCORE_GROUP_RANGE_MAP[group];returnlist.filter(itemitem.scoreminitem.scoremax).length;}六、通用UI组件标准化实现6.1 DataStatsBar 通用统计卡片组件纯展示交互组件仅接收外部传入筛选状态与回调无内部数据请求完全解耦核心交互逻辑加载中展示Antd Spin占位数量为0的分组按钮置灰禁用禁止点击当前选中分组高亮样式再次点击同一分组自动清空筛选完善无障碍属性role/aria-label满足WCAG规范// src/dashboard/components/data-stats-bar/index.tsxtypeStatsBarProps{activeFilter:ScoreGroupKey|null;onFilterChange:(key:ScoreGroupKey|null)void;};exportfunctionDataStatsBar(props:StatsBarProps){const{activeFilter,onFilterChange}props;const{data,loading}useBizStats();if(loading||!data){returndiv className{styles.loadWrap}Spin sizesmall/统计数据加载中/div;}// 基于模型层批量生成卡片配置constcardConfigListALL_SCORE_GROUPS.map(key({key,label:SCORE_GROUP_LABEL_MAP[key],count:countRecordByScoreGroup(data.record_list,key),}));// 卡片点击逻辑consthandleCardClick(item:typeofcardConfigList[0]){if(item.count0)return;// 重复点击取消筛选constnextKeyactiveFilteritem.key?null:item.key;onFilterChange(nextKey);};return(div className{styles.barWrap}rolegrouparia-label业务数据统计分组div className{styles.cardContainer}{cardConfigList.map(item(button key{item.key}className{clsx(styles.statCard,activeFilteritem.keystyles.cardActive,item.count0styles.cardDisabled)}onClick{()handleCardClick(item)}title{${item.label}共${item.count}条数据}span className{styles.colorDot}/span className{styles.cardLabel}{item.label}/spanspan className{styles.cardNum}{item.count}/span/button))}/divspan className{styles.tipText}*默认统计近30天全部分类数据/span/div);}6.2 通用评分标签组件统一分数-视觉映射规则全局复用在表格、卡片、详情页// src/common/components/score-tag.tsxtypeScoreTagProps{score:number};exportfunctionScoreTag({score}:ScoreTagProps){constgetTagColor(s:number){if(s5)returngold;if(s3)returnsuccess;returnerror;};returnTag color{getTagColor(score)}{score}分/Tag;}七、Mock模拟服务通用设计脱敏本地调试模拟接口数据逻辑通用可直接迁移至任意统计业务模拟登录操作人信息从Cookie读取当前登录账号自动维护记录评分、总分、平均分、最低分聚合字段统一追加操作时间线日志保证Mock数据结构和线上接口完全对齐核心逻辑新增一条评分记录后自动重算分组聚合数值无需手动维护统计量八、通用权限控制方案后台统一返回用户权限标识字符串示例通用权限keyplatform.biz.stats全局权限工具函数checkPermission(权限标识)判断用户权限无权限时直接不渲染整个统计模块而非CSS隐藏减少DOM渲染开销// 工作台页面权限使用 const canViewStats checkPermission(platform.biz.stats); return ( div classNamedashboard-container {canViewStats ( DataStatsBar activeFilter{filterKey} onFilterChange{changeFilter} / FilteredRecordTable / / )} {/* 其他页面模块 */} /div );九、标准化分层架构与技术最佳实践9.1 四层分层规范通用企业前端标准┌─────────────────────────────────────┐ │ Components 展示层 │ 纯UI渲染不处理请求、业务计算 ├─────────────────────────────────────┤ │ Custom Hooks 逻辑层 │ 状态管理、接口调用、交互逻辑封装 ├─────────────────────────────────────┤ │ API Layer 请求层 │ 统一接口地址、参数、响应解析、异常 ├─────────────────────────────────────┤ │ Models 模型工具层 │ 类型定义、分组规则、通用计算函数 └─────────────────────────────────────┘9.2 核心技术选型通用无业务绑定React Ant Design TypeScript CSS Modules ViteTS泛型通用工具函数跨业务复用全链路类型约束CSS Modules样式隔离避免多业务模块样式冲突useStateuseCallback轻量状态管理无Redux等重型状态库冗余9.3 技术设计决策通用思路技术选择实现方案通用优势数据筛选前端内存过滤一次请求全量数据切换筛选无网络延迟减轻后端查询压力状态管理组件内本地state单模块独立无全局状态污染维护成本低异常处理三层降级提示接口异常 → 业务错误文案 → 兜底默认提示用户友好周期统计内置30天计算工具可扩展自定义起止时间适配7天/90天等其他统计需求扩展能力配置化分组模型新增统计分组仅修改SCORE_GROUP_RANGE_MAP无需修改组件/接口9.4 通用性能优化手段数据复用统计卡片、表格共用同一份接口返回明细不重复请求权限条件渲染无权限直接销毁组件减少JS执行与DOM节点筛选快速重置清空筛选时直接置空表格状态不等待接口返回纯函数工具计数、过滤逻辑无副作用配合React缓存减少重计算十、通用目录结构脱敏适配所有后台统计模块src/ ├── api/ │ └── business-stats.ts# 通用统计接口、请求函数、顶层类型├── models/ │ └── business/ │ └── score-group.ts# 分组配置、泛型过滤/计数工具├── dashboard/ │ ├── hooks/ │ │ ├── use-biz-stats.ts# 统计基础数据Hook│ │ └── use-filtered-record-list.ts# 筛选联动Hook│ └── components/ │ └──># 通用统计卡片组件│ └── index.module.less# 隔离样式├── common/ │ └── components/ │ └── score-tag.tsx# 全局通用评分标签└── mock/ └── business/ └── record-service.ts# 本地模拟接口服务整体方案通用复用总结该套实现完全剥离专属业务名词、接口路径、权限标识、业务字段仅保留统计筛选联动通用技术逻辑可一键复用于质检统计、工单评价、客户回访评分、巡检打分等任意后台数据看板场景。核心技术落地要点分层解耦UI、逻辑、请求、数据模型四层分离单一职责前端本地筛选优化交互体验降低后端接口压力TypeScript泛型抽象工具函数跨业务复用保障类型安全完整状态兜底加载、空数据、报错、禁用、选中多状态全覆盖配置化扩展新增统计分组、自定义统计周期无需改动核心组件代码。