feat(bid): 完成物料管理模块全功能开发

1. 新增物料详情页路由、菜单与接口,支持查看物料报价与信息
2. 重构物料列表页面,新增品牌筛选、表格样式优化与详情跳转
3. 扩展物料实体与数据库字段,新增材质、用途、性能参数等字段
4. 新增供应商/甲方报价查询、批量对比、同名称物料匹配接口
5. 新增物料详情组件,包含基础信息、供应商报价、甲方报价标签页
6. 修复比价路由跳转路径错误,调整数据库密码配置
7. 新增物料相关SQL脚本与初始化数据
This commit is contained in:
2026-05-29 08:58:58 +08:00
parent c718ec4076
commit e521b0dfeb
26 changed files with 4871 additions and 41 deletions

View File

@@ -0,0 +1,957 @@
# 福安德智慧报价平台 — 完整开发方案
> 基于 RuoYi-Vue v3.9.2 (Spring Boot 4.0.3 + JDK 17 + Vue 2 + Element UI)
> 融合 PPT《报价比对系统》5大板块 + XLSX《电气自动化设备综合管理系统_V1》27个Sheet数据
> 对接现有项目12个已完成模块
---
## 目录
- [一、项目全景与数据资产](#一项目全景与数据资产)
- [二、板块一:物料信息](#二板块一物料信息)
- [三、板块二:物料详情](#三板块二物料详情)
- [四、板块三:供应商管理](#四板块三供应商管理)
- [五、板块四:报价商门户(供应商端)](#五板块四报价商门户供应商端)
- [六、板块五:甲方报价单](#六板块五甲方报价单)
- [七、报价单管理与指派系统](#七报价单管理与指派系统)
- [八、电气设备数据初始化方案](#八电气设备数据初始化方案)
- [九、开发优先级与里程碑](#九开发优先级与里程碑)
- [十、关键接口清单](#十关键接口清单)
- [十一、权限与安全设计](#十一权限与安全设计)
---
## 一、项目全景与数据资产
### 1.1 PPT五大板块映射
| PPT板块 | 对应功能 | 现有进度 | 开发类型 |
|---------|---------|---------|---------|
| 智采系统-物料信息 | 物料CRUD + 分类树 + 性能参数JSON | `biz_material` 已有基础字段 | 扩展增强 |
| 智采系统-物料详情 | 详情页 + 3个Tab(历史报价/甲方报价/同比) | 未开发 | 新建 |
| 智采系统-供应商管理 | 供货清单 + 报价单管理 + 指派界面 | `biz_supplier` 已有基础 | 扩展增强 |
| 智采系统-报价商 | 供应商门户(已报项/可报项/报价界面) | 未开发 | 新建 |
| 给甲方报价单 | 子RFQ拆解 + 成本回填 + 历史版本 + 横向对比 | `biz_client_quote` 基础已有 | 核心增强 |
### 1.2 XLSX数据资产清单
Excel中包含了完整的电气设备业务数据共27个Sheet
| Sheet | 名称 | 行数 | 用途 |
|-------|------|------|------|
| 1 | 00_导航首页 | 24 | 系统导航和功能入口说明 |
| 2 | 01_项目报价单(fad给甲方) | 52 | 甲方报价模板(含品牌/型号/数量/折扣率) |
| 3 | 02_报价汇总 | 27 | 按类汇总 + 加价系数 + 对外报价 |
| 4 | 10_变频器比价 | 48 | 汇川/禾望/西门子/ABB 三家比价 |
| 5 | 11_整流单元比价 | 37 | 整流/制动/回馈单元比价 |
| 6 | 12_PLC比价 | 15 | CPU+模块比价 |
| 7 | 13_低压电器比价 | 22 | 断路器/接触器/热继电器比价 |
| 8 | 14_电缆线槽比价 | 25 | 电缆/控制线/线槽综合比价 |
| 9-19 | 20_变频器型号库 ~ 30_网关型号库 | 321+ | 全品类型号数据库 |
| 20 | 31_品牌汇总 | 22 | 各品牌型号数量统计 |
### 1.3 核心业务流程
```
甲方需求 → 创建甲方报价单 → 拆解为内部RFQ(子报价单)
→ 指派供应商(可报项) → 供应商报价 → 比价选择
→ 成本回填甲方报价单 → 生成最终甲方报价 → 甲方确认
→ 生成采购单 → 交付 → 评价/异议处理
```
---
## 二、板块一:物料信息
### 2.1 现有基础
`biz_material` 表已有字段:
- `material_id`, `tenant_id`, `category_id`, `material_code`, `material_name`
- `spec`, `unit`, `brand`, `description`
- `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`
### 2.2 扩展字段
```sql
ALTER TABLE biz_material ADD COLUMN (
-- PPT要求字段
manufacturer VARCHAR(100) COMMENT '厂家/品牌(与brand一致作为冗余筛选)',
model_size VARCHAR(200) COMMENT '型号/尺寸(如MD500T37G, TMY-60×6)',
performance_params TEXT COMMENT '性能参数(JSON格式: {"功率":"37kW","电压":"380V"})',
material VARCHAR(100) COMMENT '材质(铜/铝合金/PVC等)',
purpose VARCHAR(500) COMMENT '用途(如"通用负载","风机水泵")',
remarks TEXT COMMENT '备注',
category_tree_path VARCHAR(500) COMMENT '分类路径(冗余,如"1/5/23")',
spec_comparison_group VARCHAR(100) COMMENT '横向对比分组标识',
-- 扩展业务字段
min_stock INT DEFAULT 0 COMMENT '最低库存预警',
unit_weight DECIMAL(10,4) COMMENT '单重(kg)',
image_url VARCHAR(500) COMMENT '物料图片',
data_source VARCHAR(20) DEFAULT 'manual' COMMENT '数据来源(manual/import/excel)',
version INT DEFAULT 1 COMMENT '乐观锁版本号'
);
-- 型号唯一索引(防止重复录入同规格物料)
ALTER TABLE biz_material ADD UNIQUE INDEX idx_model_manufacturer (manufacturer, model_size);
```
### 2.3 性能参数JSON规范
性能参数使用JSON格式存储前端动态渲染为键值对表格
```json
// 变频器示例
{
"功率": "37kW",
"电压": "380V",
"电流": "72A",
"过载能力": "150%/60s",
"通讯接口": "RS485/PROFINET",
"防护等级": "IP20"
}
// 电缆示例
{
"芯数×截面": "3×70+1×35",
"额定电压": "0.6/1kV",
"外径": "42mm",
"载流量": "210A",
"护套材质": "PVC铠装"
}
```
**前端组件**使用Element UI动态表单`el-form` + `el-table`),每行=参数名+参数值+单位支持增删行。保存时组装为JSON字符串读取时`JSON.parse`后渲染为只读表格。
### 2.4 前端页面结构
```
物料信息列表页 (/bid/material)
├── 左侧:物料分类树 (复用 biz_material_category)
│ ├── 树节点点击 → 右侧表格过滤
│ └── 面包屑导航(基于category_tree_path)
├── 右侧:物料表格
│ ├── 顶部筛选栏
│ │ ├── 厂家下拉(去重,从manufacturer字段DISTINCT)
│ │ ├── 型号模糊搜索(输入前缀智能联想)
│ │ ├── 分类级联选择器
│ │ └── 关键词搜索
│ ├── 表格列:编码 | 名称 | 厂家 | 型号 | 材质 | 用途 | 单位 | 操作
│ └── 操作按钮:详情 | 编辑 | 删除 | 加入对比篮
└── 新增/编辑对话框(抽屉形式)
├── 基础信息(名称/分类/厂家/型号/材质/用途/单位)
├── 性能参数动态表单(支持增删行)
├── 规格明细(可扩展多规格)
└── 图片上传(物料图/铭牌)
```
### 2.5 后端接口扩展
`BizMaterialController` 中新增:
| 接口 | 方法 | 说明 |
|------|------|------|
| `/bid/material/detail/{id}` | GET | 物料详情(含性能参数解析+历史报价摘要) |
| `/bid/material/manufacturer/list` | GET | 厂家下拉列表(去重) |
| `/bid/material/import` | POST | Excel批量导入(EasyExcel解析) |
| `/bid/material/export` | GET | 导出为Excel模板 |
| `/bid/material/suggest` | GET | 型号智能联想(q参数前缀匹配) |
| `/bid/material/comparison-group/{groupId}` | GET | 按对比组获取物料 |
---
## 三、板块二:物料详情
### 3.1 页面架构
采用"1+N"信息架构——1个基础信息区 + N个动态关联Tab
```
物料详情页 (/bid/material/detail/:id)
├── 顶部基础信息卡片(两栏)
│ ├── 左栏(16/24):基础信息表(物料ID/厂家/型号/材质/用途)
│ │ └── 性能参数表格(从JSON动态渲染)
│ └── 右栏(8/24)价格趋势ECharts迷你折线图
│ └── 近6个月最低报价走势(从biz_quotation_item聚合)
├── Tab 1供应商历史报价清单
├── Tab 2我方给甲方的历史报价
└── Tab 3不同品牌/规格同比
```
### 3.2 Tab 1供应商历史报价清单
**数据来源**`biz_quotation_item``biz_quotation``biz_supplier`
**展示字段**
| 字段 | 说明 |
|------|------|
| 报价日期 | biz_quotation.submit_time |
| 供应商名称 | biz_supplier.supplier_name |
| 单价(元) | biz_quotation_item.unit_price |
| 数量 | biz_quotation_item.quantity |
| 交期(周) | biz_quotation_item.delivery_days / 7 |
| 报价单号 | biz_quotation.quote_no |
| 操作 | 查看详情(点击下钻到报价单) |
**关键交互**
- 点击单价 → 抽屉展示原始报价单详情
- 价格预警高于近3个月平均价15% → 行背景红色高亮
- 按时间倒序排列
**后端API**
```java
// BizMaterialController
@GetMapping("/{id}/supplier-quotes")
public AjaxResult getSupplierQuoteHistory(@PathVariable Long id) {
// 查询 biz_quotation_item JOIN biz_quotation JOIN biz_supplier
// WHERE material_id = id ORDER BY submit_time DESC
}
```
### 3.3 Tab 2我方给甲方的历史报价
**数据来源**`biz_client_quote_item``biz_client_quote`
**展示字段**
| 字段 | 说明 |
|------|------|
| 报价日期 | client_quote.create_time |
| 甲方名称 | client_quote.client_name |
| 我方含税单价 | client_quote_item.unit_price |
| 折扣率 | client_quote_item.discount_rate |
| 最终成交价 | 含税单价 × 折扣率 |
| 状态 | sent/accepted/rejected(带标签) |
| 关联RFQ | client_quote.rfq_id → biz_rfq.rfq_no |
**功能扩展**
- 落选标注原因(新增client_quote_item.reject_reason字段)
- 版本对比(基于parent_quote_id)
### 3.4 Tab 3不同品牌/规格同比
#### 新建对比关系表
```sql
CREATE TABLE biz_material_comparison (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
group_id VARCHAR(50) NOT NULL COMMENT '对比组ID(如"VFD-37kW-380V")',
group_name VARCHAR(200) COMMENT '对比组名称(如"37kW 380V变频器对比组")',
material_id BIGINT NOT NULL COMMENT '物料ID',
counterpart_brand VARCHAR(100) COMMENT '对标品牌',
counterpart_model VARCHAR(200) COMMENT '对标型号',
comparison_notes TEXT COMMENT '对比说明(差异点)',
sort_order INT DEFAULT 0 COMMENT '组内排序',
status CHAR(1) DEFAULT '0' COMMENT '状态',
create_by VARCHAR(64),
create_time DATETIME,
update_by VARCHAR(64),
update_time DATETIME,
UNIQUE KEY uk_group_material (group_id, material_id),
KEY idx_material (material_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='物料横向对比组';
```
**功能逻辑**
1. **管理员维护对比组**(在物料详情页可直接操作)
- 为某个物料添加"对标物料"(跨品牌)
- 如汇川MD500T37G ↔ 禾望HV500-37G ↔ 西门子G120 PM240 37kW
2. **自动对比展示**
- 系统自动从 biz_comparison 对比结果中拉取对标物料的最新供应商报价
- 对比维度:单价 | 功率 | 过载能力 | 通讯接口 | 防护等级 | 适用场合
3. **数据初始化**
- 利用Excel Sheet 10-14的比价数据预置对比组
- 如Sheet 10中"37kW变频器"对应的汇川/禾望/西门子/ABB四家数据
#### 前端展示
```
┌─────────────────────────────────────────────────────────────┐
│ 37kW 380V变频器 对比组 │
├──────────────┬──────────┬──────────┬──────────┬────────────┤
│ │ 汇川 │ 禾望 │ 西门子 │ ABB │
│ │ MD500T37G │ HV500-37G│ G120 37kW│ ACS880-01 │
├──────────────┼──────────┼──────────┼──────────┼────────────┤
│ 最低报价(元) │ 6,200 │ 5,800 │ 10,500 │ 8,900 │
│ 功率(kW) │ 37 │ 37 │ 37 │ 37 │
│ 过载能力 │ 150%/60s │ 150%/60s │ 140%/60s │ 150%/60s │
│ 通讯接口 │ RS485 │ RS485 │ PROFINET │ PROFINET │
│ 防护等级 │ IP20 │ IP20 │ IP20 │ IP21 │
│ 综合评价 │ ★★★★☆ │ ★★★★★ │ ★★★☆☆ │ ★★★★☆ │
├──────────────┼──────────┴──────────┴──────────┴────────────┤
│ 推荐选型 │ 禾望HV500-37G (性价比最优) │
└──────────────┴─────────────────────────────────────────────┘
```
---
## 四、板块三:供应商管理
### 4.1 现有基础
`biz_supplier` 表已有字段supplier_id, supplier_name, contact, phone, email, address, status
### 4.2 供应商详情页重构
在现有 `/bid/supplier` 基础上,将列表页改为"列表+详情"结构,点击供应商进入详情页:
```
供应商详情页 (/bid/supplier/detail/:id)
├── Tab 1: 基础信息 (现有功能)
│ ├── 供应商名称/联系人/电话/邮箱/地址
│ └── 资质文件上传(营业执照/授权证书)
├── Tab 2: 供货清单 (新建)
│ ├── 供应商-物料关系维护
│ └── 历史报价快速查看
├── Tab 3: 报价单管理 (增强)
│ ├── 参与的RFQ列表
│ └── 报价单状态跟踪
├── Tab 4: 历史报价趋势 (新建)
│ └── ECharts折线图
└── Tab 5: 账号管理 (新建)
└── 供应商登录账号创建/权限管理
```
### 4.3 供货清单
#### 新建供应商-物料关系表
```sql
CREATE TABLE biz_supplier_material (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
supplier_id BIGINT NOT NULL,
material_id BIGINT NOT NULL,
supply_status TINYINT DEFAULT 1 COMMENT '0停供 1正常 2备选',
last_quote_price DECIMAL(18,4) COMMENT '最新报价(缓存)',
last_quote_time DATETIME COMMENT '最新报价时间',
delivery_cycle INT DEFAULT 0 COMMENT '供应周期(天)',
min_order_qty DECIMAL(15,4) DEFAULT 1 COMMENT '最小起订量',
preferred TINYINT DEFAULT 0 COMMENT '是否优选供应商',
create_time DATETIME,
UNIQUE KEY uk_supplier_material (supplier_id, material_id),
KEY idx_supplier (supplier_id),
KEY idx_material (material_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商物料供应关系';
```
**前端交互**
- 点击物料名称 → 跳转物料详情页(`/bid/material/detail/:id`)
- 支持在物料详情页"添加供应商"反向维护
- 批量导入根据Excel比价数据自动建立供应关系
### 4.4 报价单管理
供应商参与的RFQ及报价单管理增强现有 `biz_rfq`
```sql
ALTER TABLE biz_rfq ADD COLUMN (
contract_no VARCHAR(100) COMMENT '合同号',
client_name VARCHAR(100) COMMENT '甲方名称',
project_name VARCHAR(200) COMMENT '项目名称',
delivery_required_date DATE COMMENT '要求交货日期',
delivery_weeks INT COMMENT '要求交货周期(周)',
quote_deadline DATETIME COMMENT '供应商报价截止日',
total_budget DECIMAL(18,4) COMMENT '预算总额',
winner_supplier_id BIGINT COMMENT '中标供应商ID',
winner_quotation_id BIGINT COMMENT '中标报价单ID'
);
```
**报价单列表页字段**:询价单号 | 合同号 | 甲方 | 项目名称 | 状态 | 报价截止日 | 已报价/邀请数 | 操作
**状态流转**`draft(草稿) → published(已发布) → in_progress(报价中) → closed(已关闭) → completed(已完成)`
### 4.5 指派供应商界面
**触发点**RFQ发布时选择被邀请的供应商
```
┌─ 指派供应商对话框 ─────────────────────────────────┐
│ │
│ 询价单号: RFQ-2026-001 │
│ 标题: 自动化生产线控制系统采购 │
│ │
│ ☐ 全选 搜索供应商: [______] │
│ │
│ ☑ 深圳市华顺达电子有限公司 上次合作: 2026-01 │
│ ☑ 苏州博远精密设备有限公司 上次合作: 2026-01 │
│ ☐ 上海瑞达工控科技有限公司 新供应商 │
│ ☑ 广州联盟电气集团 报价历史优秀 │
│ ☐ 武汉华中精工机械有限公司 评价4.8分 │
│ │
│ 发送方式: [📧 邮件通知] [💬 站内信] [📱 短信通知] │
│ │
│ [取消] [确认指派] │
└─────────────────────────────────────────────────────┘
```
**指派后**:系统向供应商发送通知,供应商登录后可看到"可报项"
---
## 五、板块四:报价商门户(供应商端)
### 5.1 账户体系设计
```sql
-- 在 sys_user 增加供应商类型字段(已有 tenant_id)
ALTER TABLE sys_user ADD COLUMN (
user_type TINYINT DEFAULT 1 COMMENT '1内部员工 2供应商账号',
supplier_id BIGINT COMMENT '关联供应商ID(仅user_type=2时有效)',
account_status TINYINT DEFAULT 1 COMMENT '0待审核 1正常 2冻结'
);
```
**权限控制**
- 供应商账号(`user_type=2`) → 仅能看到本供应商数据(通过`supplier_id`过滤)
- RuoYi `@PreAuthorize`注解 + 自定义数据权限拦截器
- 路由层面:供应商端访问 `/supplier/**` 路径,内部员工无法访问
### 5.2 供应商路由体系
新建独立路由模块,与后台管理路由隔离:
```javascript
// ruoyi-ui/src/router/supplier.js
export const supplierRoutes = [
{
path: '/supplier',
component: Layout,
hidden: true, // 不在管理后台侧边栏显示
children: [
{ path: 'dashboard', component: () => import('@/views/supplier/dashboard'), meta: { title: '供应商首页' } },
{ path: 'rfq/pending', component: () => import('@/views/supplier/rfq-pending'), meta: { title: '可报项' } },
{ path: 'rfq/quoted', component: () => import('@/views/supplier/rfq-quoted'), meta: { title: '已报项' } },
{ path: 'quote/edit/:rfqId', component: () => import('@/views/supplier/quote-edit'), meta: { title: '报价填写' } },
{ path: 'profile', component: () => import('@/views/supplier/profile'), meta: { title: '我的信息' } },
]
}
];
```
### 5.3 供应商首页 (`/supplier/dashboard`)
```
┌────────────────────────────────────────────────────────────┐
│ 欢迎您,深圳市华顺达电子有限公司 │
├──────────┬──────────┬──────────┬──────────┬───────────────┤
│ 可报项 │ 已报项 │ 中标数 │ 中标率 │ 累计成交额 │
│ 3 │ 12 │ 5 │ 41.7% │ ¥1,286,500 │
├──────────┴──────────┴──────────┴──────────┴───────────────┤
│ ⏰ 紧急提醒RFQ-2026-003 报价截止还剩 2天
│ 📋 最新中标的报价单RFQ-2026-001 (2026-01-15中标) │
└────────────────────────────────────────────────────────────┘
```
### 5.4 可报项 (`/supplier/rfq/pending`)
**数据来源**`biz_rfq_supplier` WHERE `supplier_id = ?` AND `status = 'published'` AND `quote_deadline > NOW()`
**列表字段**
| 字段 | 说明 |
|------|------|
| RFQ编号 | biz_rfq.rfq_no |
| 甲方/项目 | biz_rfq.client_name / project_name |
| 报价截止日 | biz_rfq.quote_deadline (红色<3天) |
| 物料数量 | biz_rfq_item COUNT |
| 操作 | 立即报价(按钮) |
**紧急提醒**截止前24小时发送站内信(复用RuoYi消息中心)
### 5.5 已报项 (`/supplier/rfq/quoted`)
**数据来源**`biz_quotation` WHERE `supplier_id = ?`
**列表字段**
| 字段 | 说明 |
|------|------|
| RFQ编号 | rfq_no |
| 报价日期 | quotation.create_time |
| 物料数量 | quotation_item COUNT |
| 报价总额 | quotation.total_amount |
| 状态 | pending(待开标)/won(已中标)/lost(未中标) |
| 操作 | 查看详情 / 修改报价(截止前可改) |
### 5.6 报价填写界面 (`/supplier/quote/edit/:rfqId`)
采用**分步表单**
```
Step 1 → 物料清单确认 (只读展示RFQ物料)
Step 2 → 逐项填价 (核心步骤)
Step 3 → 预览提交
```
**Step 2 填价界面**
```
物料清单表格:
┌──────────┬────────┬──────┬──────┬──────────┬────────┬──────────┐
│ 物料名称 │ 规格 │ 数量 │ 单位 │ 单价(元)* │ 交期(周)│ 备注 │
├──────────┼────────┼──────┼──────┼──────────┼────────┼──────────┤
│ PLC控制器 │ CPU... │ 5 │ 套 │ [___] │ [___] │ [______] │
│ 变频器 │ 三相...│ 8 │ 台 │ [___] │ [___] │ [______] │
│ 电源模块 │ 24V... │ 20 │ 台 │ [___] │ [___] │ [______] │
└──────────┴────────┴──────┴──────┴──────────┴────────┴──────────┘
含税/未税切换: [●含税] [○未税] 自动计算增值税13%
```
**关键交互**
- 必填校验单价 > 0交期 ≤ RFQ要求
- 智能提示当输入单价低于该物料历史最低价的80%时 → 警告弹窗"报价异常偏低,请确认"
- 附件上传:产品彩页、资质证书、型式试验报告(新表`biz_quotation_attachment`)
- 自动保存草稿(LocalStorage + 后端每3分钟自动保存)
- 提交前预览比价结果(提示"您的报价在当前排名第X/共Y家")
### 5.7 供应商端API
| 接口 | 方法 | 说明 |
|------|------|------|
| `/supplier/dashboard/stats` | GET | 统计数据总览 |
| `/supplier/rfq/pending` | GET | 可报项列表(分页) |
| `/supplier/rfq/quoted` | GET | 已报项列表(分页) |
| `/supplier/quote/draft/{rfqId}` | GET | 获取草稿报价 |
| `/supplier/quote/save-draft` | POST | 保存报价草稿 |
| `/supplier/quote/submit` | POST | 提交报价 |
| `/supplier/quote/{id}/attachments` | POST | 上传附件 |
| `/supplier/profile` | GET/PUT | 供应商信息维护 |
---
## 六、板块五:甲方报价单
### 6.1 现有基础
`biz_client_quote` 已有基础CRUD`biz_client_quote_item` 已有明细表。现有页面已支持基本的新建/编辑/PDF导出。
### 6.2 数据模型增强
```sql
-- 增强甲方报价单
ALTER TABLE biz_client_quote ADD COLUMN (
rfq_id BIGINT COMMENT '关联内部RFQ',
cost_total DECIMAL(18,4) COMMENT '内部成本合计(供应商中标价汇总)',
margin_rate DECIMAL(5,2) COMMENT '毛利率%',
quote_version INT DEFAULT 1 COMMENT '报价版本号',
parent_quote_id BIGINT COMMENT '父报价单ID(版本迭代)',
project_name VARCHAR(200) COMMENT '项目名称',
validity_date DATETIME COMMENT '报价有效期',
payment_terms VARCHAR(500) COMMENT '付款条件',
delivery_terms VARCHAR(500) COMMENT '交货条款',
status VARCHAR(20) COMMENT 'draft/sent/accepted/rejected/revised',
margin_rate_setting DECIMAL(5,2) DEFAULT 15.00 COMMENT '加价系数(%)',
tax_rate DECIMAL(4,2) DEFAULT 13.00 COMMENT '税率(%)'
);
-- 新建甲方报价-物料-供应商关联表(记录每个物料选定的供应商)
CREATE TABLE biz_client_quote_item_source (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
quote_item_id BIGINT NOT NULL COMMENT 'biz_client_quote_item.id',
supplier_id BIGINT COMMENT '选定的供应商ID',
supplier_quote_id BIGINT COMMENT '供应商报价单ID(biz_quotation.quotation_id)',
unit_cost DECIMAL(18,4) COMMENT '供应商中标单价(含税)',
selected_reason VARCHAR(500) COMMENT '选择该供应商原因',
internal_note TEXT COMMENT '内部备注',
create_by VARCHAR(64),
create_time DATETIME,
update_by VARCHAR(64),
update_time DATETIME,
KEY idx_quote_item (quote_item_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='甲方报价物料来源';
```
### 6.3 业务流程图
```
┌──────────────┐
│ 甲方询价需求 │
└──────┬───────┘
┌──────────────────┐
│ 创建甲方报价单 │ ← 手动输入甲方需求物料
│ (biz_client_quote)│
└──────┬───────────┘
┌──────────────────┐
│ 生成内部RFQ │ ← 从甲方物料自动拆解为RFQ
│ (点击"发起询价") │ 按品类分多个子RFQ
└──────┬───────────┘
┌──────────────────┐
│ 指派供应商报价 │ ← 每个子RFQ指派不同供应商
│ (供应商端报价) │ 变频器→A/B/C, 电缆→D/E
└──────┬───────────┘
┌──────────────────┐
│ 比价选择供应商 │ ← 使用现有智慧比价引擎
│ (选定最优方案) │
└──────┬───────────┘
┌──────────────────┐
│ 成本回填 │ ← 自动回填选中供应商价格到
│ (自动/手动同步) │ biz_client_quote_item_source
└──────┬───────────┘
┌──────────────────┐
│ 计算对外报价 │ ← 成本 × (1 + 加价系数)
│ 生成PDF → 发送甲方 │ 可手动调整覆盖
└──────────────────┘
```
### 6.4 甲方报价单详情页重构
```
甲方报价单详情页 (/bid/clientquote/detail/:id)
├── 顶部操作栏
│ ├── 保存草稿 | 导出PDF | 发送甲方 | 版本迭代
│ └── 状态标签(draft/sent/accepted/rejected)
├── 基本信息卡片
│ ├── 客户名称 | 项目名称 | 有效期 | 币种
│ ├── 关联RFQ(下拉选择) | 合同号
│ └── 付款条件 | 交货条款
├── 物料清单表格(可编辑)
│ ├── 行数据:序号 | 类别 | 物料名称 | 品牌 | 型号规格
│ │ | 数量 | 单位 | 供应商中标价(成本)
│ │ | 加价系数 | 对外含税单价 | 小计
│ ├── 操作:添加行 | 删除行 | 批量导入
│ └── 特殊列:询价状态(未询价/报价中/已回价/已定价)
│ └── 已定价 → 显示供应商名称,点击查看来源
│ └── 未询价 → 点击"发起询价"→ 弹出选择供应商 → 生成子RFQ
├── 右侧成本汇总面板(固定)
│ ├── 物料成本合计: ¥XXX (自动汇总供应商中标价)
│ ├── 加价系数: 15% (可调整)
│ ├── 对外报价(含税): ¥XXX = 成本 × (1 + 加价系数)
│ ├── 预计毛利率: XX.X% (实时计算)
│ └── 操作按钮:同步最新采购价 | 重新计算
├── Tab: 智能选型对比
│ └── 选中物料 → 弹出对比窗口 → 展示同规格多品牌对比
│ → 一键替换物料型号和成本
└── Tab: 历史版本
└── 版本列表(通过parent_quote_id关联)
→ 版本对比(高亮显示差异)
```
### 6.5 子RFQ生成逻辑
```java
// 从甲方报价单生成内部RFQ
@PostMapping("/bid/clientquote/{id}/generateRfq")
public AjaxResult generateSubRfq(@PathVariable Long id, @RequestBody GenerateRfqRequest req) {
// 1. 获取甲方报价单主表
// 2. 根据选中的行物料,按category_id分组
// 如: 变频器类一组,PLC类一组,电缆类一组
// 3. 为每组创建子RFQ:
// - rfq_title = 甲方报价单项目名 + "(" + 类别名称 + ")"
// - deadline = 甲方报价单有效期前7天
// - parent_client_quote_id = 甲方报价单ID
// 4. 将选中物料复制到biz_rfq_item
// 5. 指派供应商(从req.supplier_ids)
// 6. 返回生成的RFQ ID列表
}
```
### 6.6 成本回填机制
**自动回填触发点**
1. 采购单确认时(`biz_purchase_order.status → 'confirmed'`)
2. 甲方报价单页面手动点击"同步最新采购价"
**回填逻辑**
```java
// 自动回填
@PostMapping("/bid/clientquote/{id}/syncCost")
public AjaxResult syncCost(@PathVariable Long id) {
// 1. 获取所有子RFQ的最新成交报价
// 2. 将选中供应商的成交价写入biz_client_quote_item_source
// 3. 更新biz_client_quote.cost_total
// 4. 重新计算margin_rate
// 5. 记录价格变动日志
}
```
**价格变动日志表**
```sql
CREATE TABLE biz_price_change_log (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
source_type VARCHAR(20) COMMENT '来源类型(quotation/client_quote)',
source_id BIGINT COMMENT '来源ID',
material_id BIGINT COMMENT '物料ID',
old_price DECIMAL(18,4),
new_price DECIMAL(18,4),
change_reason VARCHAR(500) COMMENT '变更原因',
operator VARCHAR(64),
create_time DATETIME
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='价格变动日志';
```
### 6.7 两个报价历史
**历史1我方给甲方的报价历史**
- 数据源:`biz_client_quote` 通过 `parent_quote_id` 形成版本链
- 功能:版本对比 → 选择两个版本高亮显示价格差异
**历史2供应商给我方的报价历史**
- 数据源:`biz_quotation_item` 中该物料的历史记录
- 功能:在甲方报价单物料行点击"查看成本来源" → 抽屉展示时间轴
---
## 七、报价单管理与指派系统
### 7.1 报价单详情页 (`/bid/rfq/detail/:id`)
```
RFQ详情页 (/bid/rfq/detail/:id)
├── 顶部:基础信息(合同号/甲方/截止日/状态)
├── 左侧:已邀请供应商列表
│ ├── 供应商名称 | 报价状态(未报价/已报价/已逾期)
│ ├── 已报价 → 显示报价金额及操作(查看详情)
│ └── 未报价 → 显示"催办"按钮(发送通知)
├── 右侧:物料明细及各家报价对比表格
│ ├── 与XLSX Sheet 10-14格式一致
│ ├── 行:物料,列:各供应商单价(最低价绿色高亮)
│ └── 差额/差价自动计算
├── 底部操作栏
│ ├── 确认中标 → 弹出选择中标供应商对话框
│ ├── 重新询价 → 复制当前RFQ生成新版本
│ ├── 导出比价报告(PDF) → 复用现有导出功能
│ └── 关闭询价
```
### 7.2 供应商报价填写界面(供应商端)
见5.6节详细描述。
### 7.3 比价报告PDF
模板格式参考XLSX Sheet 10-14包含
- 表头RFQ编号、项目名称、日期
- 物料对比表:每行展示各供应商报价、最低价标记
- 推荐方案:综合评分推荐最优供应商
- 统计摘要:总价对比、节省金额
---
## 八、电气设备数据初始化方案
### 8.1 数据范围
利用XLSX Sheet 20-31的型号库数据预置如下初始数据
| 品类 | 型号数量 | 数据来源Sheet | 对应品牌 |
|------|---------|--------------|---------|
| 变频器 | ~322 | 31_品牌汇总 | 汇川/禾望/西门子/ABB |
| 整流制动单元 | ~100 | 21_整流制动单元库 | 汇川/禾望/西门子 |
| PLC CPU | ~55 | 22_PLC_CPU型号库 | 西门子/三菱/欧姆龙 |
| PLC扩展模块 | ~98 | 23_PLC_扩展模块库 | 西门子/三菱/欧姆龙 |
| 低压电器 | ~75 | 24_低压电器型号库 | 正泰/施耐德 |
| 触摸屏 | ~20 | 25_触摸屏型号库 | 威纶通/昆仑通态/西门子 |
| 铜牌母线 | ~20 | 26_铜牌母线型号库 | TMY铜排 |
| 动力电缆 | ~23 | 27_电缆型号库 | YJV22系列 |
| 控制线 | ~21 | 28_控制线型号库 | KVVP系列 |
| 线槽 | ~18 | 29_线槽型号库 | PVC/钢制 |
| 工业网关 | ~12 | 30_网关型号库 | 汇川/研华 |
| **合计** | **~764** | | |
### 8.2 供应商初始化
基于XLSX比价数据中的供应商初始化以下供应商
| 供应商 | 供应品类 | 数据范围 |
|--------|---------|---------|
| A供应商(汇川/正泰等) | 变频器/整流/低压电器 | Sheet 10-14 |
| B供应商(禾望等) | 变频器/整流/PLC | Sheet 10-14 |
| C供应商(西门子/施耐德等) | 变频器/PLC/低压电器 | Sheet 10-14 |
### 8.3 对比组初始化
根据Sheet 10-14比价数据建立初始对比组
| 对比组 | 包含品牌 | 数据来源 |
|--------|---------|---------|
| 37kW 380V变频器 | 汇川MD500T37G / 禾望HV500-37G / 西门子G120 / ABB ACS880 | Sheet 10 |
| 55kW 380V变频器 | 汇川MD500T55G / 禾望HV500-55G / 西门子G120 PM240 | Sheet 10 |
| 整流单元75kW | MDR100T75 / HBD-075 / BLM-075 | Sheet 11 |
| CPU 1515-2 PN | 三家供应商报价对比 | Sheet 12 |
| 断路器NXM-125S | 正泰/施耐德/其他 | Sheet 13 |
| 动力电缆YJV 3×70+1×35 | 三家供应商报价对比 | Sheet 14 |
### 8.4 导入策略
**方案一SQL脚本导入推荐首批**
- 将型号库数据编写为 `INSERT` 语句
- 写入 `sql/demo_data.sql` 或新建 `sql/excel_import_data.sql`
- 每个物料生成 `material_code` (如 `M-EL-001`)
**方案二Excel批量导入功能后续维护**
- 通过 `/bid/material/import` 接口
- 上传Excel文件 → EasyExcel解析 → 数据校验 → 批量写入
- 提供下载导入模板功能
---
## 九、开发优先级与里程碑
### 第一阶段基础数据层第1-2周
| 优先级 | 任务 | 涉及文件 |
|--------|------|---------|
| P0 | 物料表字段扩展 + 性能参数JSON动态表单 | `biz_material` + 前端物料表单 |
| P0 | 物料分类树+表格联动 | 复用现有 `BizMaterialCategoryController` |
| P1 | 物料详情页基础框架 + Tab1(供应商历史报价) | 新建 `material/detail.vue` |
| P1 | 供应商-物料关系表 + 供货清单Tab | 新建 `biz_supplier_material` |
| P1 | 物料横向对比组表 + 维护界面 | 新建 `biz_material_comparison` |
| P2 | Excel电气设备型号库数据导入(首批~764条) | 扩充 `demo_data.sql` |
### 第二阶段业务流程层第3-5周
| 优先级 | 任务 | 涉及文件 |
|--------|------|---------|
| P0 | RFQ增强(合同号/甲方/截止日/指派界面) | `biz_rfq` 扩展 + RFQ详情页重构 |
| P0 | 供应商门户独立路由 + 可报项/已报项列表 | 新建 `views/supplier/*` |
| P0 | 供应商报价填写界面(分步表单) | 新建 `supplier/quote-edit.vue` |
| P1 | 供应商账号管理(账号创建/权限分配) | `sys_user` user_type扩展 |
| P1 | 甲方报价单增强(子RFQ生成) | `BizClientQuoteController` |
| P1 | 成本回填机制(自动+手动触发) | 新建 `biz_client_quote_item_source` |
| P2 | 物料详情Tab2(甲方历史报价) | 扩展 `material/detail.vue` |
### 第三阶段智能分析层第6-8周
| 优先级 | 任务 | 涉及文件 |
|--------|------|---------|
| P1 | 物料详情Tab3(横向同比+推荐算法) | 扩展 `material/detail.vue` |
| P1 | 甲方报价单智能选型对比 | `BizComparisonService` 扩展 |
| P2 | 价格趋势ECharts折线图(物料详情页) | 物料详情右栏 |
| P2 | 供应商报价历史趋势ECharts | 供应商详情Tab4 |
| P2 | 价格预警机制(高于均价15%红色高亮) | 前端表格渲染 |
| P3 | 比价报告PDF增强 | 复用现有JSPDF导出 |
### 第四阶段优化完善第9-10周
| 优先级 | 任务 | 涉及文件 |
|--------|------|---------|
| P2 | 版本对比(甲方报价单历史版本diff) | 扩展 `client-quote` |
| P2 | 批量导入Excel型号库(维护界面) | `/bid/material/import` |
| P3 | 供应商端多语言/国际化 | i18n配置 |
| P3 | 性能优化(物料列表大数据量分页) | 后端分页+前端虚拟滚动 |
| P3 | Docker部署配置更新 | `deploy/` |
---
## 十、关键接口清单
### 物料模块
| 接口 | 方法 | 说明 | 优先级 |
|------|------|------|--------|
| `/bid/material/detail/{id}` | GET | 物料详情+历史报价摘要 | P0 |
| `/bid/material/{id}/supplier-quotes` | GET | 供应商历史报价清单 | P0 |
| `/bid/material/{id}/client-quotes` | GET | 我方给甲方历史报价 | P1 |
| `/bid/material/{id}/comparison` | GET | 横向对比数据 | P1 |
| `/bid/material/manufacturer/list` | GET | 厂家下拉列表(去重) | P0 |
| `/bid/material/import` | POST | Excel批量导入 | P1 |
| `/bid/material/export` | GET | 导出模板 | P1 |
| `/bid/material/suggest` | GET | 型号智能联想 | P2 |
### 供应商模块
| 接口 | 方法 | 说明 | 优先级 |
|------|------|------|--------|
| `/bid/supplier/{id}/materials` | GET | 供货清单(分页) | P0 |
| `/bid/supplier/{id}/materials` | POST | 添加供应物料 | P1 |
| `/bid/supplier/{id}/quotes` | GET | 报价单管理列表 | P1 |
| `/bid/supplier/{id}/price-trend` | GET | 历史报价趋势 | P2 |
| `/bid/supplier/{id}/accounts` | GET | 供应商账号列表 | P1 |
| `/bid/supplier/{id}/accounts` | POST | 创建供应商账号 | P2 |
### RFQ模块
| 接口 | 方法 | 说明 | 优先级 |
|------|------|------|--------|
| `/bid/rfq/{id}/assign` | POST | 指派供应商 | P0 |
| `/bid/rfq/{id}/comparison` | GET | 比价结果(现有增强) | P0 |
| `/bid/rfq/{id}/bid-report` | GET | 导出比价报告PDF | P1 |
| `/bid/rfq/{id}/winner` | POST | 确认中标供应商 | P1 |
### 供应商端
| 接口 | 方法 | 说明 | 优先级 |
|------|------|------|--------|
| `/supplier/dashboard/stats` | GET | 统计数据总览 | P0 |
| `/supplier/rfq/pending` | GET | 可报项列表 | P0 |
| `/supplier/rfq/quoted` | GET | 已报项列表 | P0 |
| `/supplier/quote/draft/{rfqId}` | GET | 获取草稿报价 | P0 |
| `/supplier/quote/save-draft` | POST | 保存报价草稿 | P0 |
| `/supplier/quote/submit` | POST | 提交报价 | P0 |
| `/supplier/quote/{id}/attachments` | POST | 上传附件 | P1 |
### 甲方报价单
| 接口 | 方法 | 说明 | 优先级 |
|------|------|------|--------|
| `/bid/clientquote/{id}/generateRfq` | POST | 生成子RFQ | P0 |
| `/bid/clientquote/{id}/syncCost` | POST | 同步采购成本 | P1 |
| `/bid/clientquote/{id}/compareSpec` | GET | 智能选型对比 | P1 |
| `/bid/clientquote/{id}/versions` | GET | 历史版本列表 | P2 |
| `/bid/clientquote/version-compare` | POST | 版本对比diff | P2 |
| `/bid/clientquote/{id}/export-pdf` | GET | 导出PDF | P0(现有) |
---
## 十一、权限与安全设计
### 11.1 权限矩阵
| 角色 | 物料 | 供应商 | RFQ | 供应商报价 | 比价 | 甲方报价 | 供应商门户 |
|------|------|--------|-----|-----------|------|---------|-----------|
| 管理员 | CRUD | CRUD | CRUD | CRUD | 查看 | CRUD | 不可访问 |
| 采购员 | 查看 | 查看/编辑 | CRUD | 查看 | 查看/操作 | 查看 | 不可访问 |
| 销售员 | 查看 | 查看 | 查看 | 查看 | 查看 | 创建/编辑 | 不可访问 |
| 供应商 | 查看(仅关联) | 查看(仅自己) | 查看(受邀) | 查看(仅自己) | 不可见 | 不可见 | 报价/查看 |
### 11.2 数据权限
- **租户隔离**:所有业务表已有 `tenant_id`查询SQL必须带 `tenant_id = ?`
- **供应商隔离**:供应商账号 `user_type=2`,所有查询追加 `supplier_id = ?`
- **价格脱敏**:供应商看不到其他供应商的报价价格(但可以看到自己的排名)
### 11.3 安全措施
- **价格字段加密**敏感价格字段在数据库中使用AES加密存储接口返回时按角色脱敏
- **乐观锁防并发**`biz_quotation` 增加 `version` 字段供应商报价提交时CAS检查
- **操作日志**所有CRUD操作使用RuoYi `@Log` 注解记录
- **文件上传校验**:限制附件类型(pdf/jpg/png)大小≤10MB
---
## 附录Excel数据对照表
### XLSX → 系统表映射
| Excel Sheet | 对应系统表 | 说明 |
|------------|-----------|------|
| 01_项目报价单 | `biz_client_quote` + `biz_client_quote_item` | 甲方报价模板映射 |
| 02_报价汇总 | `biz_client_quote` (汇总字段) | 汇总逻辑直接实现 |
| 10-14_比价表 | `biz_quotation` + `biz_comparison`(已有) | 比价数据初始化来源 |
| 20-30_型号库 | `biz_material` | 初始物料数据(764条) |
| 31_品牌汇总 | 统计查询 | 直接SQL统计实现 |
### XLSX比价表 → 系统比价引擎字段映射
| Excel列 | 系统字段 | 说明 |
|---------|---------|------|
| A供应商型号 | quotation_item.material_name/spec | 报价物料 |
| A供应商报价 | quotation_item.unit_price | 供应商A报价单价 |
| B供应商型号 | quotation_item.material_name/spec | 报价物料 |
| B供应商报价 | quotation_item.unit_price | 供应商B报价单价 |
| 最低价 | BizComparisonVO.minPrice | 当前最低价(系统自动计算) |
| 推荐 | BizComparisonVO.recommendedSupplier | 评分最优推荐 |
---
> 本文档基于PPT《报价比对系统》(6页) + XLSX《电气自动化设备综合管理系统_V1》(27Sheet) + 现有项目源码(RuoYi-Vue v3.9.2, 12个已完成模块)综合分析生成,可直接作为迭代开发的技术参考。
>
> 最后更新2026-05-27