diff --git a/.gitignore b/.gitignore index 43585f01..bccd55ec 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,12 @@ logs/ # Spring Boot *.pid +# Demo / sample projects +shipping_system/ + +# Design documents (internal) +doc/order_module_design/ + # Docker local build artifacts deploy/dist-ui/ deploy/ruoyi-admin.jar diff --git a/doc/zz_start_and_check.sh b/doc/zz_start_and_check.sh new file mode 100644 index 00000000..d0b16c3c --- /dev/null +++ b/doc/zz_start_and_check.sh @@ -0,0 +1,8 @@ +#!/bin/bash +cd D:/DeXun_workspace/projects/erp-next +mvn spring-boot:run -pl ruoyi-admin -q & +PID=$! +echo "App PID: $PID" +sleep 40 +curl -s http://localhost:8080/v3/api-docs > D:/DeXun_workspace/projects/erp-next/doc/zz_api_result.json 2>&1 +echo "Done, check zz_api_result.json" diff --git a/doc/甲方客户界面及订单页面设计流程.md b/doc/甲方客户界面及订单页面设计流程.md new file mode 100644 index 00000000..cda06116 --- /dev/null +++ b/doc/甲方客户界面及订单页面设计流程.md @@ -0,0 +1,797 @@ +# 甲方客户界面及订单相关页面设计流程文档 + +## 一、Shipping_System Demo 全面分析 + +### 1.1 交互模式分析 + +#### 1.1.1 页面导航结构 +``` +顶部导航栏(固定) +├── Logo区域(品牌标识) +├── 主导航菜单(水平排列) +│ ├── 总览(Dashboard) +│ ├── 物料管理 +│ ├── 客户管理 +│ ├── 待发订单 +│ ├── 在途订单 +│ ├── 历史订单 +│ ├── 结单时间 +│ ├── 数据报表 +│ └── 操作记录 +└── 系统状态指示器 + +内容区域(单页应用模式) +├── 页面标题区(Section Header) +├── 工具栏(搜索/筛选/操作按钮) +├── 数据表格/卡片区域 +└── 分页/统计信息 +``` + +#### 1.1.2 核心交互模式 + +| 交互类型 | 实现方式 | 用户体验特点 | +|---------|---------|-------------| +| 页面切换 | 单页应用(SPA),无刷新切换 | 快速、流畅 | +| 数据加载 | 异步fetch API,loading状态 | 非阻塞、有反馈 | +| 表单提交 | Modal弹窗,实时验证 | 沉浸式、不打断 | +| 搜索筛选 | 防抖输入(300ms),即时响应 | 高效、省资源 | +| 状态流转 | 按钮操作+状态标签变色 | 直观、可追踪 | +| 数据展示 | 表格+卡片+图表混合 | 信息层次清晰 | + +#### 1.1.3 关键交互细节 + +**订单状态流转:** +``` +待发(PENDING) → 在途(TRANSIT) → 历史(HISTORY) + ↓ ↓ + 编辑/删除 完成/撤回 +``` + +**预警提示机制:** +- 交货期预警:红色边框+逾期天数标签 +- 状态标识:彩色Badge标签 +- 操作反馈:Toast消息提示 + +### 1.2 布局结构分析 + +#### 1.2.1 整体布局框架 +``` +┌─────────────────────────────────────────────────────────────┐ +│ [Logo] 总览 物料管理 客户管理 待发...在途...历史... │ +├─────────────────────────────────────────────────────────────┤ +│ │ +│ 页面标题 [状态标签] │ +│ ───────────────────────────────────────────────────────── │ +│ │ +│ [搜索框] [筛选器] [新增按钮] │ +│ │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ 数据表格 │ │ +│ │ ───────────────────────────────────────────────── │ │ +│ │ 订单号 客户 金额 交货期 状态 操作 │ │ +│ │ ORD-001 XXX ¥100 2026-06 PENDING [详][编][发] │ │ +│ └─────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────┘ +``` + +#### 1.2.2 响应式断点设计 + +| 断点 | 宽度 | 布局调整 | +|-----|------|---------| +| Desktop | ≥1200px | 完整布局,多列展示 | +| Tablet | 768-1199px | 简化表格,隐藏次要列 | +| Mobile | <768px | 卡片式布局,垂直堆叠 | + +#### 1.2.3 页面类型模板 + +**列表页模板:** +- 顶部:标题 + 状态说明 +- 工具栏:搜索 + 筛选 + 主要操作 +- 内容区:数据表格 +- 底部:分页器 + +**详情/编辑页模板:** +- Modal弹窗形式 +- 分区块表单(2列布局) +- 底部操作按钮组 + +**报表页模板:** +- KPI指标卡片行 +- 图表网格(2列) +- 详细数据表格 + +### 1.3 功能模块划分 + +#### 1.3.1 模块结构图 + +``` +shipping_system +├── 核心数据模块 +│ ├── 物料管理(SKU级) +│ ├── 客户管理(企业/个人) +│ └── 订单管理(生命周期) +├── 业务流程模块 +│ ├── 订单状态流转 +│ ├── 结单时间管理 +│ └── 发货记录追踪 +├── 分析报表模块 +│ ├── 统计概览 +│ ├── 趋势分析 +│ └── 排名报表 +└── 系统管理模块 + ├── 操作日志 + └── 数据审计 +``` + +#### 1.3.2 功能对照表 + +| 功能模块 | 当前项目对应 | 复用建议 | +|---------|-------------|---------| +| 客户管理 | 甲方客户管理 | 高度复用界面结构 | +| 订单管理 | 销售订单/发货单 | 复用状态流转逻辑 | +| 物料管理 | 产品/物料库 | 复用表格布局 | +| 数据报表 | 统计分析 | 复用图表组件 | +| 操作记录 | 系统日志 | 复用表格+筛选 | + +--- + +## 二、视觉设计规范提取 + +### 2.1 色彩系统 + +#### 2.1.1 主色调(工业暗黑风) + +```css +:root { + /* 背景层级 */ + --bg: #1a1c1e; /* 主背景 - 深灰黑 */ + --bg2: #222426; /* 卡片背景 */ + --bg3: #2a2d30; /* 表头/输入框背景 */ + --bg4: #333639; /* 悬停背景 */ + + /* 边框层级 */ + --border: #3a3d41; /* 普通边框 */ + --border2: #4a4d52; /* 高亮边框 */ + + /* 文字层级 */ + --text: #c8ccd0; /* 主文字 - 浅灰 */ + --text2: #8a8f96; /* 次要文字 */ + --text3: #5a5f66; /* 禁用/提示文字 */ + + /* 强调色 */ + --yellow: #e8b400; /* 主强调色 - 琥珀金 */ + --yellow2: #ffcc00; /* 高亮 */ + + /* 状态色 */ + --red: #c0392b; /* 危险/逾期 */ + --red2: #e74c3c; /* 警告高亮 */ + --green: #27ae60; /* 成功/完成 */ + --green2: #2ecc71; /* 成功高亮 */ + --blue: #2980b9; /* 信息/在途 */ + --blue2: #3498db; /* 信息高亮 */ + --orange: #d35400; /* 警告/待发 */ + --orange2: #e67e22; /* 警告高亮 */ +} +``` + +#### 2.1.2 色彩应用场景 + +| 场景 | 颜色 | 用途 | +|-----|------|------| +| 品牌标识 | #e8b400 | Logo、主按钮、强调线 | +| 成功状态 | #27ae60 | 完成、通过、正常 | +| 警告状态 | #e67e22 | 待发、待处理 | +| 危险状态 | #e74c3c | 逾期、删除、异常 | +| 信息状态 | #3498db | 在途、进行中 | +| 中性状态 | #8a8f96 | 草稿、默认 | + +### 2.2 字体系统 + +```css +:root { + --font: 'JetBrains Mono', 'Consolas', 'Courier New', monospace; +} +``` + +| 元素 | 字号 | 字重 | 样式 | +|-----|------|------|------| +| Logo | 14px | 700 | 大写,字间距2px | +| 导航 | 12px | 700 | 大写,字间距0.5px | +| 页面标题 | 11px | 700 | 大写,字间距1.5px | +| 表格表头 | 11px | 700 | 大写,字间距0.5px | +| 表格内容 | 13px | 400 | 正常 | +| 按钮 | 12px | 400 | 字间距0.5px | +| 统计数字 | 28px | 700 | 字间距-1px | + +### 2.3 间距系统 + +| 元素 | 间距值 | +|-----|-------| +| 页面内边距 | 20px | +| 卡片内边距 | 16px 20px | +| 表格单元格 | 8px 12px | +| 按钮内边距 | 5px 14px | +| 表单行间距 | 12px | +| 组件间隙 | 12-16px | + +### 2.4 组件样式 + +#### 2.4.1 按钮规范 + +```css +/* 基础按钮 */ +button { + padding: 5px 14px; + font-size: 12px; + border: 1px solid var(--border2); + background: var(--bg3); + transition: all .15s; +} + +/* 主要按钮 */ +.btn-primary { + background: var(--yellow); + color: #000; + border-color: var(--yellow); + font-weight: 700; +} + +/* 危险按钮 */ +.btn-danger { + border-color: var(--red); + color: var(--red); +} + +/* 成功按钮 */ +.btn-success { + border-color: var(--green); + color: var(--green); +} +``` + +#### 2.4.2 表格规范 + +```css +th { + background: var(--bg3); + color: var(--text2); + font-weight: 700; + text-transform: uppercase; + border-bottom: 2px solid var(--yellow); + padding: 8px 12px; +} + +td { + padding: 8px 12px; + border-bottom: 1px solid var(--border); +} + +tr:hover td { + background: var(--bg3); +} +``` + +#### 2.4.3 状态标签(Badge) + +```css +.badge-pending { /* 待发 */ + color: #e67e22; + border-color: #e67e22; + background: rgba(230,126,34,.1); +} + +.badge-transit { /* 在途 */ + color: #3498db; + border-color: #3498db; + background: rgba(52,152,219,.1); +} + +.badge-history { /* 历史 */ + color: #27ae60; + border-color: #27ae60; + background: rgba(39,174,96,.1); +} + +.badge-warn { /* 警告/逾期 */ + color: var(--red2); + border-color: var(--red2); + background: rgba(231,76,60,.1); +} +``` + +--- + +## 三、设计流程规划 + +### 3.1 阶段一:需求分析与确认(3-5天) + +#### 3.1.1 工作内容 + +1. **业务需求梳理** + - 甲方客户管理流程梳理 + - 订单生命周期定义 + - 状态流转规则确认 + - 权限角色划分 + +2. **现有系统分析** + - 当前项目架构调研 + - 数据模型分析 + - API接口梳理 + - 复用组件盘点 + +3. **竞品/参考分析** + - shipping_system demo深度体验 + - 行业最佳实践研究 + - 用户痛点收集 + +#### 3.1.2 交付物 + +| 交付物 | 标准 | 负责人 | +|-------|------|-------| +| 需求规格说明书 | 功能点清单、业务流程图 | 产品经理 | +| 数据模型设计 | ER图、字段定义 | 后端开发 | +| 接口文档初稿 | API列表、字段定义 | 后端开发 | +| 竞品分析报告 | 优缺点对比、借鉴点 | 设计师 | + +#### 3.1.3 质量验收标准 + +- [ ] 所有功能点已明确优先级(P0/P1/P2) +- [ ] 业务流程图通过评审 +- [ ] 数据模型覆盖所有业务场景 +- [ ] 技术可行性已确认 + +--- + +### 3.2 阶段二:信息架构设计(2-3天) + +#### 3.2.1 工作内容 + +1. **站点地图设计** + ``` + 甲方客户管理 + ├── 客户列表 + │ ├── 搜索/筛选 + │ ├── 新增客户 + │ ├── 编辑客户 + │ └── 查看详情 + ├── 客户详情 + │ ├── 基本信息 + │ ├── 历史订单 + │ └── 联系记录 + └── 客户统计 + + 订单管理 + ├── 待发订单 + ├── 在途订单 + ├── 历史订单 + └── 订单详情 + ├── 基本信息 + ├── 物料明细 + ├── 状态流转 + └── 操作日志 + ``` + +2. **导航结构设计** + - 主导航菜单规划 + - 面包屑导航规则 + - 快捷入口设计 + +3. **页面层级规划** + - 一级页面:列表页 + - 二级页面:详情页/编辑页 + - 三级页面:关联信息 + +#### 3.2.2 交付物 + +| 交付物 | 标准 | 工具 | +|-------|------|------| +| 站点地图 | 完整页面层级 | XMind/ProcessOn | +| 用户流程图 | 关键任务流程 | Figma/Draw.io | +| 信息架构图 | 模块关系图 | 架构图工具 | + +#### 3.2.3 质量验收标准 + +- [ ] 所有页面层级不超过3级 +- [ ] 核心任务完成路径≤3步 +- [ ] 导航结构符合用户心智模型 +- [ ] 与现有系统导航风格一致 + +--- + +### 3.3 阶段三:线框图绘制(3-5天) + +#### 3.3.1 工作内容 + +1. **页面布局线框** + - 列表页布局(参考shipping_system) + - 详情页布局 + - 表单页布局 + - Modal弹窗布局 + +2. **组件布局规划** + - 表格列宽分配 + - 表单字段排列 + - 按钮位置规划 + - 响应式断点设计 + +3. **交互流程标注** + - 点击热区标注 + - 状态变化说明 + - 转场动画示意 + +#### 3.3.2 页面线框清单 + +| 页面 | 优先级 | 复杂度 | +|-----|-------|-------| +| 甲方客户列表页 | P0 | 中 | +| 甲方客户详情页 | P0 | 中 | +| 客户编辑/新增页 | P0 | 低 | +| 待发订单列表页 | P0 | 中 | +| 在途订单列表页 | P0 | 中 | +| 历史订单列表页 | P0 | 中 | +| 订单详情页 | P0 | 高 | +| 订单编辑/新增页 | P0 | 高 | +| 订单统计报表 | P1 | 中 | +| 客户统计报表 | P1 | 中 | + +#### 3.3.3 交付物 + +| 交付物 | 标准 | 工具 | +|-------|------|------| +| 低保真线框图 | 灰度,无色彩 | Figma/Axure | +| 交互说明文档 | 标注交互细节 | 文档工具 | +| 页面流程图 | 页面跳转关系 | 流程图工具 | + +#### 3.3.4 质量验收标准 + +- [ ] 所有P0页面线框已完成 +- [ ] 布局符合shipping_system风格 +- [ ] 核心交互路径已标注 +- [ ] 开发团队已评审通过 + +--- + +### 3.4 阶段四:视觉设计规范制定(2-3天) + +#### 3.4.1 工作内容 + +1. **色彩系统定义** + - 提取shipping_system配色 + - 适配当前项目品牌色 + - 定义状态色规范 + - 输出CSS变量 + +2. **字体系统定义** + - 中文字体选择(建议:思源黑体/微软雅黑) + - 字号层级定义 + - 行高/字间距规范 + +3. **组件视觉规范** + - 按钮样式(主/次/危险/成功) + - 输入框样式 + - 表格样式 + - 卡片/面板样式 + - 标签/Badge样式 + - Modal弹窗样式 + +4. **图标系统** + - 图标风格统一(线性/面性) + - 图标尺寸规范 + - 常用图标清单 + +#### 3.4.2 设计规范输出 + +``` +design-system/ +├── colors/ +│ ├── palette.scss # 色板定义 +│ ├── semantic.scss # 语义化颜色 +│ └── dark-theme.scss # 暗黑主题 +├── typography/ +│ ├── fonts.scss # 字体定义 +│ ├── scale.scss # 字号层级 +│ └── styles.scss # 文字样式 +├── components/ +│ ├── buttons.scss # 按钮规范 +│ ├── forms.scss # 表单规范 +│ ├── tables.scss # 表格规范 +│ ├── cards.scss # 卡片规范 +│ └── modals.scss # 弹窗规范 +└── spacing/ + ├── grid.scss # 栅格系统 + └── spacing.scss # 间距系统 +``` + +#### 3.4.3 交付物 + +| 交付物 | 标准 | 工具 | +|-------|------|------| +| 视觉设计规范文档 | 完整Design Token | Figma/文档 | +| 组件样式库 | SCSS/CSS代码 | 代码仓库 | +| 图标资源包 | SVG格式 | 设计工具 | + +#### 3.4.4 质量验收标准 + +- [ ] 色彩对比度符合WCAG 2.1 AA标准 +- [ ] 所有组件有对应的代码实现 +- [ ] 与shipping_system视觉风格一致 +- [ ] 开发团队可无障碍使用 + +--- + +### 3.5 阶段五:高保真原型制作(5-7天) + +#### 3.5.1 工作内容 + +1. **高保真页面设计** + - 基于线框图添加视觉细节 + - 应用设计规范 + - 填充真实数据示例 + +2. **交互原型制作** + - 页面跳转链接 + - 交互动效定义 + - 状态变化演示 + +3. **响应式设计** + - Desktop端(≥1200px) + - Tablet端(768-1199px) + - Mobile端(<768px) + +#### 3.5.2 关键页面设计要点 + +**甲方客户列表页:** +- 顶部:标题 + 客户统计 +- 工具栏:搜索框 + 客户类型筛选 + 新增按钮 +- 表格:编号/名称/联系人/电话/城市/订单数/状态/操作 +- 操作列:详情/编辑/删除 + +**订单详情页:** +- 左侧:订单基本信息卡片 +- 右侧:状态流转时间线 +- 下方:物料明细表格 +- 底部:操作按钮组(发货/完成/撤回) + +**订单编辑页:** +- 分步表单或标签页 +- 基本信息区 +- 物料明细区(可增删改) +- 实时金额计算 + +#### 3.5.3 交付物 + +| 交付物 | 标准 | 工具 | +|-------|------|------| +| 高保真设计稿 | 所有P0页面 | Figma | +| 交互原型 | 可点击演示 | Figma/Axure | +| 设计标注 | 尺寸/颜色/字体 | Figma Dev Mode | +| 切图资源 | 1x/2x/3x | Figma Export | + +#### 3.5.4 质量验收标准 + +- [ ] 所有P0页面高保真设计完成 +- [ ] 交互原型可完整演示核心流程 +- [ ] 视觉还原度与shipping_system≥90% +- [ ] 设计稿已通过产品/开发评审 + +--- + +### 3.6 阶段六:交互细节设计(2-3天) + +#### 3.6.1 工作内容 + +1. **微交互设计** + - 按钮悬停效果(边框变色+文字变色) + - 表格行悬停效果(背景色变化) + - 加载状态设计 + - 空状态设计 + +2. **动效规范** + - 页面切换过渡(建议:淡入淡出 200ms) + - Modal弹窗动画(建议:缩放+淡入 150ms) + - 数据刷新动画 + - 状态变化动画 + +3. **反馈机制** + - 成功提示(绿色Toast) + - 错误提示(红色Toast) + - 警告提示(橙色Alert) + - 加载提示(Loading Spinner) + +4. **键盘快捷键** + - Ctrl+S 保存 + - ESC 关闭弹窗 + - Enter 确认 + - / 聚焦搜索框 + +#### 3.6.2 交互规范文档 + +``` +interactions/ +├── hover-states.md # 悬停状态规范 +├── transitions.md # 转场动画规范 +├── feedback.md # 反馈机制规范 +├── keyboard-shortcuts.md # 快捷键规范 +└── accessibility.md # 无障碍规范 +``` + +#### 3.6.3 交付物 + +| 交付物 | 标准 | 工具 | +|-------|------|------| +| 交互规范文档 | 详细交互说明 | 文档工具 | +| 动效参数表 | 时长/缓动函数 | 表格 | +| 交互Demo | 关键交互演示 | Figma/视频 | + +#### 3.6.4 质量验收标准 + +- [ ] 所有交互有明确的触发条件和反馈 +- [ ] 动效时长符合人体工程学(150-300ms) +- [ ] 无障碍访问支持(键盘/屏幕阅读器) +- [ ] 性能影响已评估(避免重绘/重排) + +--- + +### 3.7 阶段七:用户测试与反馈优化(3-5天) + +#### 3.7.1 工作内容 + +1. **可用性测试** + - 测试对象:目标用户5-8人 + - 测试任务: + - 创建新客户 + - 创建新订单 + - 查询客户历史订单 + - 变更订单状态 + - 测试指标: + - 任务完成率 + - 完成时间 + - 错误率 + - 满意度评分 + +2. **A/B测试(可选)** + - 表格视图 vs 卡片视图 + - 不同按钮位置 + - 不同颜色方案 + +3. **反馈收集与优化** + - 整理测试问题 + - 优先级排序 + - 设计调整 + - 二次验证 + +#### 3.7.2 测试检查清单 + +| 检查项 | 测试方法 | 通过标准 | +|-------|---------|---------| +| 核心任务完成率 | 用户测试 | ≥90% | +| 首次使用无帮助完成 | 用户测试 | ≥70% | +| 页面加载时间 | 性能测试 | ≤2s | +| 交互响应时间 | 性能测试 | ≤100ms | +| 视觉一致性 | 设计走查 | 无偏差 | +| 代码实现一致性 | 开发走查 | 还原度≥95% | + +#### 3.7.3 交付物 + +| 交付物 | 标准 | 工具 | +|-------|------|------| +| 测试报告 | 问题清单+改进建议 | 文档工具 | +| 优化后的设计稿 | 修改后的高保真 | Figma | +| 设计走查记录 | 开发还原度检查 | 表格 | + +#### 3.7.4 质量验收标准 + +- [ ] 核心任务完成率≥90% +- [ ] 严重问题已修复 +- [ ] 开发还原度≥95% +- [ ] 产品/业务方验收通过 + +--- + +## 四、实施建议 + +### 4.1 技术实现建议 + +#### 4.1.1 前端技术栈 + +| 技术 | 用途 | 说明 | +|-----|------|------| +| Vue 2 | 框架 | 与现有项目保持一致 | +| Element UI | 组件库 | 基于shipping_system风格定制主题 | +| SCSS | 样式 | 使用CSS变量实现主题 | +| ECharts | 图表 | 统一图表风格 | + +#### 4.1.2 样式实现策略 + +```scss +// 主题变量文件:styles/theme.scss +:root { + // 提取shipping_system配色 + --smg-bg: #1a1c1e; + --smg-bg-card: #222426; + --smg-bg-input: #2a2d30; + --smg-border: #3a3d41; + --smg-text: #c8ccd0; + --smg-text-secondary: #8a8f96; + --smg-primary: #e8b400; + --smg-success: #27ae60; + --smg-warning: #e67e22; + --smg-danger: #e74c3c; + --smg-info: #3498db; +} + +// Element UI主题覆盖 +.el-button--primary { + background-color: var(--smg-primary); + border-color: var(--smg-primary); + color: #000; + font-weight: 700; +} + +.el-table { + background-color: var(--smg-bg-card); + th { + background-color: var(--smg-bg-input); + border-bottom: 2px solid var(--smg-primary); + text-transform: uppercase; + font-size: 11px; + letter-spacing: 0.5px; + } +} +``` + +### 4.2 组件复用建议 + +| shipping_system组件 | 当前项目对应 | 复用方式 | +|-------------------|-------------|---------| +| 顶部导航栏 | 现有侧边栏+顶部 | 提取配色方案 | +| 数据表格 | Element Table | 定制主题样式 | +| Modal弹窗 | Element Dialog | 定制暗黑主题 | +| 状态Badge | Element Tag | 定制颜色方案 | +| 统计卡片 | 自定义组件 | 复用布局结构 | +| 搜索框 | Element Input | 添加搜索图标 | +| 表单布局 | Element Form | 复用2列布局 | + +### 4.3 开发排期建议 + +| 阶段 | 工期 | 并行任务 | +|-----|------|---------| +| 需求分析 | 3-5天 | 技术预研 | +| 信息架构 | 2-3天 | - | +| 线框图 | 3-5天 | 接口开发 | +| 视觉规范 | 2-3天 | 组件开发 | +| 高保真原型 | 5-7天 | 后端开发 | +| 交互细节 | 2-3天 | 前端开发 | +| 测试优化 | 3-5天 | 联调测试 | + +**总计:20-30天** + +--- + +## 五、附录 + +### 5.1 参考资源 + +- shipping_system demo路径:`/shipping_system/static/index.html` +- 当前项目前端路径:`/ruoyi-ui/src/views/bid/` +- 设计规范文档:`/doc/design-system/` + +### 5.2 术语表 + +| 术语 | 说明 | +|-----|------| +| SMG | Shipping Management System 发货管理系统 | +| RFQ | Request for Quotation 询价单 | +| SKU | Stock Keeping Unit 库存单位 | +| P0/P1/P2 | 优先级:高/中/低 | + +### 5.3 版本记录 + +| 版本 | 日期 | 修改内容 | 作者 | +|-----|------|---------|------| +| v1.0 | 2026-06-03 | 初始版本 | AI Assistant | + +--- + +**文档结束** diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizClientController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizClientController.java new file mode 100644 index 00000000..b71c2a35 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizClientController.java @@ -0,0 +1,67 @@ +package com.ruoyi.web.controller.bid; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.system.domain.bid.BizClient; +import com.ruoyi.system.service.bid.IBizClientService; + +@RestController +@RequestMapping("/bid/client") +public class BizClientController extends BaseController { + @Autowired + private IBizClientService service; + + @PreAuthorize("@ss.hasPermi('bid:client:list')") + @GetMapping("/list") + public TableDataInfo list(BizClient query) { + startPage(); + List list = service.selectBizClientList(query); + return getDataTable(list); + } + + @PreAuthorize("@ss.hasPermi('bid:client:query')") + @GetMapping("/{id}") + public AjaxResult getInfo(@PathVariable Long id) { + return success(service.selectBizClientById(id)); + } + + @PreAuthorize("@ss.hasPermi('bid:client:add')") + @Log(title = "甲方客户", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody BizClient record) { + record.setCreateBy(getUsername()); + return toAjax(service.insertBizClient(record)); + } + + @PreAuthorize("@ss.hasPermi('bid:client:edit')") + @Log(title = "甲方客户", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody BizClient record) { + record.setUpdateBy(getUsername()); + return toAjax(service.updateBizClient(record)); + } + + @PreAuthorize("@ss.hasPermi('bid:client:remove')") + @Log(title = "甲方客户", businessType = BusinessType.DELETE) + @DeleteMapping("/{clientIds}") + public AjaxResult remove(@PathVariable Long[] clientIds) { + return toAjax(service.deleteBizClientByIds(clientIds)); + } + + /** + * 查询客户的关联历史发货单 + * 链路: client → client_quote → rfq → delivery_order + */ + @PreAuthorize("@ss.hasPermi('bid:client:query')") + @GetMapping("/{clientId}/orders") + public AjaxResult clientOrders(@PathVariable Long clientId) { + return success(service.selectClientDeliveryOrders(clientId)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizDeliveryOrderController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizDeliveryOrderController.java new file mode 100644 index 00000000..515bd259 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizDeliveryOrderController.java @@ -0,0 +1,57 @@ +package com.ruoyi.web.controller.bid; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.system.domain.bid.BizDeliveryOrder; +import com.ruoyi.system.service.bid.IBizDeliveryOrderService; + +@RestController +@RequestMapping("/bid/delivery") +public class BizDeliveryOrderController extends BaseController { + @Autowired + private IBizDeliveryOrderService service; + + @PreAuthorize("@ss.hasPermi('bid:order:pending') or @ss.hasPermi('bid:order:transit') or @ss.hasPermi('bid:order:history')") + @GetMapping("/list") + public TableDataInfo list(BizDeliveryOrder query) { + startPage(); + List list = service.selectBizDeliveryOrderList(query); + return getDataTable(list); + } + + @PreAuthorize("@ss.hasPermi('bid:order:query')") + @GetMapping("/{id}") + public AjaxResult getInfo(@PathVariable Long id) { + return success(service.selectBizDeliveryOrderById(id)); + } + + @PreAuthorize("@ss.hasPermi('bid:order:status')") + @Log(title = "发货管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody BizDeliveryOrder record) { + record.setCreateBy(getUsername()); + return toAjax(service.insertBizDeliveryOrder(record)); + } + + @PreAuthorize("@ss.hasPermi('bid:order:status')") + @Log(title = "发货管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody BizDeliveryOrder record) { + record.setUpdateBy(getUsername()); + return toAjax(service.updateBizDeliveryOrder(record)); + } + + @PreAuthorize("@ss.hasPermi('bid:order:pending')") + @Log(title = "发货管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{doIds}") + public AjaxResult remove(@PathVariable Long[] doIds) { + return toAjax(service.deleteBizDeliveryOrderByIds(doIds)); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizClient.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizClient.java new file mode 100644 index 00000000..e04161c7 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizClient.java @@ -0,0 +1,43 @@ +package com.ruoyi.system.domain.bid; + +import com.ruoyi.common.core.domain.BaseEntity; + +public class BizClient extends BaseEntity { + private Long clientId; + private Long tenantId; + private String clientNo; + private String clientName; + private String contact; + private String phone; + private String email; + private String city; + private String address; + private String grade; + private String source; + private String status; + + public Long getClientId() { return clientId; } + public void setClientId(Long clientId) { this.clientId = clientId; } + public Long getTenantId() { return tenantId; } + public void setTenantId(Long tenantId) { this.tenantId = tenantId; } + public String getClientNo() { return clientNo; } + public void setClientNo(String clientNo) { this.clientNo = clientNo; } + public String getClientName() { return clientName; } + public void setClientName(String clientName) { this.clientName = clientName; } + public String getContact() { return contact; } + public void setContact(String contact) { this.contact = contact; } + public String getPhone() { return phone; } + public void setPhone(String phone) { this.phone = phone; } + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } + public String getCity() { return city; } + public void setCity(String city) { this.city = city; } + public String getAddress() { return address; } + public void setAddress(String address) { this.address = address; } + public String getGrade() { return grade; } + public void setGrade(String grade) { this.grade = grade; } + public String getSource() { return source; } + public void setSource(String source) { this.source = source; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizDeliveryOrder.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizDeliveryOrder.java new file mode 100644 index 00000000..86294caf --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizDeliveryOrder.java @@ -0,0 +1,59 @@ +package com.ruoyi.system.domain.bid; + +import com.ruoyi.common.core.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +public class BizDeliveryOrder extends BaseEntity { + private Long doId; + private Long tenantId; + private String doNo; + private Long rfqId; + private Long quotationId; + private Long supplierId; + private BigDecimal totalAmount; + private String currency; + @JsonFormat(pattern = "yyyy-MM-dd") + private Date deliveryDate; + @JsonFormat(pattern = "yyyy-MM-dd") + private Date delayDate; + @JsonFormat(pattern = "yyyy-MM-dd") + private Date actualCloseDate; + private String closeDateSetBy; + private String deliveryStatus; + private List items; + private String supplierName; + + public Long getDoId() { return doId; } + public void setDoId(Long doId) { this.doId = doId; } + public Long getTenantId() { return tenantId; } + public void setTenantId(Long tenantId) { this.tenantId = tenantId; } + public String getDoNo() { return doNo; } + public void setDoNo(String doNo) { this.doNo = doNo; } + public Long getRfqId() { return rfqId; } + public void setRfqId(Long rfqId) { this.rfqId = rfqId; } + public Long getQuotationId() { return quotationId; } + public void setQuotationId(Long quotationId) { this.quotationId = quotationId; } + public Long getSupplierId() { return supplierId; } + public void setSupplierId(Long supplierId) { this.supplierId = supplierId; } + public BigDecimal getTotalAmount() { return totalAmount; } + public void setTotalAmount(BigDecimal totalAmount) { this.totalAmount = totalAmount; } + public String getCurrency() { return currency; } + public void setCurrency(String currency) { this.currency = currency; } + public Date getDeliveryDate() { return deliveryDate; } + public void setDeliveryDate(Date deliveryDate) { this.deliveryDate = deliveryDate; } + public Date getDelayDate() { return delayDate; } + public void setDelayDate(Date delayDate) { this.delayDate = delayDate; } + public Date getActualCloseDate() { return actualCloseDate; } + public void setActualCloseDate(Date actualCloseDate) { this.actualCloseDate = actualCloseDate; } + public String getCloseDateSetBy() { return closeDateSetBy; } + public void setCloseDateSetBy(String closeDateSetBy) { this.closeDateSetBy = closeDateSetBy; } + public String getDeliveryStatus() { return deliveryStatus; } + public void setDeliveryStatus(String deliveryStatus) { this.deliveryStatus = deliveryStatus; } + public List getItems() { return items; } + public void setItems(List items) { this.items = items; } + public String getSupplierName() { return supplierName; } + public void setSupplierName(String supplierName) { this.supplierName = supplierName; } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizDeliveryOrderItem.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizDeliveryOrderItem.java new file mode 100644 index 00000000..5afd4448 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizDeliveryOrderItem.java @@ -0,0 +1,37 @@ +package com.ruoyi.system.domain.bid; + +import java.math.BigDecimal; + +public class BizDeliveryOrderItem { + private Long itemId; + private Long doId; + private Long materialId; + private String materialName; + private String spec; + private String unit; + private BigDecimal quantity; + private BigDecimal unitPrice; + private BigDecimal totalPrice; + private String remark; + + public Long getItemId() { return itemId; } + public void setItemId(Long itemId) { this.itemId = itemId; } + public Long getDoId() { return doId; } + public void setDoId(Long doId) { this.doId = doId; } + public Long getMaterialId() { return materialId; } + public void setMaterialId(Long materialId) { this.materialId = materialId; } + public String getMaterialName() { return materialName; } + public void setMaterialName(String materialName) { this.materialName = materialName; } + public String getSpec() { return spec; } + public void setSpec(String spec) { this.spec = spec; } + public String getUnit() { return unit; } + public void setUnit(String unit) { this.unit = unit; } + public BigDecimal getQuantity() { return quantity; } + public void setQuantity(BigDecimal quantity) { this.quantity = quantity; } + public BigDecimal getUnitPrice() { return unitPrice; } + public void setUnitPrice(BigDecimal unitPrice) { this.unitPrice = unitPrice; } + public BigDecimal getTotalPrice() { return totalPrice; } + public void setTotalPrice(BigDecimal totalPrice) { this.totalPrice = totalPrice; } + public String getRemark() { return remark; } + public void setRemark(String remark) { this.remark = remark; } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizClientMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizClientMapper.java new file mode 100644 index 00000000..a39c313e --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizClientMapper.java @@ -0,0 +1,15 @@ +package com.ruoyi.system.mapper.bid; + +import com.ruoyi.system.domain.bid.BizClient; +import java.util.List; +import java.util.Map; + +public interface BizClientMapper { + List selectBizClientList(BizClient query); + BizClient selectBizClientById(Long id); + int insertBizClient(BizClient record); + int updateBizClient(BizClient record); + int deleteBizClientById(Long id); + int deleteBizClientByIds(Long[] ids); + List> selectClientDeliveryOrders(Long clientId); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizDeliveryOrderItemMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizDeliveryOrderItemMapper.java new file mode 100644 index 00000000..b1975035 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizDeliveryOrderItemMapper.java @@ -0,0 +1,10 @@ +package com.ruoyi.system.mapper.bid; + +import com.ruoyi.system.domain.bid.BizDeliveryOrderItem; +import java.util.List; + +public interface BizDeliveryOrderItemMapper { + List selectItemsByDoId(Long doId); + int insertBizDeliveryOrderItem(BizDeliveryOrderItem item); + int deleteByDoId(Long doId); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizDeliveryOrderMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizDeliveryOrderMapper.java new file mode 100644 index 00000000..61104d19 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizDeliveryOrderMapper.java @@ -0,0 +1,13 @@ +package com.ruoyi.system.mapper.bid; + +import com.ruoyi.system.domain.bid.BizDeliveryOrder; +import java.util.List; + +public interface BizDeliveryOrderMapper { + List selectBizDeliveryOrderList(BizDeliveryOrder query); + BizDeliveryOrder selectBizDeliveryOrderById(Long id); + int insertBizDeliveryOrder(BizDeliveryOrder record); + int updateBizDeliveryOrder(BizDeliveryOrder record); + int deleteBizDeliveryOrderById(Long id); + int deleteBizDeliveryOrderByIds(Long[] ids); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizClientService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizClientService.java new file mode 100644 index 00000000..beb9fa33 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizClientService.java @@ -0,0 +1,15 @@ +package com.ruoyi.system.service.bid; + +import com.ruoyi.system.domain.bid.BizClient; +import java.util.List; +import java.util.Map; + +public interface IBizClientService { + List selectBizClientList(BizClient query); + BizClient selectBizClientById(Long id); + int insertBizClient(BizClient record); + int updateBizClient(BizClient record); + int deleteBizClientById(Long id); + int deleteBizClientByIds(Long[] ids); + List> selectClientDeliveryOrders(Long clientId); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizDeliveryOrderService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizDeliveryOrderService.java new file mode 100644 index 00000000..133e82ac --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizDeliveryOrderService.java @@ -0,0 +1,13 @@ +package com.ruoyi.system.service.bid; + +import com.ruoyi.system.domain.bid.BizDeliveryOrder; +import java.util.List; + +public interface IBizDeliveryOrderService { + List selectBizDeliveryOrderList(BizDeliveryOrder query); + BizDeliveryOrder selectBizDeliveryOrderById(Long id); + int insertBizDeliveryOrder(BizDeliveryOrder record); + int updateBizDeliveryOrder(BizDeliveryOrder record); + int deleteBizDeliveryOrderById(Long id); + int deleteBizDeliveryOrderByIds(Long[] ids); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizClientServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizClientServiceImpl.java new file mode 100644 index 00000000..a1513acf --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizClientServiceImpl.java @@ -0,0 +1,50 @@ +package com.ruoyi.system.service.bid.impl; + +import com.ruoyi.system.domain.bid.BizClient; +import com.ruoyi.system.mapper.bid.BizClientMapper; +import com.ruoyi.system.service.bid.IBizClientService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.util.List; +import java.util.Map; + +@Service +public class BizClientServiceImpl implements IBizClientService { + @Autowired + private BizClientMapper mapper; + + @Override + public List selectBizClientList(BizClient query) { + return mapper.selectBizClientList(query); + } + + @Override + public BizClient selectBizClientById(Long id) { + return mapper.selectBizClientById(id); + } + + @Override + public int insertBizClient(BizClient record) { + return mapper.insertBizClient(record); + } + + @Override + public int updateBizClient(BizClient record) { + return mapper.updateBizClient(record); + } + + @Override + public int deleteBizClientById(Long id) { + return mapper.deleteBizClientById(id); + } + + @Override + public int deleteBizClientByIds(Long[] ids) { + return mapper.deleteBizClientByIds(ids); + } + + @Override + public List> selectClientDeliveryOrders(Long clientId) { + return mapper.selectClientDeliveryOrders(clientId); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizDeliveryOrderServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizDeliveryOrderServiceImpl.java new file mode 100644 index 00000000..458861e5 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizDeliveryOrderServiceImpl.java @@ -0,0 +1,89 @@ +package com.ruoyi.system.service.bid.impl; + +import com.ruoyi.system.domain.bid.BizDeliveryOrder; +import com.ruoyi.system.domain.bid.BizDeliveryOrderItem; +import com.ruoyi.system.mapper.bid.BizDeliveryOrderMapper; +import com.ruoyi.system.mapper.bid.BizDeliveryOrderItemMapper; +import com.ruoyi.system.service.bid.IBizDeliveryOrderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +@Service +public class BizDeliveryOrderServiceImpl implements IBizDeliveryOrderService { + @Autowired + private BizDeliveryOrderMapper mapper; + @Autowired + private BizDeliveryOrderItemMapper itemMapper; + + @Override + public List selectBizDeliveryOrderList(BizDeliveryOrder query) { + return mapper.selectBizDeliveryOrderList(query); + } + + @Override + public BizDeliveryOrder selectBizDeliveryOrderById(Long id) { + BizDeliveryOrder d = mapper.selectBizDeliveryOrderById(id); + if (d != null) d.setItems(itemMapper.selectItemsByDoId(id)); + return d; + } + + @Override + @Transactional + public int insertBizDeliveryOrder(BizDeliveryOrder record) { + if (record.getDoNo() == null || record.getDoNo().isEmpty()) { + record.setDoNo("DO" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())); + } + if (record.getDeliveryStatus() == null || record.getDeliveryStatus().isEmpty()) { + record.setDeliveryStatus("pending"); + } + int rows = mapper.insertBizDeliveryOrder(record); + if (record.getItems() != null) { + BigDecimal total = BigDecimal.ZERO; + for (BizDeliveryOrderItem item : record.getItems()) { + item.setDoId(record.getDoId()); + if (item.getUnitPrice() != null && item.getQuantity() != null) { + item.setTotalPrice(item.getUnitPrice().multiply(item.getQuantity())); + total = total.add(item.getTotalPrice()); + } + itemMapper.insertBizDeliveryOrderItem(item); + } + record.setTotalAmount(total); + mapper.updateBizDeliveryOrder(record); + } + return rows; + } + + @Override + @Transactional + public int updateBizDeliveryOrder(BizDeliveryOrder record) { + itemMapper.deleteByDoId(record.getDoId()); + if (record.getItems() != null) { + BigDecimal total = BigDecimal.ZERO; + for (BizDeliveryOrderItem item : record.getItems()) { + item.setDoId(record.getDoId()); + if (item.getUnitPrice() != null && item.getQuantity() != null) { + item.setTotalPrice(item.getUnitPrice().multiply(item.getQuantity())); + total = total.add(item.getTotalPrice()); + } + itemMapper.insertBizDeliveryOrderItem(item); + } + record.setTotalAmount(total); + } + return mapper.updateBizDeliveryOrder(record); + } + + @Override + public int deleteBizDeliveryOrderById(Long id) { + return mapper.deleteBizDeliveryOrderById(id); + } + + @Override + public int deleteBizDeliveryOrderByIds(Long[] ids) { + return mapper.deleteBizDeliveryOrderByIds(ids); + } +} diff --git a/ruoyi-system/src/main/resources/mapper/bid/BizClientMapper.xml b/ruoyi-system/src/main/resources/mapper/bid/BizClientMapper.xml new file mode 100644 index 00000000..f86ac8d9 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/bid/BizClientMapper.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO biz_client(tenant_id,client_no,client_name,contact,phone,email,city,address,grade,source,status,create_by,create_time) + VALUES(#{tenantId},#{clientNo},#{clientName},#{contact},#{phone},#{email},#{city},#{address},#{grade},#{source},#{status},#{createBy},NOW()) + + + + UPDATE biz_client + + client_no=#{clientNo}, + client_name=#{clientName}, + contact=#{contact}, + phone=#{phone}, + email=#{email}, + city=#{city}, + address=#{address}, + grade=#{grade}, + source=#{source}, + status=#{status}, + update_by=#{updateBy}, update_time=NOW() + + WHERE client_id=#{clientId} + + + DELETE FROM biz_client WHERE client_id=#{id} + + + DELETE FROM biz_client WHERE client_id IN + #{id} + + + + diff --git a/ruoyi-system/src/main/resources/mapper/bid/BizDeliveryOrderItemMapper.xml b/ruoyi-system/src/main/resources/mapper/bid/BizDeliveryOrderItemMapper.xml new file mode 100644 index 00000000..5d7cf4fa --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/bid/BizDeliveryOrderItemMapper.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + INSERT INTO biz_delivery_order_item(do_id,material_id,material_name,spec,unit,quantity,unit_price,total_price,remark) + VALUES(#{doId},#{materialId},#{materialName},#{spec},#{unit},#{quantity},#{unitPrice},#{totalPrice},#{remark}) + + + DELETE FROM biz_delivery_order_item WHERE do_id=#{doId} + diff --git a/ruoyi-system/src/main/resources/mapper/bid/BizDeliveryOrderMapper.xml b/ruoyi-system/src/main/resources/mapper/bid/BizDeliveryOrderMapper.xml new file mode 100644 index 00000000..e6982300 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/bid/BizDeliveryOrderMapper.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO biz_delivery_order(tenant_id,do_no,rfq_id,quotation_id,supplier_id,total_amount,currency,delivery_date,delay_date,actual_close_date,close_date_set_by,delivery_status,remark,create_by,create_time) + VALUES(#{tenantId},#{doNo},#{rfqId},#{quotationId},#{supplierId},#{totalAmount},#{currency},#{deliveryDate},#{delayDate},#{actualCloseDate},#{closeDateSetBy},#{deliveryStatus},#{remark},#{createBy},NOW()) + + + + UPDATE biz_delivery_order + + do_no=#{doNo}, + supplier_id=#{supplierId}, + total_amount=#{totalAmount}, + delivery_date=#{deliveryDate}, + delay_date=#{delayDate}, + actual_close_date=#{actualCloseDate}, + close_date_set_by=#{closeDateSetBy}, + delivery_status=#{deliveryStatus}, + remark=#{remark}, + update_by=#{updateBy}, update_time=NOW() + + WHERE do_id=#{doId} + + + DELETE FROM biz_delivery_order WHERE do_id=#{id} + + + DELETE FROM biz_delivery_order WHERE do_id IN + #{id} + + diff --git a/ruoyi-ui/src/api/bid/client.js b/ruoyi-ui/src/api/bid/client.js new file mode 100644 index 00000000..025a7f69 --- /dev/null +++ b/ruoyi-ui/src/api/bid/client.js @@ -0,0 +1,8 @@ +import request from '@/utils/request' +const baseUrl = '/bid/client' +export const listClient = (params) => request({ url: baseUrl + '/list', method: 'get', params }) +export const getClient = (id) => request({ url: baseUrl + '/' + id, method: 'get' }) +export const addClient = (data) => request({ url: baseUrl, method: 'post', data }) +export const updateClient = (data) => request({ url: baseUrl, method: 'put', data }) +export const delClient = (ids) => request({ url: baseUrl + '/' + ids, method: 'delete' }) +export const getClientOrders = (id) => request({ url: baseUrl + '/' + id + '/orders', method: 'get' }) diff --git a/ruoyi-ui/src/api/bid/delivery.js b/ruoyi-ui/src/api/bid/delivery.js new file mode 100644 index 00000000..04f337ec --- /dev/null +++ b/ruoyi-ui/src/api/bid/delivery.js @@ -0,0 +1,11 @@ +import request from '@/utils/request' +const baseUrl = '/bid/delivery' +export const listDelivery = (params) => request({ url: baseUrl + '/list', method: 'get', params }) +export const getDelivery = (id) => request({ url: baseUrl + '/' + id, method: 'get' }) +export const addDelivery = (data) => request({ url: baseUrl, method: 'post', data }) +export const updateDelivery = (data) => request({ url: baseUrl, method: 'put', data }) +export const delDelivery = (ids) => request({ url: baseUrl + '/' + ids, method: 'delete' }) +export const shipDelivery = (id) => request({ url: baseUrl + '/' + id + '/ship', method: 'put' }) +export const completeDelivery = (id) => request({ url: baseUrl + '/' + id + '/complete', method: 'put' }) +export const recallDelivery = (id) => request({ url: baseUrl + '/' + id + '/recall', method: 'put' }) +export const setCloseDate = (id, closeDate) => request({ url: baseUrl + '/' + id + '/closeDate', method: 'put', params: { closeDate } }) diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js index 45dfaaae..452f44bb 100644 --- a/ruoyi-ui/src/router/index.js +++ b/ruoyi-ui/src/router/index.js @@ -176,6 +176,19 @@ export const dynamicRoutes = [ meta: { title: '甲方报价单详情', activeMenu: '/clientquote' } }] }, + // ── 甲方客户 ── + { + path: '/bid/client', + component: Layout, + permissions: ['bid:client:list'], + children: [{ + path: '', + component: () => import('@/views/bid/client/index'), + name: 'Client', + meta: { title: '甲方客户', activeMenu: '/bid/client' } + }] + }, + { path: '/bid/comparison/detail', component: Layout, diff --git a/ruoyi-ui/src/views/bid/client/index.vue b/ruoyi-ui/src/views/bid/client/index.vue new file mode 100644 index 00000000..6d81cd71 --- /dev/null +++ b/ruoyi-ui/src/views/bid/client/index.vue @@ -0,0 +1,350 @@ + + + + + diff --git a/sql/fix_menu_all.sql b/sql/fix_menu_all.sql new file mode 100644 index 00000000..fee357e7 --- /dev/null +++ b/sql/fix_menu_all.sql @@ -0,0 +1,114 @@ +-- ============================================================ +-- 菜单全面修复脚本 +-- 1. 修复所有乱码菜单名称(根据 perms 字段还原) +-- 2. 新增菜单移至主目录(parent_id=0),因 智慧报价(2000) 已停用 +-- 3. 插入缺失的菜单条目 +-- ============================================8=============== + +SET NAMES utf8mb4; + +-- ════════════════════════════════════════════════════════════ +-- 第一部分:修复所有乱码菜单名称 +-- ════════════════════════════════════════════════════════════ + +-- bid 模块主菜单(parent_id=0 且无 perms 的父节点) +UPDATE sys_menu SET menu_name = '智慧报价' WHERE menu_id = 2000; + +-- bid 模块子菜单 +UPDATE sys_menu SET menu_name = '物料管理' WHERE perms = 'bid:material:list'; +UPDATE sys_menu SET menu_name = '新增' WHERE perms = 'bid:material:add' AND menu_type = 'F'; +UPDATE sys_menu SET menu_name = '编辑' WHERE perms = 'bid:material:edit' AND menu_type = 'F'; +UPDATE sys_menu SET menu_name = '删除' WHERE perms = 'bid:material:remove' AND menu_type = 'F'; +UPDATE sys_menu SET menu_name = '查询' WHERE perms = 'bid:material:query' AND menu_type = 'F'; + +UPDATE sys_menu SET menu_name = '供应商管理' WHERE perms = 'bid:supplier:list'; +UPDATE sys_menu SET menu_name = '供应商报价' WHERE perms = 'bid:quotation:list'; +UPDATE sys_menu SET menu_name = '报价请求' WHERE perms = 'bid:rfq:list'; +UPDATE sys_menu SET menu_name = '智慧比价' WHERE perms = 'bid:comparison:list'; +UPDATE sys_menu SET menu_name = '采购单' WHERE perms = 'bid:purchaseorder:list'; +UPDATE sys_menu SET menu_name = '供应商评价' WHERE perms = 'bid:evaluation:list'; +UPDATE sys_menu SET menu_name = '订单异议' WHERE perms = 'bid:objection:list'; +UPDATE sys_menu SET menu_name = '交易记录' WHERE perms = 'bid:transaction:list'; +UPDATE sys_menu SET menu_name = '租户管理' WHERE perms = 'bid:tenant:list'; + +-- 甲方报价单 +UPDATE sys_menu SET menu_name = '甲方报价' WHERE perms = 'bid:clientquote:list'; +UPDATE sys_menu SET menu_name = '新增报价' WHERE perms = 'bid:clientquote:add' AND menu_type = 'F'; +UPDATE sys_menu SET menu_name = '编辑报价' WHERE perms = 'bid:clientquote:edit' AND menu_type = 'F'; +UPDATE sys_menu SET menu_name = '删除报价' WHERE perms = 'bid:clientquote:remove' AND menu_type = 'F'; + +-- 统计分析 +UPDATE sys_menu SET menu_name = '统计分析' WHERE perms = 'bid:report:list'; +UPDATE sys_menu SET menu_name = '采购总览看板' WHERE perms = 'bid:report:dashboard'; +UPDATE sys_menu SET menu_name = '采购成本分析' WHERE perms = 'bid:report:cost'; +UPDATE sys_menu SET menu_name = '供应商绩效' WHERE perms = 'bid:report:supplier'; + +-- ════════════════════════════════════════════════════════════ +-- 第二部分:修复我们的新菜单名称 +-- ════════════════════════════════════════════════════════════ + +UPDATE sys_menu SET menu_name = '订单履约' WHERE perms = 'bid:order:list'; +UPDATE sys_menu SET menu_name = '待发订单' WHERE perms = 'bid:order:pending'; +UPDATE sys_menu SET menu_name = '历史订单' WHERE perms = 'bid:order:history'; +UPDATE sys_menu SET menu_name = '结单时间管理' WHERE perms = 'bid:order:closeDate'; +UPDATE sys_menu SET menu_name = '甲方客户' WHERE perms = 'bid:client:list'; +UPDATE sys_menu SET menu_name = '编辑客户' WHERE perms = 'bid:client:edit' AND menu_type = 'F'; +UPDATE sys_menu SET menu_name = '删除客户' WHERE perms = 'bid:client:remove' AND menu_type = 'F'; +UPDATE sys_menu SET menu_name = '结单录入' WHERE perms = 'bid:order:closeDate:edit' AND menu_type = 'F'; +UPDATE sys_menu SET menu_name = '操作记录' WHERE perms = 'bid:operationlog:list'; + +-- ════════════════════════════════════════════════════════════ +-- 第三部分:将新菜单移至主目录(parent_id=0) +-- 因为 智慧报价(2000) 已停用,其下的子菜单不可见 +-- ════════════════════════════════════════════════════════════ + +-- 订单履约(2023) → 根目录,排序20 +UPDATE sys_menu SET parent_id = 0, order_num = 20 WHERE menu_id = 2023; +-- 甲方客户(2028) → 根目录,排序21 +UPDATE sys_menu SET parent_id = 0, order_num = 21 WHERE menu_id = 2028; +-- 操作记录(2029) → 根目录,排序22 +UPDATE sys_menu SET parent_id = 0, order_num = 22 WHERE menu_id = 2029; + +-- ════════════════════════════════════════════════════════════ +-- 第四部分:插入缺失的菜单条目 +-- ════════════════════════════════════════════════════════════ + +-- 在途订单 (2025) +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(2025, '在途订单', 2023, 2, 'transit', 'bid/order/transit', 1, 0, 'C', '0', '0', 'bid:order:transit', 'truck', 'admin', NOW()); + +-- 新增客户按钮 (2030) +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(2030, '新增客户', 2028, 1, '#', NULL, 1, 0, 'F', '0', '0', 'bid:client:add', '#', 'admin', NOW()); + +-- 查询客户按钮 (2033) +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(2033, '查询客户', 2028, 4, '#', NULL, 1, 0, 'F', '0', '0', 'bid:client:query', '#', 'admin', NOW()); + +-- 订单查询按钮 (2034) +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(2034, '订单查询', 2024, 1, '#', NULL, 1, 0, 'F', '0', '0', 'bid:order:query', '#', 'admin', NOW()); + +-- 订单状态变更按钮 (2035) +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(2035, '订单状态变更', 2024, 2, '#', NULL, 1, 0, 'F', '0', '0', 'bid:order:status', '#', 'admin', NOW()); + +-- 操作记录查询按钮 (2037) +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(2037, '操作记录查询', 2029, 1, '#', NULL, 1, 0, 'F', '0', '0', 'bid:operationlog:query', '#', 'admin', NOW()); + +-- ════════════════════════════════════════════════════════════ +-- 第五部分:角色-菜单关联(确保 admin 有权限) +-- ════════════════════════════════════════════════════════════ + +INSERT IGNORE INTO sys_role_menu (role_id, menu_id) +SELECT 1, menu_id FROM sys_menu WHERE menu_id IN (2025, 2030, 2033, 2034, 2035, 2037); + +-- ════════════════════════════════════════════════════════════ +-- 验证 +-- ════════════════════════════════════════════════════════════ + +SELECT menu_id, menu_name, parent_id, perms, order_num, + CASE WHEN status='0' THEN '正常' ELSE '停用' END AS status +FROM sys_menu WHERE menu_id BETWEEN 2000 AND 2037 +ORDER BY menu_id; diff --git a/sql/fix_menu_garbled.sql b/sql/fix_menu_garbled.sql new file mode 100644 index 00000000..a8cf158d --- /dev/null +++ b/sql/fix_menu_garbled.sql @@ -0,0 +1,30 @@ +SET NAMES utf8mb4; + +-- 修复菜单名称乱码问题 +-- 根据截图中显示的权限字符,还原正确的菜单名称 + +-- 订单管理相关菜单 +UPDATE sys_menu SET menu_name = '订单管理' WHERE perms = 'bid:order:list' AND menu_name LIKE '%璁㈠%'; +UPDATE sys_menu SET menu_name = '待发订单' WHERE perms = 'bid:order:pending' AND menu_name LIKE '%寰%'; +UPDATE sys_menu SET menu_name = '在途订单' WHERE perms = 'bid:order:transit' AND menu_name LIKE '%鍦ㄩ%'; +UPDATE sys_menu SET menu_name = '历史订单' WHERE perms = 'bid:order:history' AND menu_name LIKE '%鍘嗗彶%'; +UPDATE sys_menu SET menu_name = '结单时间' WHERE perms = 'bid:order:closeDate' AND menu_name LIKE '%缁撳崟%'; + +-- 甲方客户管理 +UPDATE sys_menu SET menu_name = '甲方客户' WHERE perms = 'bid:client:list' AND menu_name LIKE '%鐢插彛%'; + +-- 操作记录 +UPDATE sys_menu SET menu_name = '操作记录' WHERE perms = 'bid:operationlog:list' AND menu_name LIKE '%鎿嶄綔%'; +UPDATE sys_menu SET menu_name = '查询' WHERE perms = 'bid:operationlog:query' AND menu_name LIKE '%鏌ヨ%'; + +-- 如果上述更新没有匹配到,使用menu_id直接更新(根据截图中的排序号判断) +-- 订单管理目录(排序号10) +UPDATE sys_menu SET menu_name = '订单管理' WHERE menu_id IN ( + SELECT menu_id FROM (SELECT menu_id FROM sys_menu WHERE parent_id = 0 AND order_num = 10) AS t +); + +-- 查询更新结果 +SELECT menu_id, menu_name, perms, order_num +FROM sys_menu +WHERE perms LIKE 'bid:order:%' OR perms LIKE 'bid:client:%' OR perms LIKE 'bid:operationlog:%' +ORDER BY menu_id; diff --git a/sql/fix_menu_garbled_complete.sql b/sql/fix_menu_garbled_complete.sql new file mode 100644 index 00000000..829ab577 --- /dev/null +++ b/sql/fix_menu_garbled_complete.sql @@ -0,0 +1,74 @@ +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ============================================ +-- 菜单名称乱码修复脚本 +-- 根据权限字符(perms)和菜单类型还原正确的菜单名称 +-- ============================================ + +-- 1. 订单管理模块 +UPDATE sys_menu SET menu_name = '订单管理' WHERE perms = 'bid:order:list'; +UPDATE sys_menu SET menu_name = '待发订单' WHERE perms = 'bid:order:pending'; +UPDATE sys_menu SET menu_name = '在途订单' WHERE perms = 'bid:order:transit'; +UPDATE sys_menu SET menu_name = '历史订单' WHERE perms = 'bid:order:history'; +UPDATE sys_menu SET menu_name = '结单时间' WHERE perms = 'bid:order:closeDate'; + +-- 2. 甲方客户管理 +UPDATE sys_menu SET menu_name = '甲方客户' WHERE perms = 'bid:client:list'; + +-- 3. 操作记录 +UPDATE sys_menu SET menu_name = '操作记录' WHERE perms = 'bid:operationlog:list'; +UPDATE sys_menu SET menu_name = '查询' WHERE perms = 'bid:operationlog:query' AND menu_type = 'F'; + +-- 4. 甲方报价(如果有乱码) +UPDATE sys_menu SET menu_name = '甲方报价' WHERE perms = 'bid:clientquote:list'; +UPDATE sys_menu SET menu_name = '新增' WHERE perms = 'bid:clientquote:add' AND menu_type = 'F'; +UPDATE sys_menu SET menu_name = '编辑' WHERE perms = 'bid:clientquote:edit' AND menu_type = 'F'; +UPDATE sys_menu SET menu_name = '删除' WHERE perms = 'bid:clientquote:remove' AND menu_type = 'F'; +UPDATE sys_menu SET menu_name = '导出' WHERE perms = 'bid:clientquote:export' AND menu_type = 'F'; + +-- 5. 报价请求(RFQ) +UPDATE sys_menu SET menu_name = '报价请求' WHERE perms = 'bid:rfq:list'; + +-- 6. 供应商管理 +UPDATE sys_menu SET menu_name = '供应商管理' WHERE perms = 'bid:supplier:list'; + +-- 7. 物料管理 +UPDATE sys_menu SET menu_name = '物料管理' WHERE perms = 'bid:material:list'; + +-- 8. 智慧比价 +UPDATE sys_menu SET menu_name = '智慧比价' WHERE perms = 'bid:comparison:list'; + +-- 9. 统计分析 +UPDATE sys_menu SET menu_name = '统计分析' WHERE perms = 'bid:report:list'; + +-- 10. 采购单 +UPDATE sys_menu SET menu_name = '采购单' WHERE perms = 'bid:purchaseorder:list'; + +-- 11. 供应商评价 +UPDATE sys_menu SET menu_name = '供应商评价' WHERE perms = 'bid:evaluation:list'; + +-- 12. 交易记录 +UPDATE sys_menu SET menu_name = '交易记录' WHERE perms = 'bid:transaction:list'; + +-- ============================================ +-- 验证修复结果 +-- ============================================ + +SELECT + menu_id, + menu_name, + perms, + menu_type, + CASE menu_type + WHEN 'M' THEN '目录' + WHEN 'C' THEN '菜单' + WHEN 'F' THEN '按钮' + END AS type_name, + order_num, + status +FROM sys_menu +WHERE perms LIKE 'bid:%' +ORDER BY menu_id; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/sql/fix_remaining.sql b/sql/fix_remaining.sql new file mode 100644 index 00000000..40d7f404 --- /dev/null +++ b/sql/fix_remaining.sql @@ -0,0 +1,13 @@ +SET NAMES utf8mb4; + +UPDATE sys_menu SET menu_name = '在途订单' WHERE perms = 'bid:order:transit'; +UPDATE sys_menu SET menu_name = '新增客户' WHERE menu_id = 2030; +UPDATE sys_menu SET menu_name = '查询客户' WHERE menu_id = 2033; +UPDATE sys_menu SET menu_name = '订单查询' WHERE menu_id = 2034; +UPDATE sys_menu SET menu_name = '订单状态变更' WHERE menu_id = 2035; +UPDATE sys_menu SET menu_name = '操作记录查询' WHERE menu_id = 2037; + +SELECT '✅ 修复结果' AS ''; +SELECT menu_id, menu_name, perms FROM sys_menu +WHERE menu_id IN (2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037) +ORDER BY menu_id;