1184 lines
60 KiB
Markdown
1184 lines
60 KiB
Markdown
# 图书进销存系统 — 技术文档
|
||
|
||
> **项目名称**:Cards(图书进销存管理后台)
|
||
> **版本**:1.0.0
|
||
> **最后更新**:2026-06-15
|
||
> **项目路径**:`D:\project\psi_web`
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
1. [项目概述](#1-项目概述)
|
||
2. [技术栈](#2-技术栈)
|
||
3. [项目结构](#3-项目结构)
|
||
4. [构建与部署](#4-构建与部署)
|
||
5. [路由与权限](#5-路由与权限)
|
||
6. [API 架构](#6-api-架构)
|
||
7. [API 接口详表](#7-api-接口详表)
|
||
8. [状态管理](#8-状态管理)
|
||
9. [工具函数](#9-工具函数)
|
||
10. [外部服务集成](#10-外部服务集成)
|
||
11. [核心业务流程](#11-核心业务流程)
|
||
12. [打印服务](#12-打印服务)
|
||
13. [数据模型](#13-数据模型)
|
||
14. [已知问题与维护](#14-已知问题与维护)
|
||
|
||
---
|
||
|
||
## 1. 项目概述
|
||
|
||
本项目是一个面向图书行业的**进销存管理后台系统**,覆盖图书采购入库、库存管理、商品发布、销售出库、发货打单、盘库盘点等全链路业务流程。系统支持多角色(管理员/代理)权限控制,并集成了核价器、快递打印、OCR 识别、孔夫子旧书网登录等外部服务。
|
||
|
||
### 核心业务范围
|
||
|
||
| 模块 | 说明 |
|
||
|------|------|
|
||
| **波次管理** | 相机扫码 → 条码识别 → 书籍信息编辑 → 波次创建/释放 |
|
||
| **订单管理** | 采购订单 → 销售订单 → 出库单 → 发货单,全链路可追溯 |
|
||
| **库存管理** | 库存查询(商品维度/仓库维度)、变动记录、盘库盘点 |
|
||
| **商品管理** | 商品 CRUD、实拍图片管理、多店铺发布/重试、Excel 导入 |
|
||
| **店铺管理** | 多客户店铺(拼多多、孔夫子、闲鱼等)管理、授权状态 |
|
||
| **分账管理** | 分账规则配置、扣款日志查询与导出 |
|
||
| **快递管理** | 快递配置、物流模板、面单打印(拼多多/通用)、单号回填 |
|
||
| **小车管理** | 拣货小车 CRUD、小车-店铺关联 |
|
||
| **系统管理** | 代理账号、员工类型、核价器配置、物流模板、打印机管理、PDA 管理 |
|
||
|
||
---
|
||
|
||
## 2. 技术栈
|
||
|
||
### 2.1 前端框架与依赖
|
||
|
||
| 依赖 | 版本 | 用途 |
|
||
|------|------|------|
|
||
| `vue` | ^3.2.8 | 前端框架(Composition API + `<script setup>`) |
|
||
| `vue-router` | ^4.1.6 | 前端路由(History 模式) |
|
||
| `pinia` | ^2.1.7 | 状态管理 |
|
||
| `element-plus` | ^2.13.7 | UI 组件库(中文 locale,small 尺寸,zIndex 3000) |
|
||
| `@element-plus/icons-vue` | ^2.1.0 | 图标库(全局注册所有图标) |
|
||
| `axios` | ^1.7.9 | HTTP 客户端 |
|
||
| `crypto-js` | ^4.2.0 | 签名算法(MD5/SHA256) |
|
||
| `json-bigint` | ^1.0.0 | 大整数精度处理(替换默认 JSON.parse) |
|
||
| `@zxing/library` | ^0.21.3 | 条形码/二维码扫描 |
|
||
| `jsbarcode` | ^3.12.3 | 条码生成 |
|
||
| `qrcode` | ^1.5.4 | QR 码生成 |
|
||
| `@vue/compiler-sfc` | ^3.2.8 | SFC 编译器 |
|
||
| `sass-embedded` | ^1.99.0 | CSS 预处理器(嵌入版) |
|
||
|
||
### 2.2 工程化工具
|
||
|
||
| 工具 | 版本 | 用途 |
|
||
|------|------|------|
|
||
| `vite` | ^2.5.2 | 构建工具与开发服务器 |
|
||
| `@vitejs/plugin-vue` | ^1.6.0 | Vite Vue 插件 |
|
||
| `typescript` | ^5.5.4 | 类型检查(项目以 JS 为主,仅部分 .ts 文件) |
|
||
| `sass` | ^1.99.0 | CSS 预处理器(dart-sass) |
|
||
|
||
### 2.3 环境变量(`.env`)
|
||
|
||
| 变量 | 值 | 说明 |
|
||
|------|-----|------|
|
||
| `VITE_APP_API_KEY` | `psi` | API 签名密钥 |
|
||
| `VITE_APP_CLIENT_ID` | `psi` | 客户端 ID |
|
||
| `VITE_APP_API_SECRET` | `psi_api_sign_secret` | 签名密钥 |
|
||
|
||
### 2.4 脚本命令
|
||
|
||
| 命令 | 说明 |
|
||
|------|------|
|
||
| `npm run dev` | 启动开发服务器,端口 5174 |
|
||
| `npm run build` | 生产构建,输出到 `dist/` |
|
||
| `npm run serve` | 预览生产构建(`vite preview`) |
|
||
|
||
---
|
||
|
||
## 3. 项目结构
|
||
|
||
```
|
||
src/
|
||
├── api/ # API 层:所有后端接口调用集中于此(31 个文件)
|
||
│ ├── barcode.js # 条码生成
|
||
│ ├── book.js # 书籍信息查询/同步
|
||
│ ├── car.js # 小车管理(CRUD + 小车-店铺关联)
|
||
│ ├── config.js # 核价器配置(直连外部 IP:Port,非 request 封装)
|
||
│ ├── courierConfig.js # 快递配置(createConfig 等,仅部分实现)
|
||
│ ├── dashboard.js # 仪表盘统计
|
||
│ ├── district.js # 行政区划(省/市/区)及运费模板
|
||
│ ├── employee.js # 员工/代理管理
|
||
│ ├── employeeType.js # 员工类型管理
|
||
│ ├── goodsInfo.js # 提交异常书目(product_log/save)
|
||
│ ├── submIllegalBook.js # 异常书目审核/审批(product_log/audit)
|
||
│ ├── reviewIllegalBook.js # 异常书目查询/删除(product_log/list + delete)
|
||
│ ├── inventory.js # 库存记录(汇总/明细/变动日志)
|
||
│ ├── location.js # 库位管理(CRUD、批量生成、Excel 导入)
|
||
│ ├── login.js # 登录(管理员/代理)
|
||
│ ├── logistics.js # 物流模板 CRUD
|
||
│ ├── outbound.js # 出库管理(CRUD、审核、导出、改库位)
|
||
│ ├── print.js # 打印服务(重导出 Lodop 方法)
|
||
│ ├── product.js # 商品管理(CRUD、图片、OCR、Excel 导入)
|
||
│ ├── purchase-order.js # 采购订单(CRUD、带波次创建、波次释放)
|
||
│ ├── releaseRecord.js # 发布记录(全 Mock 数据)
|
||
│ ├── sales-order.js # 销售订单(CRUD、确认、取消、退货)
|
||
│ ├── shop.js # 店铺管理(内部 API + 外部 API 双路径)
|
||
│ ├── shipping-order.js # 发货单(内部 CRUD + 外部快递接口)
|
||
│ ├── split.js # 分账配置(旧版,不完整,部分 stub)
|
||
│ ├── splitAccount.js # 分账配置(完整版,JSON 请求体)
|
||
│ ├── splitDeductionLog.js # 分账扣款日志(查询/导出)
|
||
│ ├── stock-check.js # 盘库管理(CRUD、盘点、调整、退货)
|
||
│ ├── supplier.js # 供应商 CRUD
|
||
│ ├── warehouse.js # 仓库 CRUD
|
||
│ └── wave-task.js # 波次任务(任务列表、波次管理、波次释放)
|
||
│
|
||
├── components/ # 公共组件(24 个文件)
|
||
│ ├── AdminLayout.vue # 主布局(侧边栏 + 顶部栏 + 内容区)
|
||
│ ├── goodsPop/index.vue # ISBN 悬停浮窗(书品信息预览)
|
||
│ ├── locationSelect/index.vue # 库位选择器组件
|
||
│ ├── dialog/submIllegalBook/ # 异常书目提交弹窗
|
||
│ ├── inventory/byGoods/ # 库存视图-按商品分组
|
||
│ ├── inventory/byLocation/ # 库存视图-按库位分组
|
||
│ ├── product/byGoods/ # 商品视图-按商品分组
|
||
│ ├── product/byLocation/ # 商品视图-按库位分组
|
||
│ ├── wareHouse/warehouseList.vue # 仓库列表组件
|
||
│ ├── wareHouse/locationManager.vue # 库位管理组件(有独立路由)
|
||
│ ├── wareHouse/regionData.js # 行政区划常量数据
|
||
│ └── wave/ # 波次相关子组件
|
||
│ ├── camera.vue # 相机扫码
|
||
│ ├── car.vue # 小车选择(含打印调试按钮)
|
||
│ ├── bookInfo.vue # 书籍信息展示
|
||
│ ├── goodsInfo.vue # 商品信息展示
|
||
│ ├── goosList.vue # 商品列表(注意文件名拼写 "goos")
|
||
│ ├── imageCut.vue # 图片裁剪工具
|
||
│ ├── ocrDialog.vue # OCR 识别对话框
|
||
│ ├── ocrResultDialog.vue # OCR 结果展示对话框
|
||
│ └── suitBookDialog.vue # 套装书对话框(含首次打印调试)
|
||
│
|
||
├── views/ # 页面级组件(33 个页面目录)
|
||
│ ├── login/Login.vue # 登录页
|
||
│ ├── admin/ # 管理员页面
|
||
│ │ ├── Dashboard.vue # 仪表盘
|
||
│ │ ├── EmployeeList.vue # 代理管理
|
||
│ │ ├── EmployeeAdd.vue # 添加代理
|
||
│ │ └── employeeType.vue # 员工类型管理
|
||
│ ├── wave/Wave.vue # 波次管理主页面
|
||
│ ├── waveTask/WaveTask.vue # 波次任务列表
|
||
│ ├── warehouse/ # 仓库管理
|
||
│ │ ├── wareHouse.vue # 仓库列表
|
||
│ │ └── template.vue # 运费模板管理
|
||
│ ├── supplier/Supplier.vue # 供应商列表
|
||
│ ├── product/Product.vue # 商品列表
|
||
│ ├── purchase-order/ # 采购订单
|
||
│ │ └── PurchaseOrder.vue
|
||
│ ├── sales-order/ # 销售订单
|
||
│ │ ├── SalesOrder.vue # 销售订单
|
||
│ │ └── salesInfoList.vue # 销售单详情列表
|
||
│ ├── shipping-order/ # 发货单
|
||
│ │ ├── ShippingOrder.vue # 发货单管理
|
||
│ │ ├── orderList.vue # 发货单详情列表
|
||
│ │ └── unshippedOrderList.vue # 未发货订单列表
|
||
│ ├── outbound/Outbound.vue # 出库管理
|
||
│ ├── inventory/Inventory.vue # 库存记录
|
||
│ ├── stock-check/ # 盘库管理
|
||
│ │ └── StockCheck.vue
|
||
│ ├── shop/Shop.vue # 店铺管理
|
||
│ ├── car/Car.vue # 小车管理
|
||
│ ├── location/Location.vue # 库位列表
|
||
│ ├── config/config.vue # 核价器配置
|
||
│ ├── logistics/index.vue # 物流模板
|
||
│ ├── releaseRecord/ # 发布记录
|
||
│ ├── reviewIllegalBook/ # 异常书目审核
|
||
│ ├── printer-manager/ # 打印机管理
|
||
│ ├── shop-settings/ # 店铺设置
|
||
│ ├── sorting-settings/ # 分拣设置
|
||
│ ├── scanner/Scanner.vue # 扫码页
|
||
│ ├── pdaManage/ # PDA 管理
|
||
│ ├── courier/config.vue # 快递配置
|
||
│ └── split/ # 分账管理
|
||
│ ├── config/splitConfig.vue # 分账配置
|
||
│ └── log/splitLog.vue # 分账扣款日志
|
||
│
|
||
├── router/index.js # 路由配置(History 模式 + 完整路由守卫)
|
||
├── store/ # 状态管理
|
||
│ ├── index.js # 旧版 store(reactive 方式,逐步废弃)
|
||
│ └── user.js # Pinia 用户 store
|
||
├── utils/ # 工具函数
|
||
│ ├── request.js # Axios 封装(拦截器、签名、Mock 系统)
|
||
│ ├── auth.js # Token/UserInfo 的 localStorage 读写
|
||
│ ├── sign.js # 签名工具(MD5/SHA256,参数排序展平)
|
||
│ ├── mock.js # Mock 数据(商品、卡密、代理、订单)
|
||
│ ├── daYin/print.ts # Lodop/Clodop 打印服务封装(TypeScript)
|
||
│ ├── daYinPdd/index.ts # 拼多多打印服务
|
||
│ ├── pddUpload.ts # 拼多多图片上传
|
||
│ ├── clipboard.js # 剪贴板工具
|
||
│ └── ServiceManager.js # 服务管理器
|
||
├── App.vue # 根组件(router-view + SEO footer)
|
||
└── main.js # 入口文件(注册 Element Plus / Pinia / Router / Icons)
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 构建与部署
|
||
|
||
### 4.1 开发服务器
|
||
|
||
```bash
|
||
npm run dev
|
||
# → http://localhost:5174 (host: 0.0.0.0)
|
||
```
|
||
|
||
### 4.2 生产构建
|
||
|
||
```bash
|
||
npm run build
|
||
# → 输出到 dist/
|
||
```
|
||
|
||
### 4.3 Vite 配置要点(`vite.config.js`)
|
||
|
||
| 配置项 | 值 | 说明 |
|
||
|--------|-----|------|
|
||
| **插件** | `@vitejs/plugin-vue` | Vue SFC 编译 |
|
||
| **代理** | `/api` → `https://psi.api.buzhiyushu.cn` | 主业务 API(changeOrigin) |
|
||
| **代理** | `/api/print` → `https://print.buzhiyushu.cn` | 打印服务(changeOrigin) |
|
||
| **别名** | `@` → `./src` | 模块路径别名 |
|
||
| **端口** | `5174` | 开发服务器端口 |
|
||
| **host** | `0.0.0.0` | 监听所有网络接口 |
|
||
| **historyApiFallback** | `true` | History 模式 fallback |
|
||
| **自定义中间件** | `/kongfz-login` | 孔夫子登录代理(避免跨域) |
|
||
| **SCSS** | `api: 'modern-compiler'` | SCSS 编译模式 |
|
||
| **Define** | `__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false'` | 关闭水合警告 |
|
||
|
||
### 4.4 孔夫子登录代理中间件
|
||
|
||
Vite 开发服务器注册了 `/kongfz-login` 自定义中间件:
|
||
- **方法**:仅 POST
|
||
- **流程**:接收 `loginName` + `loginPass` → POST 到 `login.kongfz.com/Pc/Login/account` → 跟随重定向 → 提取 `PHPSESSID` → GET `user.kongfz.com/User/Index/getUserInfo/` 获取昵称
|
||
- **返回**:`{ code: 200, data: { token, username, nickname } }`
|
||
- **错误处理**:HTTP 405(非 POST)→ `{ code: 405 }`;400(空参数)→ `{ code: 400 }`;500(登录失败)→ `{ code: 500, message }`
|
||
- **超时**:15 秒
|
||
- **重定向限制**:最多跟随 5 次重定向
|
||
- **User-Agent**:`Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36`
|
||
|
||
### 4.5 生产环境 API 地址
|
||
|
||
- **基础 URL**:`https://psi.api.buzhiyushu.cn/api`
|
||
- 通过环境变量 `VITE_API_BASE` 可覆盖
|
||
|
||
---
|
||
|
||
## 5. 路由与权限
|
||
|
||
### 5.1 路由模式
|
||
|
||
`createWebHistory()` — History 模式,URL 格式为 `http://host:port/path`
|
||
|
||
> ⚠️ 注意:本项目的 router 使用 History 模式,而非 Hash 模式。不支持 IE 等旧浏览器。
|
||
|
||
### 5.2 路由守卫逻辑
|
||
|
||
`router.beforeEach` 守卫依次执行:
|
||
|
||
1. **URL 参数登录(嵌入模式)**:检测 `window.location.search` 中的 `token` 参数
|
||
- 自动写入 `localStorage.admin_token`
|
||
- 设置 `localStorage.embed_mode = 'true'`(隐藏导航栏)
|
||
- 解析 JWT Payload(base64)提取 `id`、`username`、`role`、`about_id`
|
||
- 用于跨系统嵌入(如从其他系统以 iframe 嵌入本系统)
|
||
2. **标题设置**:`document.title = "{meta.title} - 进销存系统"`
|
||
3. **登录页处理**:已登录用户自动跳转 `/dashboard`
|
||
4. **仪表盘鉴权**:无 `adminUserInfo` 跳转 `/login`
|
||
5. **黑名单模式鉴权**:
|
||
- 所有非公开页面(未标记 `meta.isPublic`)均需登录
|
||
- `requiresAdmin: true` 且 `role !== 255` 跳转 `/dashboard`
|
||
- 未登录跳转 `/login`(携带 `redirect` 参数可回跳)
|
||
|
||
### 5.3 完整路由表
|
||
|
||
| 路径 | Name | 组件 | 标题 | 权限 | 隐藏 |
|
||
|------|------|------|------|------|------|
|
||
| `/login` | `Login` | `login.vue` | 登录 | 公开 | — |
|
||
| `/` | — | `AdminLayout.vue`(布局) | — | — | 重定向到 `/dashboard` |
|
||
| `/dashboard` | `Dashboard` | `dashboard.vue` | 仪表盘 | 需认证 | — |
|
||
| `/admin/employees` | `EmployeeList` | `employeeList.vue` | 代理管理 | 管理员 | — |
|
||
| `/admin/employees/add` | `EmployeeAdd` | `employeeAdd.vue` | 添加代理 | 管理员 | — |
|
||
| `/admin/employee-type` | `EmployeeType` | `employeeType.vue` | 员工类型管理 | 管理员 | — |
|
||
| `/wave` | `wave` | `wave.vue` | 波次管理 | 需认证 | — |
|
||
| `/wave-task` | `wave-task` | `waveTask.vue` | 波次任务 | 需认证 | — |
|
||
| `/warehouse` | `warehouse` | `wareHouse.vue` | 仓库列表 | 需认证 | — |
|
||
| `/warehouse/template` | `WarehouseTemplate` | `template.vue` | 运费模板管理 | 需认证 | — |
|
||
| `/location-manager` | `location-manager` | `locationManager.vue` | 库位管理 | 需认证 | ✅ 隐藏 |
|
||
| `/location` | `location` | `location.vue` | 库位列表 | 需认证 | — |
|
||
| `/supplier` | `supplier` | `supplier.vue` | 供应商管理 | 需认证 | — |
|
||
| `/product` | `product` | `product.vue` | 商品管理 | 需认证 | — |
|
||
| `/purchase-order` | `purchase-order` | `purchaseOrder.vue` | 采购订单 | 需认证 | — |
|
||
| `/sales-order` | `sales-order` | `salesOrder.vue` | 销售订单 | 需认证 | — |
|
||
| `/sales-order-info-list` | `SalesOrderInfoList` | `salesInfoList.vue` | 销售单详情列表 | 需认证 | — |
|
||
| `/outbound` | `outbound` | `outbound.vue` | 出库管理 | 需认证 | — |
|
||
| `/shipping-order` | `shipping-order` | `shippingOrder.vue` | 发货单 | 需认证 | — |
|
||
| `/shipping-order-list` | `ShippingOrderList` | `orderList.vue` | 发货单详情列表 | 需认证 | — |
|
||
| `/inventory` | `inventory` | `inventory.vue` | 库存记录 | 需认证 | — |
|
||
| `/stock-check` | `stock-check` | `stockCheck.vue` | 盘库管理 | 需认证 | — |
|
||
| `/release-record` | `release-record` | `releaseRecord.vue` | 发布记录 | 需认证 | — |
|
||
| `/shop` | `shop` | `shop.vue` | 店铺管理 | 需认证 | — |
|
||
| `/shop-settings` | `shop-settings` | `shopSettings.vue` | 店铺设置 | 需认证 | — |
|
||
| `/sorting-settings` | `sorting-settings` | `sortingSettings.vue` | 分拣设置 | 需认证 | — |
|
||
| `/car` | `car` | `car.vue` | 小车管理 | 需认证 | — |
|
||
| `/printer-manager` | `printer-manager` | `printerManager.vue` | 打印机管理 | 需认证 | — |
|
||
| `/review-illegal-book` | `reviewIllegalBook` | `reviewIllegalBook.vue` | 异常书目审核 | 管理员 | — |
|
||
| `/testUrl` | `testUrl` | `config.vue` | 核价器配置 | 管理员 | — |
|
||
| `/split-config` | `split-config` | `splitConfig.vue` | 分账配置 | 需认证 | — |
|
||
| `/split-log` | `split-log` | `splitLog.vue` | 分账扣款日志 | 需认证 | — |
|
||
| `/courier-config` | `courier-config` | `config.vue`(courier) | 快递配置 | 需认证 | — |
|
||
| `/pdaManage` | `pdaManage` | `pdaManage.vue` | PDA 管理 | 需认证 | ✅ 隐藏 |
|
||
|
||
> **隐藏路由**:`hidden: true` 的路由不会在侧边栏菜单中显示,但可通过 URL 直接访问。
|
||
|
||
### 5.4 角色权限
|
||
|
||
| role 值 | 身份 | 说明 |
|
||
|---------|------|------|
|
||
| `255` | 管理员 | 全部功能可用,包括代理管理、员工类型、核价器配置、异常审核 |
|
||
| `128` | 代理 | 仪表盘、波次、仓库、商品等基础功能 |
|
||
|
||
---
|
||
|
||
## 6. API 架构
|
||
|
||
### 6.1 网络拓扑
|
||
|
||
```
|
||
浏览器 ──→ Vite Dev Server (:5174)
|
||
├── /api/* ──→ Proxy ──→ https://psi.api.buzhiyushu.cn (主业务 API)
|
||
├── /api/print/* ──→ Proxy ──→ https://print.buzhiyushu.cn (打印服务)
|
||
├── /kongfz-login ──→ Node.js 中间件 ──→ login.kongfz.com (孔夫子登录)
|
||
└── axios 直连 ──→ 核价器 http://{ip}:{port} (用户配置)
|
||
──→ https://api.buzhiyushu.cn (店铺列表/快递回填)
|
||
──→ https://print.buzhiyushu.cn (快递面单打印)
|
||
──→ https://new.taskpool.buzhiyushu.cn:3500 (店铺详情)
|
||
```
|
||
|
||
### 6.2 请求封装(`src/utils/request.js`)
|
||
|
||
**创建 Axios 实例:**
|
||
- 开发环境 baseURL:`/api`(通过 Vite 代理)
|
||
- 生产环境 baseURL:`https://psi.api.buzhiyushu.cn/api`(可通过 `VITE_API_BASE` 覆盖)
|
||
- 超时:10 秒
|
||
- 使用 `json-bigint` 替换默认 `JSON.parse`(`transformResponse`),防止后端 19 位大整数精度丢失
|
||
|
||
**请求拦截器流程:**
|
||
|
||
```
|
||
请求发起
|
||
│
|
||
├── 注入 Bearer Token(从 localStorage.admin_token 读取)
|
||
│
|
||
├── 签名处理
|
||
│ ├── 检查 X-Need-Sign 头('false' 则跳过签名)
|
||
│ ├── GET 请求 → 对 params 签名
|
||
│ ├── POST/PUT/DELETE 请求 → 对 body 签名(先 FormData→Object 再签名)
|
||
│ └── 签名后自动注入 app_key、client_id、timestamp、sign_method
|
||
│
|
||
└── POST/PUT/DELETE 请求 → 自动对象转 FormData(objectToFormData)
|
||
└── 删除 Content-Type 头(让浏览器自动设置为 multipart/form-data)
|
||
```
|
||
|
||
**响应拦截器流程:**
|
||
|
||
```
|
||
响应返回
|
||
│
|
||
├── Mock 模式(USE_MOCK=true)→ 匹配 mockApiMap 返回模拟数据
|
||
│
|
||
├── HTTP 204 → "请求无响应数据" 错误提示
|
||
│
|
||
├── code=200 → 返回 response.data
|
||
│
|
||
├── code≠200 → 统一 ElMessage 错误提示(code 204 特殊处理)
|
||
│
|
||
├── HTTP 401 → 清除对应 token(区分 admin/user 端)→ 跳转登录页
|
||
├── HTTP 400 → 显示后端返回的错误消息
|
||
├── HTTP 403 → "没有权限访问"
|
||
├── HTTP 404 → "请求的资源不存在"
|
||
├── HTTP 500 → "服务器错误"
|
||
│
|
||
└── 网络错误 → "网络错误,请检查网络连接"
|
||
```
|
||
|
||
**objectToFormData 递归转换:**
|
||
- 支持嵌套对象 → `parentKey[key]`
|
||
- 支持数组 → `parentKey[0]`, `parentKey[1]`
|
||
- 支持 File 类型直接附加
|
||
- 跳过 `null`/`undefined` 值
|
||
|
||
**Mock 系统:**
|
||
- `USE_MOCK = false`(默认关闭)
|
||
- 支持的路由:`/products`、`/admin/cards/*`、`/admin/employee/*`、`/orders`、`/access/*`、`/cards/buy/*`
|
||
- 启用后 GET 请求自动匹配 `mockApiMap`,支持路径参数解析
|
||
|
||
### 6.3 签名机制(`src/utils/sign.js`)
|
||
|
||
`SignUtil` 类(单例导出),配置来自环境变量:
|
||
|
||
```javascript
|
||
{
|
||
appKey: 'psi',
|
||
clientId: 'psi',
|
||
appSecret: 'psi_api_sign_secret'
|
||
}
|
||
```
|
||
|
||
**核心方法:**
|
||
|
||
| 方法 | 说明 |
|
||
|------|------|
|
||
| `generateSign(params)` | 完整签名流程:过滤空值 → 注入系统参数 → 展平 → 排序 → 计算 MD5 → 返回含 sign 的 params 对象 |
|
||
| `generateSignedUrl(baseUrl, params)` | 生成带签名参数的完整 URL |
|
||
| `calculateSign(params)` | 核心哈希:拼接 `appSecret + key=value&... + appSecret`,MD5 签名后转为大写 |
|
||
| `buildParamEntries(params, prefix)` | 递归展平嵌套对象/数组为 `key=value` 条目(使用 `[key]` 下标表示法) |
|
||
| `sortKeys(a, b)` | 智能键排序:纯数字段数值比较,混合段分段字母+数字排序 |
|
||
|
||
**系统自动注入参数:**
|
||
|
||
| 参数 | 值 |
|
||
|------|-----|
|
||
| `app_key` | `VITE_APP_API_KEY(psi)` |
|
||
| `client_id` | `VITE_APP_CLIENT_ID(psi)` |
|
||
| `timestamp` | 当前时间戳(毫秒) |
|
||
| `sign_method` | `md5` |
|
||
|
||
**跳过签名:** 在请求头中设置 `X-Need-Sign: false`(如 OCR 图片上传、部分外部服务调用)
|
||
|
||
### 6.4 列表接口标准化
|
||
|
||
约 15 个 API 模块实现了 `normalizeListResponse()` 工具函数,将后端可能返回的各种列表格式统一为 `{ list: Array, total: number }`:
|
||
|
||
```javascript
|
||
const normalizeListResponse = (payload) => {
|
||
const data = payload?.data
|
||
if (!data) return { list: [], total: 0 }
|
||
if (Array.isArray(data)) return { list: data, total: data.length }
|
||
return {
|
||
list: Array.isArray(data.list) ? data.list : [],
|
||
total: typeof data.total === 'number' ? data.total : (data.list?.length || 0)
|
||
}
|
||
}
|
||
```
|
||
|
||
> ⚠️ 注意:此函数在每个 API 文件中独立定义,存在代码重复,建议未来抽离为公共工具。
|
||
|
||
### 6.5 大整数精度
|
||
|
||
使用 `json-bigint` 库替换 `JSON.parse`,在后端返回 JSON 中的 19 位大整数(如订单号、店铺 ID)时保持精度。注意:
|
||
- `json-bigint` 返回的是 `BigNumber` 对象,使用 `.toString()` 获取字符串值
|
||
- 部分比较操作可能需要特殊处理
|
||
|
||
---
|
||
|
||
## 7. API 接口详表
|
||
|
||
### 7.1 登录与认证
|
||
|
||
#### `src/api/login.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `login(type, formData)` | POST | `/login/:role` | `type` = `'admin'`(→255)/ `'employee'`(→128);`formData` = `{ username, password }` | 管理员/代理登录,自动注入 `type: 1` |
|
||
|
||
#### `src/utils/auth.js`
|
||
|
||
| 函数 | 说明 |
|
||
|------|------|
|
||
| `logout()` | 清除 `admin_token` 和 `admin_userInfo` |
|
||
| `setAdminToken(token)` / `getAdminToken()` / `removeAdminToken()` | 管理端 Token 存取 |
|
||
| `setAdminUserInfo(userInfo)` / `getAdminUserInfo()` / `removeAdminUserInfo()` | 管理端用户信息存取 |
|
||
|
||
#### `src/utils/request.js`(额外导出)
|
||
|
||
| 函数 | 说明 |
|
||
|------|------|
|
||
| `fetchCurrentUser()` | GET `/user/current`,获取当前用户信息并写入 localStorage |
|
||
|
||
### 7.2 仪表盘
|
||
|
||
#### `src/api/dashboard.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 返回 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| `fetchTodayStats()` | GET | `/dashboard/statist` | 无 | `{ today_inbound, today_outbound, today_sales }` | 今日入库/出库/销售统计 |
|
||
| `fetchEmployeeStats()` | GET | `/dashboard/statist` | 无 | `[{ employee_id, employee_name, inbound_count, outbound_count }]` | 各员工今日工作量统计 |
|
||
|
||
### 7.3 书籍与条码
|
||
|
||
#### `src/api/book.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `getBookInfo(isbn)` | GET | `/getBookInfo` | `isbn`(ISBN 号) | 根据 ISBN 查询书籍信息 |
|
||
| `syncBook(params)` | POST | `/syncBook` | `book_name, author, publisher, publication_time, binding_layout, fix_price, isbn, page_count, word_count, book_format, fid, f_isbn, f_book_name, live_image[0], type` | 同步/保存书籍信息(JSON 体) |
|
||
|
||
#### `src/api/barcode.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 返回 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| `generateBarcode(content)` | POST | `/barcode/generate` | `content`(条码内容) | `{ data: { image_base64 } }` | 生成条码图片 Base64(FormData) |
|
||
|
||
### 7.4 商品管理
|
||
|
||
#### `src/api/product.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchProductList({ keyword, status, shop_id, page, pageSize })` | GET | `/product/list` | 关键词、状态、店铺筛选、分页 | 商品分页列表 |
|
||
| `fetchProductListByShop({ shop_id, page, pageSize })` | GET | `/product/list` | 委托 `fetchProductList` | 按店铺筛选商品 |
|
||
| `fetchProductDetail(id)` | GET | `/product/detail` | `id` | 商品详情 |
|
||
| `createProduct(product)` | POST | `/product/save` | 商品对象 | 创建商品 |
|
||
| `saveProduct(product)` | POST | `/product/save` | 含 `name, barcode, price, live_image` | 保存商品(兼容旧接口) |
|
||
| `updateProduct(product)` | POST | `/product/save` | 含 `id` | 更新商品(同创建端点) |
|
||
| `deleteProduct(product)` | POST | `/product/delete` | 含 `id` | 删除商品 |
|
||
| `updateProductLiveImage(id, pictureName, extra)` | POST | `/product/save` | 图片名 + 额外字段 | 更新实拍图(Shxy URL) |
|
||
| `updateProductLiveImageAsPddUrl(id, picUrl, extra)` | POST | `/product/save` | 完整 URL | 用 PDD URL 更新实拍图 |
|
||
| `updateProductLiveImageForTest(id, pictureName, extra)` | POST | `/product/save` | 测试用 | 硬编码测试 URL 更新实拍图 |
|
||
| `getSuitBook(isbn)` | GET | `/getSuitBook` | `isbn` | 查询套装书 |
|
||
| `getProCode({ book_name, author, publisher })` | GET | `/getProCode` | 书名/作者/出版社 | 获取产品编码(OCR 模式用) |
|
||
| `ocrImage(imageBlob)` | POST | `/ocr` | `imageBlob`(图片 Blob) | OCR 识别(跳过签名) |
|
||
| `retryProductPublish(productId, shopId, shopType)` | POST | `/product/retry-out-task` | 商品/店铺/类型 | 重试商品发布 |
|
||
| `fetchLatestProducts(limit, start, end)` | GET | `/product/list` | 数量限制、时间范围 | 最新商品(仪表盘用) |
|
||
| `fetchShopProducts(shopId, page, pageSize)` | GET | `/product/shop-detail` | 店铺 ID 分页 | 店铺商品列表含发布统计 |
|
||
| `getBookDetails(id)` | GET | `/product/detail` | `id` | 书籍详情(`fetchProductDetail` 别名) |
|
||
| `importProductsByExcel({ userId, warehouse_id, file })` | POST | `/goods/import-from-excel` | 用户/仓库/Excel 文件 | 从 Excel 导入商品 |
|
||
|
||
### 7.5 店铺管理
|
||
|
||
#### `src/api/shop.js`
|
||
|
||
内部 + 外部双路径。外部 API 使用独立 axios 实例 + JSONbig。
|
||
|
||
| 函数 | 方法 | 端点 | 说明 |
|
||
|------|------|------|------|
|
||
| `fetchShopList({ keyword, page, pageSize })` | GET | `https://api.buzhiyushu.cn/zhishu/shop/list`(外部) | 从外部 API 获取店铺列表(小车用) |
|
||
| `getShopList({ keyword, shop_type, page, pageSize })` | GET | `/shop/list`(内部代理) | 从本地后端获取店铺列表 |
|
||
| `fetchShopDetail(id)` | GET | `https://new.taskpool.buzhiyushu.cn:3500/api/shop/get/:id`(外部) | 从外部 API 获取店铺详情 |
|
||
| `createShop(shop)` | POST | `/shop/create` | 创建店铺 |
|
||
| `updateShop(shop)` | PUT | `/shop/update` | 更新店铺 |
|
||
| `deleteShop(shop)` | POST | `/shop/delete` | 删除店铺 |
|
||
| `updateShopAuthorize({ id, shop_authorize })` | POST | `/shop/authorize` | 更新授权状态(0=未授权 1=已授权 2=已过期) |
|
||
| `updateShopStatus({ id, status })` | POST | `/shop/status` | 更新状态(0=正常 1=禁用) |
|
||
| `getAllShopList()` | GET | `/shop/list` | 获取所有店铺(不分页) |
|
||
|
||
> 外部 API 使用约 `about_id` 来自 `adminUserInfo`。如果 `about_id == 0` 则替换为 1。
|
||
|
||
### 7.6 供应商管理
|
||
|
||
#### `src/api/supplier.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchSupplierList({ keyword, status, page, pageSize })` | GET | `/supplier/list` | 关键词(编码/名称)、状态、分页 | 供应商分页列表 |
|
||
| `fetchSupplierDetail(id)` | GET | `/supplier/detail/:id` | ID | 供应商详情 |
|
||
| `createSupplier(supplier)` | POST | `/supplier/create` | 供应商对象 | 创建供应商 |
|
||
| `updateSupplier(supplier)` | PUT | `/supplier/update` | 含 `id` | 更新供应商 |
|
||
| `deleteSupplier(supplier)` | POST | `/supplier/delete` | 含 `id` | 删除供应商 |
|
||
|
||
### 7.7 仓库管理
|
||
|
||
#### `src/api/warehouse.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchWarehouseList({ keyword, type, status, page, pageSize })` | GET | `/warehouse/list` | 编码/名称、类型、状态、分页 | 仓库分页列表 |
|
||
| `fetchWarehousesByIds({ ids, page, pageSize })` | GET | `/warehouse/list` | `ids[]` 数组 | 按 ID 批量查询 |
|
||
| `fetchWarehouseDetail(id)` | GET | `/warehouse/detail/:id` | ID | 仓库详情 |
|
||
| `createWarehouse(warehouse)` | POST | `/warehouse/create` | 仓库对象 | 创建仓库 |
|
||
| `updateWarehouse(warehouse)` | PUT | `/warehouse/update` | 含 `id` | 更新仓库 |
|
||
| `deleteWarehouse(warehouse)` | POST | `/warehouse/delete` | 含 `id` | 删除仓库 |
|
||
|
||
### 7.8 库位管理
|
||
|
||
#### `src/api/location.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchLocationList({ keyword, warehouseId, type, status, page, pageSize })` | GET | `/location/list` | 编码(code)、仓库、类型、状态、分页 | 库位分页列表 |
|
||
| `fetchLocationDetail(id)` | GET | `/location/detail/:id` | ID | 库位详情 |
|
||
| `createLocation(location)` | POST | `/location/create` | 库位对象 | 创建库位 |
|
||
| `updateLocation(location)` | PUT | `/location/update` | 含 `id` | 更新库位 |
|
||
| `deleteLocation(location)` | POST | `/location/delete` | `ids[]`(FormData) | 批量删除库位 |
|
||
| `batchUpdateLocations(payload)` | PUT | `/location/update` | `ids[] + { code, type, capacity, status }`(FormData) | 批量更新库位属性 |
|
||
| `batchGenerateLocations(payload)` | POST | `/location/batch-generate` | 仓库/类型/容量/状态/生成规则 | 按规则批量生成库位 |
|
||
| `importLocationsFromExcel({ user_id, warehouse_id, file })` | POST | `/location/import-from-excel` | 用户/仓库/Excel 文件(FormData) | 从 Excel 导入库位 |
|
||
| `fetchAllLocations({ page, pageSize, keyword })` | GET | `/location/all-list` | 分页、关键词 | 跨仓库全库位列表 |
|
||
|
||
### 7.9 小车管理
|
||
|
||
#### `src/api/car.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchCarList({ keyword, page, pageSize })` | GET | `/car/list` | 编码/名称、分页 | 小车分页列表 |
|
||
| `fetchCarDetail(id)` | GET | `/car/detail/:id` | ID | 小车详情 |
|
||
| `createCar(carData)` | POST | `/car/create` | FormData | 创建小车 |
|
||
| `updateCar(carData)` | PUT | `/car/update` | FormData(含 `id`) | 更新小车 |
|
||
| `deleteCar(id)` | DELETE | `/car/delete` | FormData(含 `id`) | 删除小车 |
|
||
| `createCarShop(carShop)` | POST | `/car/shop/create` | 关联数据 | 创建小车-店铺关联 |
|
||
| `deleteCarShop(carShop)` | POST | `/car/shop/delete` | 含 `id` | 删除小车-店铺关联 |
|
||
|
||
### 7.10 波次管理
|
||
|
||
#### `src/api/waveTask.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchWaveTaskList(params)` | GET | `/wave/task/list` | `task_no, wave_no, page, page_size` | 波次任务列表 |
|
||
| `fetchWaveTaskDetail(id)` | GET | `/wave/task/detail` | `id` | 波次任务详情 |
|
||
| `deleteWaveTask(data)` | POST | `/delete` | 含 `id` | 删除波次任务 |
|
||
| `fetchWaveById(id)` | GET | `/wave/task/detail` | `id` | 按 ID 查波次信息 |
|
||
| `fetchWaveTaskByNo(waveNo)` | GET | (两步)先 `/wave/task/list` 再 `/wave/task/detail` | 波次号 | 按波次号查任务 |
|
||
| `fetchWaveList(params)` | GET | `/wave/list` | `keyword, status, warehouse_id, page, page_size` | 波次列表(选择器用) |
|
||
| `createWaveOutbound(outboundOrderId)` | POST | `/wave/outbound/create` | FormData | 创建波次出库 |
|
||
| `createWaveOutboundRelease(relatedOrderId, waveId)` | POST | `/wave/outbound/release` | FormData | 释放波次出库 |
|
||
| `getWaveStatusById(id)` | GET | `/wave/getWaveStatusById` | `id` | 查询波次状态 |
|
||
|
||
### 7.11 采购订单
|
||
|
||
#### `src/api/purchaseOrder.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchPurchaseOrderList({ keyword, status, page, pageSize, sort_by, sort_order })` | GET | `/purchase-order/list` | 单号(po_no)、状态、分页、排序 | 采购单列表 |
|
||
| `fetchPurchaseOrderDetail(id)` | GET | `/purchase-order/detail` | `id` | 采购单详情 |
|
||
| `createPurchaseOrder(data)` | POST | `/purchase-order/save` | 采购单数据 | 创建采购单 |
|
||
| `updatePurchaseOrder(data)` | POST | `/purchase-order/save` | 含 `id` | 更新采购单 |
|
||
| `deletePurchaseOrder(data)` | POST | `/purchase-order/delete` | 含 `id` | 删除采购单 |
|
||
| `createPurchaseOrderWithWave(data)` | POST | `/purchase-order/create-with-wave` | `warehouse_id, supplier_id, expected_arrival_date, remark, items[], direction` | 创建采购单并生成波次(步骤 1/2) |
|
||
| `releaseWave(data)` | POST | `/wave/release` | `wave_id, related_order_id, items[], car_id, car_code` | 释放波次(步骤 2/2) |
|
||
|
||
### 7.12 销售订单
|
||
|
||
#### `src/api/salesOrder.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchSalesOrderList({ keyword, status, customer_id, warehouse_id, page, pageSize, sort_by, sort_order })` | GET | `/sales-order/list` | 单号(so_no)、状态、平台、仓库、分页、排序 | 销售单列表 |
|
||
| `fetchSalesOrderDetail(id)` | GET | `/sales-order/detail` | `id` | 销售单详情(含明细) |
|
||
| `createSalesOrder(order)` | POST | `/sales-order/create` | 含 `so_no, customer_id, warehouse_id, order_date, required_delivery_date, items[]` | 创建销售单 |
|
||
| `updateSalesOrder(order)` | PUT | `/sales-order/update` | 含 `id` | 更新销售单 |
|
||
| `deleteSalesOrder(id)` | POST | `/sales-order/delete` | `id` | 删除销售单 |
|
||
| `confirmSalesOrder(id)` | POST | `/sales-order/confirm` | `id` | 确认销售单 |
|
||
| `cancelSalesOrder(id, remark)` | POST | `/sales-order/cancel` | `id, remark` | 取消销售单 |
|
||
| `returnSalesOrderItem(data)` | POST | `/stock_check/return` | `sales_order_id, sales_order_item_id, remark` | 销售单退货 |
|
||
| `fetchSalesOrderDetails({ page, pageSize })` | GET | `/sales-order/detaillist` | 分页 | 销售单明细汇总列表 |
|
||
|
||
### 7.13 出库管理
|
||
|
||
#### `src/api/outbound.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchOutboundList({ out_no, status, warehouse_id, customer_id, sales_order_id, start_date, end_date, page, page_size })` | GET | `/outbound-order/list` | 多种筛选条件 | 出库单分页列表 |
|
||
| `fetchOutboundDetail(id)` | GET | `/outbound-order/detail` | `id` | 出库单详情(含明细) |
|
||
| `createOutbound(outbound)` | POST | `/outbound-order/create` | `warehouse_id, customer_id, shipping_date, items[]` | 创建出库单 |
|
||
| `updateOutbound(outbound)` | PUT | `/outbound-order/update` | 含 `id` | 更新出库单 |
|
||
| `deleteOutbound(outbound)` | POST | `/outbound-order/delete` | 含 `id` | 删除出库单 |
|
||
| `approveOutbound(id, status, remark)` | POST | `/outbound-order/approve` | ID + 审核状态 + 备注 | 审核出库单 |
|
||
| `exportOutbound(id)` | GET | `/outbound-order/export/:id` | ID(blob 响应) | 导出出库单 |
|
||
| `changeLocation(out_order_item_id, remark)` | POST | `/outbound-order/change-location` | 明细 ID + 备注(FormData) | 改库位 |
|
||
| `createOutboundFromSalesOrder(salesOrderIds, total, remark)` | POST | `/outbound-order/create` | 销售单 IDs + 总数(FormData) | 从销售单创建出库单 |
|
||
|
||
### 7.14 发货单
|
||
|
||
#### `src/api/shippingOrder.js`
|
||
|
||
内部 + 外部双路径。
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchShippingOrderList(...)` | GET | `/shipping-order/list` | `check_no, status, customer_id, warehouse_id, sales_order_id, wave_task_id, page, pageSize` | 发货单列表 |
|
||
| `fetchShippingOrderDetailList(...)` | GET | `/shipping-order/detaillist` | `status(1=待发货 2=已发货 3=已签收 4=已取消), page, pageSize, customer_id, shipping_no, start_date, end_date` | 发货单明细列表(新接口,支持时间范围) |
|
||
| `fetchShippingOrderDetail(id)` | GET | `/shipping-order/detail` | `id` | 发货单详情 |
|
||
| `createShippingOrder({ total, outbound_order_ids })` | POST | `/shipping-order/create` | 出库单 IDs(FormData) | 从出库单生成发货单 |
|
||
| `updateShippingOrderLogistics(...)` | POST | `/shipping-order/update` | `shipping_order_id, sales_order_item_id, logistics_company, logistics_no`(FormData) | 更新物流信息 |
|
||
| `recycleWaybillNo({ user_id, logistics_no })` | POST | `/logistics/cancel` | 用户 ID + 运单号(FormData) | 回收/取消运单 |
|
||
|
||
**外部快递接口:**
|
||
|
||
| 函数 | 方法 | 端点 | 说明 |
|
||
|------|------|------|------|
|
||
| `fetchFastMailList(shopId)` | GET | `https://api.buzhiyushu.cn/zhishu/fastMail/listApi?shopId=` | 获取快递账号列表 |
|
||
| `createOrderBatch(params)` | POST | `https://print.buzhiyushu.cn/api/print/createOrderBatch` | 创建快递面单(FormData) |
|
||
| `createBmOrderDaYin(params)` | GET | `https://print.buzhiyushu.cn/api/print/createBmOrderDaYin` | 获取打印面单信息 |
|
||
| `submitCompanyOrder(params)` | POST | `https://api.buzhiyushu.cn/zhishu/orderExternalGoods/submitCompanyOrder` | 回填快递单号(JSON) |
|
||
| `fetchExpressInfo(waybillNo)` | GET | `https://print.buzhiyushu.cn/api/print/printViewByWaybillNo` | 获取快递信息 |
|
||
|
||
### 7.15 库存管理
|
||
|
||
#### `src/api/inventory.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchInventoryList(params)` | GET | `/inventory/list` | `page, page_size, product_id, warehouse_id` | 库存汇总(按商品+仓库聚合,含总量/锁定/可用) |
|
||
| `fetchInventoryDetailList(params)` | GET | `/inventory/detail` | `product_id`(必填) | 库存明细(按仓库+库位+批次) |
|
||
| `fetchInventoryLogList(params)` | GET | `/inventory/log/list` | `page, page_size, isbn, book_name, warehouse_id, change_type, related_order_no, start_date, end_date` | 库存变动记录 |
|
||
| `fetchInventoryStats(warehouse_id)` | — | — | — | **桩函数**,返回 null |
|
||
| `fetchGoodsListByLocation({ keyword, page, pageSize })` | GET | `/inventory/grouped-list` | 库位编码/商品名/条码 | 按库位分组的库存 |
|
||
| `inventorySummary()` | GET | `/inventory/summary` | 无 | 库存汇总统计 |
|
||
|
||
### 7.16 盘库管理
|
||
|
||
#### `src/api/stockCheck.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchStockCheckList(...)` | GET | `/inventory/stock-check/list` | `keyword, warehouse_id, status(1=待盘点 2=盘点中 3=已完成 4=已取消), check_type(1=全盘 2=抽盘), page, pageSize, sort_by, sort_order` | 盘库单列表 |
|
||
| `fetchStockCheckDetail(id)` | GET | `/inventory/stock-check/:id` | ID | 盘库单详情(含明细) |
|
||
| `fetchStockCheckItems(stock_check_id, ...)` | GET | `/:id/items` | 盘库单 ID、关键词、状态(1=待盘点 2=已盘点) | 盘库明细列表 |
|
||
| `createStockCheck(data)` | POST | `.../create` | `warehouse_id, check_type, remark, items[]` | 创建盘库单 |
|
||
| `startStockCheck(id)` | POST | `.../:id/start` | ID | 开始盘点 |
|
||
| `submitCheckItem(stock_check_id, data)` | POST | `.../:id/check` | `item_id, actual_quantity, remark` | 提交单项盘点结果 |
|
||
| `batchSubmitCheckItems(stock_check_id, data)` | POST | `.../:id/check/batch` | `items: [{ item_id, actual_quantity, remark }]` | 批量提交盘点结果 |
|
||
| `completeStockCheck(id)` | POST | `.../:id/complete` | ID | 完成盘点 |
|
||
| `cancelStockCheck(id, reason)` | POST | `.../:id/cancel` | ID + 原因 | 取消盘库单 |
|
||
| `deleteStockCheck(id)` | DELETE | `.../:id` | ID | 删除盘库单(仅待盘点状态) |
|
||
| `adjustStockCheck(data)` | POST | `/stock-check/adjust` | `warehouse_id, product_id, location_id, batch_no, quantity, adjust_type(1=加 2=减), remark`(FormData) | 库存调整 |
|
||
| `returnStockCheck(data)` | POST | `/stock-check/return` | 同上(FormData) | 库存退货 |
|
||
|
||
### 7.17 物流/运费模板
|
||
|
||
#### `src/api/logistics.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchLogisticsList(params)` | GET | `/logistics/list` | 查询参数 | 物流模板列表 |
|
||
| `fetchLogisticsDetail(id)` | GET | `/logistics/detail/:id` | ID | 模板详情 |
|
||
| `createLogistics(data)` | POST | `/logistics/create` | 模板数据(FormData) | 创建物流模板 |
|
||
| `updateLogistics(data)` | PUT | `/logistics/update` | 含 `id` | 更新物流模板 |
|
||
| `deleteLogistics(ids)` | POST | `/logistics/delete` | 单个 ID 或 ID 数组(FormData) | 删除模板 |
|
||
|
||
#### `src/api/district.js`
|
||
|
||
| 函数 | 方法 | 端点 | 说明 |
|
||
|------|------|------|------|
|
||
| `fetchProvinces()` | GET | `/district/province/list` | 获取省份列表 |
|
||
| `fetchCitiesByProvinceId(provinceId)` | GET | `/district/city/list/:id` | 根据省份获取城市 |
|
||
| `fetchDistrictsByCityId(cityId)` | GET | `/district/area/list/:id` | 根据城市获取区县 |
|
||
| `fetchFreightInfo(id)` | GET | `/district/freight/info/:id` | 获取运费模板信息(含发货地址) |
|
||
| `createFreightTemplate(data)` | POST | `/district/freight/create` | 创建运费模板 |
|
||
| `updateFreightTemplate(data)` | PUT | `/district/freight/update` | 更新运费模板(FormData) |
|
||
|
||
### 7.18 代理/员工管理
|
||
|
||
#### `src/api/employee.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchEmployeeList(params)` | GET | `/admin/employee/list` | `page, page_size, status, keyword` | 代理列表 |
|
||
| `addEmployee({ name, password, phone, fid, about_id })` | POST | `/admin/employee/add` | 姓名/密码/电话/上级 ID | 添加代理 |
|
||
| `topupEmployee(employeeId, { amount, remark })` | POST | `/admin/employee/topup/:employeeId` | 金额 + 备注 | 代理充值 |
|
||
| `deductEmployee(employeeId, { amount, remark })` | POST | `/admin/employee/deduct/:employeeId` | 金额 + 备注 | 代理扣款 |
|
||
| `toggleEmployeeStatus(action, employeeId)` | POST | `/admin/employee/:action/:employeeId` | `enable` 或 `disable` | 启用/禁用代理 |
|
||
|
||
#### `src/api/employeeType.js`
|
||
|
||
| 函数 | 方法 | 端点 | 说明 |
|
||
|------|------|------|------|
|
||
| `fetchEmployeeTypeList()` | GET | `/admin/user-type/list` | 员工类型列表 |
|
||
| `updataEmployeInfo(formdata)` | PUT | `/api/admin/user-type/update` | ⚠️ 函数名拼写错误(应为 update),更新员工类型信息 |
|
||
|
||
### 7.19 异常书目管理
|
||
|
||
#### 提交异常书目:`src/api/goodsInfo.js`
|
||
|
||
| 函数 | 方法 | 端点 | 说明 |
|
||
|------|------|------|------|
|
||
| `saveAbnormalBook(data)` | POST | `/product_log/save` | 提交异常书目记录(FormData,multipart/form-data),含新旧字段对比(书名、作者、出版社、出版时间、价格、装帧、页码、字数、是否套装、实拍图) |
|
||
|
||
#### 异常书目审核:`src/api/submIllegalBook.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `auditProductLog(id, status, newFields)` | POST | `/product_log/audit` | `status`: 1=通过 2=驳回;`newFields`: 通过时更新的字段 | 审核异常书目(FormData) |
|
||
|
||
#### 异常书目查询/删除:`src/api/reviewIllegalBook.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchProductLogList(params)` | GET | `/product_log/list` | `barcode, status, page, page_size` | 异常书目列表 |
|
||
| `deleteProductLog(id)` | POST | `/product_log/delete` | ID(FormData) | 删除异常书目 |
|
||
|
||
### 7.20 分账管理
|
||
|
||
#### 分账配置(完整版):`src/api/splitAccount.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchSplitConfigList({ rule_name, status, page, pageSize })` | GET | `/split-account-config/list` | 规则名、状态、分页 | 分账配置列表 |
|
||
| `fetchSplitConfigDetail(id)` | GET | `/split-account-config/detail` | `id` | 配置详情 |
|
||
| `createSplitConfig({ rule_name, rule_value, status, description })` | POST | `/split-account-config/create` | 规则名、规则值(JSON)、状态、描述 | 创建分账配置(JSON 体) |
|
||
| `updateSplitConfig(data)` | POST | `/split-account-config/update` | 含 `id` | 更新分账配置 |
|
||
| `deleteSplitConfig(id)` | POST | `/split-account-config/delete` | `id` | 删除分账配置 |
|
||
| `toggleSplitConfigStatus(id, status)` | POST | `/split-account-config/update` | `status`: 0=禁用 1=启用 | 启用/禁用配置 |
|
||
|
||
#### ⚠️ 旧版分账(不完整):`src/api/split.js`
|
||
|
||
仅 `createSplitConfig`(使用 URLSearchParams,非 JSON)+ `updateSplitConfig`(空函数体)。建议使用 `splitAccount.js`。
|
||
|
||
#### 分账扣款日志:`src/api/splitDeductionLog.js`
|
||
|
||
| 函数 | 方法 | 端点 | 参数 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `fetchSplitLogList(...)` | GET | `/split-account-deduction-log/list` | `business_no, config_name, created_by, start_time, end_time, page, pageSize` | 扣款日志列表 |
|
||
| `fetchSplitLogDetail(id)` | GET | `/split-account-deduction-log/detail` | `id` | 日志详情 |
|
||
| `exportSplitLog(params)` | GET | `/split-account-deduction-log/export` | 同列表筛选参数(blob 响应) | 导出日志 |
|
||
|
||
### 7.21 快递配置
|
||
|
||
#### `src/api/courierConfig.js`
|
||
|
||
⚠️ **不完整**——仅 `createConfig({ key, value })`(POST `/config/create`,FormData)有完整实现,`queryConfigList` 仅为 JSDoc 桩。
|
||
|
||
### 7.22 核价器(外部服务)
|
||
|
||
#### `src/api/config.js`
|
||
|
||
所有请求直连用户配置的 `http://{ip}:{port}`,不经过项目代理或签名。
|
||
|
||
| 函数 | 方法 | 端点 | 请求格式 | 说明 |
|
||
|------|------|------|----------|------|
|
||
| `testConnection(ip, port)` | POST | `/api/goods/query` | URLSearchParams | 测试连接(`isbn=0&out_id=0&quality=0&query_index=1&user_id=0`) |
|
||
| `saveNewPrice(ip, port, newPrice, placeholderDownPrice, minShippingFee, minPrice, verifyIndex)` | POST | `/api/config/price/set` | URLSearchParams | 保存价格配置 |
|
||
| `kongfzLogin(username, password, ip, port)` | POST | `/api/kfz/login` | FormData(15s 超时) | 孔夫子登录(通过核价器) |
|
||
| `batchAddTokens(tokens, ip, port)` | POST | `/api/token/add` | JSON Array | 批量提交账号 Token |
|
||
| `fetchTokenList(ip, port)` | POST | `/api/token/list` | JSON `{}` | 获取 Token 列表 |
|
||
| `fetchConfig(ip, port)` | POST | `/api/config/price/get` | JSON `{}` | 获取价格配置 |
|
||
| `queryGoodsPrice({ ip, port, isbn, bookName, author, publisher, isSuit, outId, quality, queryIndex, userId, ... })` | POST | `/api/goods/query` | URLSearchParams | 查询商品价格(套装书传 `book_name+author+publisher` 替代 isbn) |
|
||
| `deleteToken(ip, port, id)` | GET | `/api/token/delete` | 查询参数 | 删除 Token |
|
||
|
||
### 7.23 打印服务(重导出)
|
||
|
||
#### `src/api/print.js`
|
||
|
||
重导出自 `src/utils/daYin/print.ts`:
|
||
|
||
| 函数 | 说明 |
|
||
|------|------|
|
||
| `initLodop()` | 初始化 Lodop/Clodop 打印控件 |
|
||
| `createPrintTask(...)` | 创建打印任务 |
|
||
| `getSimplePrinterList()` | 获取已安装的打印机列表 |
|
||
|
||
### 7.24 发布记录(Mock)
|
||
|
||
#### `src/api/releaseRecord.js`
|
||
|
||
**全部为 Mock 数据**,无后端接口。包含 4 个模拟店铺(博知书社/pdd、孔夫子旧书网、闲鱼优选、新知图书/pdd)。
|
||
|
||
| 函数 | 参数 | 说明 |
|
||
|------|------|------|
|
||
| `fetchReleaseRecordList({ keyword, shop_type, status, page, pageSize })` | 关键词/店铺类型/发布状态/分页 | Mock 发布记录列表(300ms 延迟) |
|
||
| `retryRelease(shopId, productId, shopType)` | 店铺/商品/类型 | Mock 重试发布(500ms 延迟,始终成功) |
|
||
| `fetchShopReleaseDetail(shopId)` | 店铺 ID | Mock 店铺发布详情(300ms 延迟) |
|
||
|
||
---
|
||
|
||
## 8. 状态管理
|
||
|
||
### 8.1 Pinia Store(`src/store/user.js`)— 推荐使用
|
||
|
||
| 状态/方法 | 类型 | 说明 |
|
||
|-----------|------|------|
|
||
| `adminUserInfo` | `ref` | 管理员用户信息(从 localStorage 初始化) |
|
||
| `userInfo` | `computed` | adminUserInfo 的别名 |
|
||
| `isAdmin` | `computed` | `role === 255` |
|
||
| `points` | `computed` | 当前积分 |
|
||
| `setUserInfoAction(info)` | 方法 | 更新用户信息并同步 localStorage |
|
||
| `updatePoints(newPoints)` | 方法 | 更新积分 |
|
||
| `clearAdminUserInfo()` | 方法 | 清除用户信息(登出) |
|
||
| `getAdminInfo()` | 方法 | 返回 `adminUserInfo.value` |
|
||
|
||
### 8.2 旧版 Store(`src/store/index.js`)
|
||
|
||
基于 Vue `reactive()` 的简单 store,未使用 Pinia:
|
||
|
||
| 状态/方法 | 说明 |
|
||
|-----------|------|
|
||
| `state.user` | 用户信息 |
|
||
| `state.token` | Token |
|
||
| `setUser(user)` | 设置用户 |
|
||
| `setToken(token)` | 设置 Token |
|
||
| `clear()` | 清除状态 |
|
||
|
||
> ⚠️ **逐步废弃中**,建议迁移到 Pinia store。
|
||
|
||
### 8.3 认证存储(localStorage)
|
||
|
||
由 `src/utils/auth.js` 统一管理:
|
||
|
||
| Key | 内容 | 用途 |
|
||
|-----|------|------|
|
||
| `admin_token` | JWT Token | 管理员 Bearer Token(Authorization 头) |
|
||
| `admin_userInfo` | JSON `{ id, username, role, about_id, points }` | 管理员信息 |
|
||
| `admin_expire` | 过期时间 | Token 有效期 |
|
||
| `embed_mode` | `"true"` | 嵌入模式标志(隐藏导航栏) |
|
||
| `user_token` | JWT Token | 用户端 Token(区别于管理端) |
|
||
| `user_userInfo` | JSON | 用户端信息 |
|
||
| `printFlag` | `"1"` | 打印调试模式标记 |
|
||
|
||
---
|
||
|
||
## 9. 工具函数
|
||
|
||
### 9.1 签名工具(`src/utils/sign.js`)
|
||
|
||
`SignUtil` 单例类:
|
||
|
||
| 方法 | 说明 |
|
||
|------|------|
|
||
| `generateSign(params)` | 生成完整签名参数对象(含 app_key、client_id、timestamp、sign_method、sign) |
|
||
| `generateSignedUrl(baseUrl, params)` | 生成带签名的完整 URL |
|
||
| `calculateSign(params)` | 核心 MD5 签名计算 |
|
||
| `buildParamEntries(params, prefix)` | 递归展平嵌套对象/数组 |
|
||
| `sortKeys(a, b)` | 智能键排序 |
|
||
|
||
### 9.2 Mock 数据(`src/utils/mock.js`)
|
||
|
||
| 数据集 | 内容 |
|
||
|--------|------|
|
||
| `mockProducts` | 4 个模拟商品(基础会员卡 100pts 等) |
|
||
| `mockCards` | 50 张模拟卡密(随机状态 1/2/3/4) |
|
||
| `mockEmployees` | 4 个模拟代理(张三、李四、王五、系统管理员) |
|
||
| `mockOrders` | 30 个模拟订单 |
|
||
| `mockAccessLogs` | 50 条模拟积分记录(70% 收入 + 30% 支出) |
|
||
|
||
### 9.3 打印服务
|
||
|
||
| 文件 | 内容 |
|
||
|------|------|
|
||
| `src/utils/daYin/print.ts` | Lodop/Clodop 打印封装(TypeScript):`initLodop`, `createPrintTask`, `getSimplePrinterList` |
|
||
| `src/utils/daYinPdd/index.ts` | 拼多多打印服务 |
|
||
| `src/utils/pddUpload.ts` | 拼多多图片上传 |
|
||
|
||
### 9.4 其他
|
||
|
||
| 文件 | 说明 |
|
||
|------|------|
|
||
| `src/utils/clipboard.js` | 剪贴板操作工具 |
|
||
| `src/utils/ServiceManager.js` | 服务管理器 |
|
||
|
||
---
|
||
|
||
## 10. 外部服务集成
|
||
|
||
### 10.1 核价器(Pricer)
|
||
|
||
- **方式**:通过 `axios` 直连(不经过项目主 API),访问用户配置的 `{ip}:{port}`
|
||
- **功能**:查询商品价格、设置价格、孔夫子登录/Token 管理
|
||
- **文件**:`src/api/config.js`
|
||
- **特点**:每个请求动态传入 IP:Port,支持 URLSearchParams/JSON/FormData 多种请求格式
|
||
|
||
### 10.2 快递打印
|
||
|
||
- **方式**:通过独立 `axios` 实例直连(不经过 request 拦截器签名)
|
||
- **服务地址**:
|
||
- `api.buzhiyushu.cn` — 快递账号列表、回填快递单号
|
||
- `print.buzhiyushu.cn` — 创建快递面单、获取打印面单、查询快递信息
|
||
- **文件**:`src/api/shipping-order.js`
|
||
|
||
### 10.3 外部店铺 API
|
||
|
||
- **服务地址**:`https://api.buzhiyushu.cn/zhishu/shop/list` / `https://new.taskpool.buzhiyushu.cn:3500/api/shop/get/:id`
|
||
- **使用独立 axios 实例** + `json-bigint` 处理大整数
|
||
- **文件**:`src/api/shop.js`
|
||
|
||
### 10.4 孔夫子旧书网登录
|
||
|
||
- **方式**:Vite 开发服务器自定义中间件 `/kongfz-login`
|
||
- **流程**:POST `login.kongfz.com` → 跟随重定向 → 提取 PHPSESSID → 获取用户信息
|
||
- **绕过**:浏览器跨域限制(CORS)
|
||
- **错误码**:400(参数为空)/ 405(非 POST)/ 500(登录失败)
|
||
|
||
### 10.5 OCR 识别
|
||
|
||
- **端点**:`/ocr`(经过主 API 代理)
|
||
- **特殊处理**:设置 `X-Need-Sign: false` 跳过签名,保持 FormData 中 Blob 数据完整性
|
||
- **文件**:`src/api/product.js`(`ocrImage()` 方法)
|
||
|
||
---
|
||
|
||
## 11. 核心业务流程
|
||
|
||
### 11.1 波次管理流程
|
||
|
||
```
|
||
相机扫码 (camera.vue)
|
||
├── 扫描条码 → 查询书籍信息 (getBookInfo)
|
||
├── OCR 识别 → 提取书名/作者/出版社 (ocrImage)
|
||
├── 生成条码图片 (generateBarcode)
|
||
├── 编辑书籍信息 → 同步到系统 (syncBook)
|
||
└── 添加商品 → 创建波次 (createWaveOutbound)
|
||
└── 释放波次 → 生成采购/出库任务 (releaseWave)
|
||
```
|
||
|
||
### 11.2 采购到出库到发货全流程
|
||
|
||
```
|
||
创建采购订单 (createPurchaseOrder)
|
||
└── 创建带波次采购单 (createPurchaseOrderWithWave)
|
||
├── 释放波次 (releaseWave) → 生成波次任务
|
||
└── 采购入库 → 库存增加
|
||
└── 创建销售订单 (createSalesOrder)
|
||
├── 确认销售订单 (confirmSalesOrder)
|
||
│ └── 创建出库单 (createOutbound / createOutboundFromSalesOrder)
|
||
│ ├── 审核出库单 (approveOutbound)
|
||
│ │ └── 生成发货单 (createShippingOrder)
|
||
│ │ ├── 填写物流公司/单号 (updateShippingOrderLogistics)
|
||
│ │ └── 回填快递单号 (submitCompanyOrder)
|
||
│ └── 导出出库单 (exportOutbound)
|
||
└── 取消销售订单 (cancelSalesOrder)
|
||
```
|
||
|
||
### 11.3 盘库流程
|
||
|
||
```
|
||
创建盘库单 (createStockCheck) — 全盘/抽盘
|
||
└── 开始盘点 (startStockCheck) → 状态变为"盘点中"
|
||
└── 逐条/批量提交盘点结果 (submitCheckItem / batchSubmitCheckItems)
|
||
└── 完成盘点 (completeStockCheck) → 状态变为"已完成"
|
||
└── 库存调整 (adjustStockCheck) — 如有差异
|
||
|
||
也可中途取消盘库单 (cancelStockCheck)
|
||
```
|
||
|
||
### 11.4 商品发布流程
|
||
|
||
```
|
||
商品录入 → 选择店铺 → 发布商品
|
||
└── 查看发布记录(当前为 Mock 数据)
|
||
└── 失败重试 (retryProductPublish)
|
||
```
|
||
|
||
### 11.5 异常书目审核流程
|
||
|
||
```
|
||
员工提交异常书目 (saveAbnormalBook)
|
||
└── 管理员审核 (auditProductLog)
|
||
├── 通过 → 更新书目信息
|
||
└── 驳回 → 标记异常状态
|
||
```
|
||
|
||
---
|
||
|
||
## 12. 打印服务
|
||
|
||
### 12.1 打印架构
|
||
|
||
前端打印基于 **C-Lodop** / **Lodop** 控件,运行在 `http://localhost:8000`。
|
||
|
||
| 文件 | 说明 |
|
||
|------|------|
|
||
| `src/utils/daYin/print.ts` | 核心封装(TypeScript):`initLodop` 加载 `CLodopfuncs.js`,`createPrintTask` 创建打印任务,`getSimplePrinterList` 获取打印机列表 |
|
||
| `src/utils/daYinPdd/index.ts` | 拼多多打印封装 |
|
||
| `src/api/print.js` | 重导出上述 TS 文件的方法 |
|
||
|
||
### 12.2 打印机调试模式
|
||
|
||
**套装书条码打印**在首次走 `PRINT_SETUP`(弹出打印设置对话框),确认后 `localStorage.printFlag = '1'`,后续走 `PRINT()` 静默打印。
|
||
|
||
| 状态 | 打印方式 | 说明 |
|
||
|------|---------|------|
|
||
| `printFlag` 未设置或不为 `'1'` | `PRINT_SETUP()` | 弹出打印设置对话框,用户调整参数后确认 |
|
||
| `printFlag === '1'` | `PRINT()` | 直接静默打印 |
|
||
|
||
**手动入口**:波次页搜索栏的"打印调试"按钮,使用固定测试号 `9787000000000-01` 生成条码,始终弹出调试框。
|
||
|
||
---
|
||
|
||
## 13. 数据模型
|
||
|
||
### 13.1 盘库模块
|
||
|
||
| 表名 | 用途 |
|
||
|------|------|
|
||
| `stock_check` | 盘库单主表 |
|
||
| `stock_check_item` | 盘库明细表 |
|
||
|
||
**盘库单状态**:`1`=待盘点 → `2`=盘点中 → `3`=已完成 → `4`=已取消
|
||
**盘点类型**:`1`=全盘,`2`=抽盘
|
||
**明细状态**:`1`=待盘点,`2`=已盘点
|
||
|
||
### 13.2 出库/发货模块
|
||
|
||
- 基于 `shipping_order` 表结构(API 层已按表结构调整)
|
||
- 状态:`1`=待发货,`2`=已发货,`3`=已签收,`4`=已取消
|
||
|
||
### 13.3 波次模块
|
||
|
||
| 端点 | 用途 |
|
||
|------|------|
|
||
| `/wave/task/list` | 波次任务列表 |
|
||
| `/wave/task/detail` | 波次任务详情 |
|
||
| `/wave/list` | 波次列表(选择器用) |
|
||
| `/wave/getWaveStatusById` | 波次状态查询 |
|
||
|
||
### 13.4 库存模块
|
||
|
||
- **汇总级别**:按商品 + 仓库聚合
|
||
- **明细级别**:按仓库 + 库位 + 批次
|
||
- **关键字段**:总量、锁定数量、可用数量
|
||
|
||
### 13.5 分账模块
|
||
|
||
| 表/概念 | 说明 |
|
||
|---------|------|
|
||
| `split_account_config` | 分账规则配置(rule_name + rule_value JSON) |
|
||
| `split_account_deduction_log` | 分账扣款日志 |
|
||
|
||
---
|
||
|
||
## 14. 已知问题与维护
|
||
|
||
### 14.1 遗留问题
|
||
|
||
| # | 问题 | 说明 | 建议 |
|
||
|---|------|------|------|
|
||
| 1 | Vite 2 版本较旧 | `^2.5.2` 有已知安全更新 | 建议升级到 Vite 4+ |
|
||
| 2 | TypeScript 使用不一致 | `tsconfig.json` 存在但项目以 JS 为主 | 统一规范或移除 TS |
|
||
| 3 | 发布记录为 Mock 数据 | `releaseRecord.js` 无后端接口 | 待后端接口对接 |
|
||
| 4 | 旧版 Store 冗余 | `store/index.js` 与 Pinia 并存 | 可迁移清理 |
|
||
| 5 | 备份文件残留 | 多个 `.bak` 文件 | 确认后可删除 |
|
||
| 6 | 函数名 typo | `employeeType.js` 中 `updataEmployeInfo` → 应为 `updateEmployeeInfo` | 后续修复 |
|
||
| 7 | 文件名 typo | `submIllegalBook.js` → 应为 `submitIllegalBook.js` | 后续重命名 |
|
||
| 8 | 文件名 typo | `goosList.vue`(组件中)→ 应为 `goodsList.vue` | 后续重命名 |
|
||
| 9 | 重复 API 文件 | `split.js`(不完整)与 `splitAccount.js`(完整)并存 | 可删除 `split.js` |
|
||
| 10 | 重复 normalizeListResponse | 约 15 个文件各自定义该函数 | 应抽离为公共工具 |
|
||
| 11 | 仪表盘内容为空 | `Dashboard.vue` 统计内容待完善 | 待与后端对接更多数据 |
|
||
| 12 | courierConfig 不完整 | 仅 `createConfig` 有实现 | 需补充完整 |
|
||
| 13 | PDF 打印未集成 | 面单打印依赖外部服务 | 后端接入后完善 |
|
||
|
||
### 14.2 开发规范
|
||
|
||
| 规范 | 说明 |
|
||
|------|------|
|
||
| **API 层** | 所有后端接口调用集中在 `src/api/`,视图层不直接调用 `request` |
|
||
| **列表接口** | 统一使用 `normalizeListResponse()` 标准化返回格式 |
|
||
| **命名** | API 函数使用 `fetchXxx`(查询)、`createXxx`(新增)、`updateXxx`(更新)、`deleteXxx`(删除) |
|
||
| **签名** | 默认所有业务接口走签名,需跳过的设置 `X-Need-Sign: false` |
|
||
| **大整数** | 涉及 ID 字段使用 `json-bigint`,比较时注意 BigNumber 类型 |
|
||
| **组件命名** | Vue 组件使用 PascalCase 文件名 |
|
||
| **路由 meta** | 正确设置 `requiresAuth` / `requiresAdmin` / `hidden` |
|
||
|
||
### 14.3 添加新模块步骤
|
||
|
||
1. 在 `src/api/` 下新建 `<module>.js`,定义所有接口函数(含 JSDoc 注释)
|
||
2. 在 `src/views/` 下新建页面目录及 `.vue` 组件
|
||
3. 在 `src/router/index.js` 的 `children` 中添加路由
|
||
4. 确保 `meta` 中正确设置 `requiresAuth` / `requiresAdmin`
|
||
5. 在 `AdminLayout.vue` 中添加菜单项(如需显示在侧边栏)
|
||
6. 实现 `normalizeListResponse()` 标准化列表返回
|
||
|
||
### 14.4 维护日志
|
||
|
||
| 日期 | 操作 |
|
||
|------|------|
|
||
| 2026-06-15 | 更新技术文档,补充完整 API 接口表、路由表、新模块 |
|
||
| 2026-06-03 | 初始技术文档创建 |
|
||
|
||
---
|
||
*本文档随项目维护持续更新*
|