# 智慧报价系统 — 统计报表模块开发方案 > 基于 RuoYi-Vue v3.9.2 (Spring Boot 4.0.3 + JDK 17 + Vue 2 + Element UI + ECharts 5.4.0) > 对接现有"智慧报价"模块 12 张业务表 & 真实生产数据 --- ## 目录 - [一、设计理念](#一设计理念) - [二、报表总览](#二报表总览) - [三、页面架构与路由设计](#三页面架构与路由设计) - [四、后端详细设计](#四后端详细设计) - [五、前端详细设计](#五前端详细设计) - [六、数据库查询方案(SQL 核心)](#六数据库查询方案sql核心) - [七、权限与菜单设计](#七权限与菜单设计) - [八、实施步骤与里程碑](#八实施步骤与里程碑) - [九、文件清单与代码量预估](#九文件清单与代码量预估) --- ## 一、设计理念 ### 1.1 目标 老板想看的不是原始数据的堆砌,而是**一眼能抓住的数据洞察**。因此本报表模块的核心原则: | 原则 | 说明 | |------|------| | **KPI 优先** | 每个页面顶部展示关键指标卡片(总计/环比/趋势),让老板一眼看到业务状况 | | **图文并茂** | ECharts 图表为主,表格为辅,避免纯表格枯燥 | | **层层下钻** | 从汇总趋势 → 点击进入明细 → 再进详情,支持交互式探索 | | **聚焦决策** | 报表要能回答老板的问题:花了多少钱?省了多少钱?哪家供应商最好? | ### 1.2 技术选型理由 | 技术 | 为什么选 | |------|---------| | **ECharts 5.4.0** | 项目已有依赖(`package.json` 中 `echarts: 5.4.0`),无需额外安装 | | **Vue 2 + Element UI** | 项目现有技术栈,风格统一 | | **MyBatis 手写 SQL** | 报表查询需要多表聚合,手写 SQL 最灵活 | | **RuoYi BaseController** | 延续 `startPage()` + `getDataTable()` 分页模式,与现有代码一致 | --- ## 二、报表总览 ### 2.1 报表菜单结构 在**智慧报价**菜单下新增一个分组 **统计分析**,包含 4 个子页面: ``` 智慧报价 (menu_id=2000) ├── 物料管理 (2001) ├── 供应商管理 (2002) ├── 报价请求 (2003) ├── 供应商报价 (2004) ├── 智慧比价 (2005) ├── 采购单 (2006) ├── 供应商评价 (2007) ├── 订单异议 (2008) ├── 交易记录 (2009) ├── 租户管理 (2010) ├── ═══════════════════════════════ ├── 📊 统计分析 (2011) ← 新增目录菜单(父节点) │ ├── 📈 采购总览看板 (2012) ← 仪表盘首页 │ ├── 💰 采购成本分析 (2013) ← 成本趋势与对比 │ └── 🏆 供应商绩效 (2014) ← 供应商评分与排名 ``` ### 2.2 四个报表页面说明 | 页面 | 路由 path | 定位 | 老板能回答什么问题 | |------|-----------|------|-------------------| | **采购总览看板** | `/bid/report/dashboard` | 仪表盘首页,一屏总览 | 本月花了多少钱?采购趋势怎么样?报价情况如何? | | **采购成本分析** | `/bid/report/cost` | 成本深度分析 | 比预算省了多少?各品类花了多少?同物料价格对比? | | **供应商绩效** | `/bid/report/supplier` | 供应商评分与排名 | 哪家供应商最好?哪家经常出问题?交期/质量/服务排名? | --- ## 三、页面架构与路由设计 ### 3.1 前端路由注册 在 `ruoyi-ui/src/router/index.js` 的 `dynamicRoutes` 中添加: ```js // ── 统计分析 路由 ── { path: '/bid/report/dashboard', component: Layout, hidden: true, permissions: ['bid:report:dashboard'], children: [{ path: '', component: () => import('@/views/bid/report/dashboard'), name: 'ReportDashboard', meta: { title: '采购总览看板', activeMenu: '/bid/report' } }] }, { path: '/bid/report/cost', component: Layout, hidden: true, permissions: ['bid:report:cost'], children: [{ path: '', component: () => import('@/views/bid/report/cost'), name: 'ReportCost', meta: { title: '采购成本分析', activeMenu: '/bid/report' } }] }, { path: '/bid/report/supplier', component: Layout, hidden: true, permissions: ['bid:report:supplier'], children: [{ path: '', component: () => import('@/views/bid/report/supplier'), name: 'ReportSupplier', meta: { title: '供应商绩效', activeMenu: '/bid/report' } }] } ``` ### 3.2 菜单 SQL 在 `bid_tables.sql` 或系统菜单表中执行以下 SQL(先查询最大 menu_id 再插入): ```sql -- 父菜单:统计分析 (2011) INSERT IGNORE INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time) VALUES(2011, '统计分析', 2000, 11, 'report', NULL, 1, 0, 'M', '0', '0', 'bid:report:list', 'chart', 'admin', NOW()); -- 子菜单:采购总览看板 (2012) INSERT IGNORE INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time) VALUES(2012, '采购总览看板', 2011, 1, 'dashboard', 'bid/report/dashboard', 1, 0, 'C', '0', '0', 'bid:report:dashboard', 'dashboard', 'admin', NOW()); -- 子菜单:采购成本分析 (2013) INSERT IGNORE INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time) VALUES(2013, '采购成本分析', 2011, 2, 'cost', 'bid/report/cost', 1, 0, 'C', '0', '0', 'bid:report:cost', 'money', 'admin', NOW()); -- 子菜单:供应商绩效 (2014) INSERT IGNORE INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time) VALUES(2014, '供应商绩效', 2011, 3, 'supplier', 'bid/report/supplier', 1, 0, 'C', '0', '0', 'bid:report:supplier', 'star', 'admin', NOW()); ``` --- ## 四、后端详细设计 ### 4.1 包结构 ``` ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/ └── BizReportController.java ← 报表统计 Controller ruoyi-system/src/main/java/com/ruoyi/system/ ├── domain/bid/ │ ├── ReportDashboardVO.java ← 看板数据 VO │ ├── ReportCostVO.java ← 成本分析 VO │ └── ReportSupplierVO.java ← 供应商绩效 VO ├── mapper/bid/ │ └── BizReportMapper.java ← 报表 Mapper 接口 ├── service/bid/ │ ├── IBizReportService.java ← 报表 Service 接口 │ └── impl/ │ └── BizReportServiceImpl.java ← 报表 Service 实现 ruoyi-system/src/main/resources/mapper/bid/ └── BizReportMapper.xml ← 报表 SQL 映射 ``` ### 4.2 Domain / VO 设计 #### ReportDashboardVO.java — 看板数据 ```java public class ReportDashboardVO { // ====== 顶部 KPI 卡片 ====== private KpiCard totalPurchaseAmount; // 采购总额(含环比) private KpiCard totalRfqCount; // RFQ总数 private KpiCard totalPoCount; // 采购单数 private KpiCard activeSupplierCount; // 活跃供应商数 // ====== 图表数据 ====== private List monthlyTrend; // 月度采购趋势 private List rfqStatusDist; // RFQ状态分布 private List topSuppliers; // Top供应商排名 private List recentActivities; // 最近动态 // ====== 内部类 ====== @Data public static class KpiCard { private String label; // 指标名 private BigDecimal value; // 当前值 private double changeRate; // 环比(%) private String unit; // 单位 private String trend; // up/down } @Data public static class MonthTrend { private String month; // "2026-01" private BigDecimal amount; // 金额 private int count; // 单数 } @Data public static class StatusDist { private String status; private String statusLabel; private int count; private double percent; } @Data public static class SupplierRank { private Long supplierId; private String supplierName; private BigDecimal totalAmount; // 采购金额 private int poCount; // 采购次数 private double avgScore; // 评价均分 } @Data public static class RecentActivity { private String time; private String type; // PO / QUOTE / EVAL / OBJECTION private String desc; private String linkId; } } ``` #### ReportCostVO.java — 成本分析 ```java public class ReportCostVO { // ====== 顶部汇总 ====== private CostSummary summary; @Data public static class CostSummary { private BigDecimal totalExpected; // 预算总额(RFQ期望价) private BigDecimal totalActual; // 实际采购总额 private BigDecimal savedAmount; // 节省金额 private double savedRate; // 节省比例 } // ====== 月度成本趋势 ====== private List costTrend; @Data public static class CostTrend { private String month; private BigDecimal expectedAmount; private BigDecimal actualAmount; private BigDecimal savedAmount; } // ====== 品类采购分布 ====== private List categoryDist; @Data public static class CategoryDist { private String categoryName; private BigDecimal amount; private int materialCount; private double percent; } // ====== 单次RFQ比价详情 ====== private List rfqDetails; @Data public static class RfqCompareDetail { private Long rfqId; private String rfqNo; private String rfqTitle; private BigDecimal expectedTotal; private BigDecimal lowestQuote; private BigDecimal acceptedQuote; private BigDecimal savedAmount; private int supplierCount; } } ``` #### ReportSupplierVO.java — 供应商绩效 ```java public class ReportSupplierVO { // ====== 评分排名 ====== private List rankings; @Data public static class SupplierScore { private Long supplierId; private String supplierName; private int evalCount; // 评价次数 private double qualityAvg; // 质量均分 private double deliveryAvg; // 交期均分 private double serviceAvg; // 服务均分 private double priceAvg; // 价格均分 private double totalAvg; // 综合均分 private int poCount; // 采购次数 private BigDecimal poAmount; // 采购金额 private double winRate; // 中标率 % } // ====== 供应商评价雷达图数据 ====== private List radarData; @Data public static class RadarData { private String supplierName; private double quality; private double delivery; private double service; private double price; } // ====== 月度评分趋势 ====== private List scoreTrends; @Data public static class ScoreTrend { private String month; private Long supplierId; private String supplierName; private double score; } // ====== 异议统计 ====== private List objectionStats; @Data public static class ObjectionStat { private Long supplierId; private String supplierName; private int objectionCount; private int resolvedCount; private String topReason; } } ``` ### 4.3 Controller 设计 ```java @RestController @RequestMapping("/bid/report") public class BizReportController extends BaseController { @Autowired private IBizReportService reportService; /** 采购总览看板数据 */ @PreAuthorize("@ss.hasPermi('bid:report:dashboard')") @GetMapping("/dashboard") public AjaxResult dashboard() { return success(reportService.getDashboard()); } /** 采购成本分析数据 */ @PreAuthorize("@ss.hasPermi('bid:report:cost')") @GetMapping("/cost") public AjaxResult costAnalysis( @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM") String startMonth, @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM") String endMonth) { return success(reportService.getCostAnalysis(startMonth, endMonth)); } /** 供应商绩效数据 */ @PreAuthorize("@ss.hasPermi('bid:report:supplier')") @GetMapping("/supplier") public AjaxResult supplierPerformance() { return success(reportService.getSupplierPerformance()); } /** 导出报表 Excel */ @PreAuthorize("@ss.hasPermi('bid:report:list')") @Log(title = "报表导出", businessType = BusinessType.EXPORT) @PostMapping("/export/{type}") public void export(HttpServletResponse response, @PathVariable String type) { // 使用 RuoYi ExcelUtil 导出,type=dashboard/cost/supplier } } ``` ### 4.4 Service 实现概要 ```java @Service public class BizReportServiceImpl implements IBizReportService { @Autowired private BizReportMapper mapper; @Override public ReportDashboardVO getDashboard() { ReportDashboardVO vo = new ReportDashboardVO(); // 1. KPI 卡片:本月数据 vs 上月 vo.setTotalPurchaseAmount(calcKpi("PO", "totalAmount")); vo.setTotalRfqCount(calcKpi("RFQ", "count")); vo.setTotalPoCount(calcKpi("PO", "count")); vo.setActiveSupplierCount(calcKpi("SUPPLIER", "activeCount")); // 2. 月度趋势(近12个月) vo.setMonthlyTrend(mapper.selectMonthlyTrend()); // 3. RFQ 状态分布 vo.setRfqStatusDist(mapper.selectRfqStatusDist()); // 4. Top 5 供应商排名 vo.setTopSuppliers(mapper.selectTopSuppliers()); // 5. 最近10条动态 vo.setRecentActivities(mapper.selectRecentActivities()); return vo; } // ... 其他方法 } ``` ### 4.5 Mapper XML 核心 SQL #### BizReportMapper.xml ```xml ``` --- ## 五、前端详细设计 ### 5.1 文件结构 ``` ruoyi-ui/src/views/bid/report/ ├── dashboard.vue ← 采购总览看板 ├── cost.vue ← 采购成本分析 ├── supplier.vue ← 供应商绩效 └── components/ ← 可复用组件 ├── KpiCard.vue ← 指标卡片 └── TrendChart.vue ← 趋势图表封装 ruoyi-ui/src/api/bid/ └── report.js ← API 封装 ``` ### 5.2 API 封装(report.js) ```js import request from '@/utils/request' const baseUrl = '/bid/report' export const getDashboard = () => request({ url: baseUrl + '/dashboard', method: 'get' }) export const getCostAnalysis = (params) => request({ url: baseUrl + '/cost', method: 'get', params }) export const getSupplierPerformance = () => request({ url: baseUrl + '/supplier', method: 'get' }) export const exportReport = (type, data) => request({ url: baseUrl + '/export/' + type, method: 'post', data, responseType: 'blob' }) ``` ### 5.3 页面一:采购总览看板(dashboard.vue) 布局方案: ``` ┌─────────────────────────────────────────────────────────┐ │ 📊 采购总览看板 │ ├────────────┬────────────┬────────────┬──────────────────┤ │ 采购总额 │ RFQ总数 │ 采购单数 │ 活跃供应商 │ │ ¥207,820 │ 7 单 │ 3 单 │ 5 家 │ │ ↑ 12.5% │ ↑ 40% │ 持平 │ ↑ 25% │ ├────────────┴────────────┴────────────┴──────────────────┤ │ │ │ ┌───────────────────┐ ┌─────────────────────────┐ │ │ │ 月度采购趋势 │ │ RFQ 状态分布 │ │ │ │ (折线图+柱状图) │ │ (饼图) │ │ │ │ │ │ │ │ │ └───────────────────┘ └─────────────────────────┘ │ │ │ │ ┌───────────────────┐ ┌─────────────────────────┐ │ │ │ 供应商排名 Top5 │ │ 最新动态 │ │ │ │ (横向柱状图) │ │ (时间线列表) │ │ │ │ │ │ │ │ │ └───────────────────┘ └─────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ ``` **关键代码片段:** #### ECharts 图表配置示例(月度趋势) ```javascript // 在 dashboard.vue 的 methods 中 initTrendChart(data) { const chart = echarts.init(document.getElementById('trendChart')) const months = data.map(d => d.month) const amounts = data.map(d => d.amount) const counts = data.map(d => d.count) chart.setOption({ tooltip: { trigger: 'axis' }, legend: { data: ['采购金额', '采购单数'] }, grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, xAxis: { type: 'category', data: months }, yAxis: [ { type: 'value', name: '金额(元)' }, { type: 'value', name: '单数' } ], series: [ { name: '采购金额', type: 'bar', data: amounts, itemStyle: { color: '#409EFF' }, label: { show: true, formatter: '¥{c}', position: 'top' } }, { name: '采购单数', type: 'line', yAxisIndex: 1, data: counts, itemStyle: { color: '#67C23A' } } ] }) } ``` #### KPI 卡片组件(KpiCard.vue) ```vue ``` ### 5.4 页面二:采购成本分析(cost.vue) 布局方案: ``` ┌─────────────────────────────────────────────────────────┐ │ 💰 采购成本分析 │ ├─────────────────────────────────────────────────────────┤ │ 预算总额: ¥XXX 实际采购: ¥XXX 节省: ¥XXX (XX%) │ ├──────────────────────┬──────────────────────────────────┤ │ │ │ │ 月度预算 vs 实际 │ 品类采购分布 │ │ (双柱状对比图) │ (饼图/环形图) │ │ │ │ ├──────────────────────┴──────────────────────────────────┤ │ │ │ RFQ 比价明细(表格) │ │ ┌──────┬──────┬──────┬──────┬──────┬──────┬──────┐ │ │ │询价单 │预算价 │最低价 │采纳价 │节省额 │比价数 │操作 │ │ │ ├──────┼──────┼──────┼──────┼──────┼──────┼──────┤ │ │ │ ... │ ... │ ... │ ... │ ... │ ... │ 详情 │ │ │ └──────┴──────┴──────┴──────┴──────┴──────┴──────┘ │ │ │ └─────────────────────────────────────────────────────────┘ ``` **核心逻辑:** 1. 查询所有 completed 的 RFQ,关联 RFQ Item 中的 `expected_price` 作为预算价 2. 查询对应被采纳的报价(`quotation.status = 'accepted'`)作为实际采购价 3. `节省额 = 预算总额 - 实际采购总额` 4. 表格中每行是一个 RFQ,点击"详情"跳转到比价详情页 ### 5.5 页面三:供应商绩效(supplier.vue) 布局方案: ``` ┌─────────────────────────────────────────────────────────┐ │ 🏆 供应商绩效 │ ├─────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────┐ │ │ │ 供应商综合评分排名(表格) │ │ │ │ 排名 │ 供应商 │ 质量 │ 交期│ 服务│ 价格│ 综合│ 操作│ │ │ │ 1 │ 华顺达 │ 5.0 │ 4.0│ 5.0│ 4.0│ 4.5│ 详情│ │ │ │ 2 │ 博远 │ 5.0 │ 3.0│ 5.0│ 5.0│ 4.5│ 详情│ │ │ │ ... │ ... │ ... │ ...│ ...│ ...│ ...│ ... │ │ │ └─────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────┐ ┌────────────────────────┐ │ │ │ 供应商评价雷达图 │ │ 中标率分析 │ │ │ │ (可切换供应商) │ │ (柱状图) │ │ │ │ │ │ │ │ │ └─────────────────────┘ └────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────┐ │ │ │ 订单异议统计(表格) │ │ │ │ 供应商 │ 异议数 │ 已解决 │ 解决率 │ 操作 │ │ │ └─────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────┘ ``` **核心交互:** 1. 评分排名表格 - 可点击表头排序 2. 雷达图 - 点击表格行可切换显示的供应商 3. 中标率 - 柱状图展示每个供应商的报价次数 vs 中标次数 4. 异议统计 - 展示各供应商的订单问题情况 --- ## 六、数据库查询方案(SQL 核心) ### 6.1 关键业务指标 SQL #### 月度采购金额与环比 ```sql -- 当月采购总额 SELECT COALESCE(SUM(total_amount), 0) AS currentMonthAmount FROM biz_purchase_order WHERE status IN ('confirmed', 'closed', 'delivered') AND DATE_FORMAT(create_time, '%Y-%m') = DATE_FORMAT(NOW(), '%Y-%m'); -- 上月采购总额(环比基准) SELECT COALESCE(SUM(total_amount), 0) AS lastMonthAmount FROM biz_purchase_order WHERE status IN ('confirmed', 'closed', 'delivered') AND DATE_FORMAT(create_time, '%Y-%m') = DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 1 MONTH), '%Y-%m'); -- 环比 = (当月 - 上月) / 上月 * 100 ``` #### 预算节省分析 ```sql -- 每个 RFQ 的预算 vs 实际采纳金额 SELECT r.rfq_id, r.rfq_no, r.rfq_title, ri.total_expected AS expectedTotal, COALESCE(q.total_amount, 0) AS acceptedQuote, (ri.total_expected - COALESCE(q.total_amount, 0)) AS savedAmount FROM biz_rfq r JOIN ( SELECT rfq_id, SUM(quantity * expected_price) AS total_expected FROM biz_rfq_item GROUP BY rfq_id ) ri ON r.rfq_id = ri.rfq_id LEFT JOIN biz_quotation q ON r.rfq_id = q.rfq_id AND q.status = 'accepted' WHERE r.status = 'completed'; ``` #### 供应商中标率 ```sql SELECT q.supplier_id, s.supplier_name, COUNT(*) AS totalQuotes, SUM(CASE WHEN q.status = 'accepted' THEN 1 ELSE 0 END) AS winCount, ROUND(SUM(CASE WHEN q.status = 'accepted' THEN 1 ELSE 0 END) / COUNT(*) * 100, 1) AS winRate FROM biz_quotation q JOIN biz_supplier s ON q.supplier_id = s.supplier_id WHERE q.status IN ('accepted', 'rejected') GROUP BY q.supplier_id, s.supplier_name ORDER BY winRate DESC; ``` ### 6.2 性能优化建议 | 优化点 | 方案 | |--------|------| | **大数据量** | 报表查询加时间范围过滤,默认只查最近12个月 | | **缓存** | 看板数据用 Redis 缓存 5 分钟(利用 RuoYi 已有 Redis 集成) | | **复杂统计** | 新建物化视图或定时任务汇总到统计表(后续优化) | --- ## 七、权限与菜单设计 ### 7.1 权限标识 | 权限标识 | 对应页面 | 说明 | |---------|---------|------| | `bid:report:list` | 统计分析目录 | 父菜单显示 | | `bid:report:dashboard` | 采购总览看板 | 仪表盘页面 | | `bid:report:cost` | 采购成本分析 | 成本页面 | | `bid:report:supplier` | 供应商绩效 | 供应商页面 | ### 7.2 权限分配 在系统管理 → 角色管理中,为管理员角色勾选新增的菜单权限: - 统计分析 → 采购总览看板 - 统计分析 → 采购成本分析 - 统计分析 → 供应商绩效 --- ## 八、实施步骤与里程碑 ### Phase 1:后端基础(预计 1 天) | 步骤 | 内容 | 文件 | |------|------|------| | 1.1 | 创建 3 个 VO 类 | `ReportDashboardVO.java`, `ReportCostVO.java`, `ReportSupplierVO.java` | | 1.2 | 创建 Mapper 接口 + XML | `BizReportMapper.java`, `BizReportMapper.xml` | | 1.3 | 创建 Service 接口 + 实现 | `IBizReportService.java`, `BizReportServiceImpl.java` | | 1.4 | 创建 Controller | `BizReportController.java` | | 1.5 | 测试 API | 使用 Swagger 或浏览器验证 JSON 返回 | ### Phase 2:前端页面(预计 1.5 天) | 步骤 | 内容 | 文件 | |------|------|------| | 2.1 | 创建 API 封装 | `src/api/bid/report.js` | | 2.2 | 搭建看板页面 | `dashboard.vue` + `KpiCard.vue` | | 2.3 | 搭建成本分析页面 | `cost.vue` | | 2.4 | 搭建供应商绩效页面 | `supplier.vue` | | 2.5 | 集成 ECharts 图表 | 在各页面中初始化 | ### Phase 3:集成上线(预计 0.5 天) | 步骤 | 内容 | |------|------| | 3.1 | 注册路由到 `router/index.js` | | 3.2 | 执行菜单 SQL,授权 admin 角色 | | 3.3 | 前后端联调测试 | | 3.4 | 展示给老板看,收集反馈 | ### 总计工期:**约 3 天** --- ## 九、文件清单与代码量预估 ### 后端(7 个文件) | 文件 | 路径 | 预估行数 | |------|------|---------| | `BizReportController.java` | `ruoyi-admin/.../controller/bid/` | ~60 行 | | `IBizReportService.java` | `ruoyi-system/.../service/bid/` | ~20 行 | | `BizReportServiceImpl.java` | `ruoyi-system/.../service/bid/impl/` | ~120 行 | | `BizReportMapper.java` | `ruoyi-system/.../mapper/bid/` | ~15 行 | | `BizReportMapper.xml` | `ruoyi-system/.../mapper/bid/` | ~200 行 | | 3 个 VO 类 | `ruoyi-system/.../domain/bid/` | ~300 行 | | **小计** | | **~715 行** | ### 前端(5 个文件) | 文件 | 路径 | 预估行数 | |------|------|---------| | `report.js` | `src/api/bid/` | ~30 行 | | `dashboard.vue` | `src/views/bid/report/` | ~350 行 | | `cost.vue` | `src/views/bid/report/` | ~300 行 | | `supplier.vue` | `src/views/bid/report/` | ~350 行 | | `KpiCard.vue` | `src/views/bid/report/components/` | ~80 行 | | **小计** | | **~1,110 行** | ### SQL 变更(1 个脚本) | 文件 | 用途 | 行数 | |------|------|------| | `report_menu.sql` | 菜单 SQL | ~20 行 | ### 总计:约 **12 个文件**,**~1,800 行代码** --- ## 附录:与老板汇报话术参考 > **老板,我做了一个统计分析模块,分为三个页面:** > > 1. **采购总览看板** — 一打开就能看到本月花了多少钱、发了多少询价单、供应商活跃情况,还配了趋势图和排名。 > 2. **采购成本分析** — 对比预算和实际花销,看哪些品类花钱多,每次比价节省了多少,一眼看清钱花在哪。 > 3. **供应商绩效** — 给每个供应商打分排名(质量/交期/服务/价格),哪家好哪家差一目了然,还有异常统计。 > > **数据都来自我们系统里已有的业务数据,不需要额外录入。预计 3 天可以开发完成。** --- > **文档版本:** v1.0 > **编写日期:** 2026-06-03 > **适用范围:** 福安德智慧报价平台