daShangDao_psiWebApp/技术文档.md
97694731 0543936df8
Some checks failed
CI / build (20.x) (push) Waiting to run
CI / lint (push) Waiting to run
CI / test (push) Waiting to run
CI / deploy-preview (push) Blocked by required conditions
CI / security (push) Waiting to run
CI / build (18.x) (push) Has been cancelled
change store
2026-06-04 11:18:46 +08:00

490 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 图书进销存系统 — 技术文档
> **项目名称**Cards图书进销存管理后台
> **版本**1.0.0
> **最后更新**2026-06-03
> **项目路径**`D:\project\cards_web`
---
## 目录
1. [项目概述](#1-项目概述)
2. [技术栈](#2-技术栈)
3. [项目结构](#3-项目结构)
4. [构建与部署](#4-构建与部署)
5. [路由与权限](#5-路由与权限)
6. [API 架构](#6-api-架构)
7. [状态管理](#7-状态管理)
8. [外部服务集成](#8-外部服务集成)
9. [核心业务流程](#9-核心业务流程)
10. [已知问题与维护](#10-已知问题与维护)
---
## 1. 项目概述
本项目是一个面向图书行业的**进销存管理后台系统**,覆盖图书采购入库、库存管理、商品发布、销售出库、发货打单、盘库盘点等全链路业务流程。系统支持多角色(管理员/代理权限控制并集成了核价器、快递打印、OCR 识别等外部服务。
### 核心业务范围
| 模块 | 说明 |
|------|------|
| **波次管理** | 相机扫码 → 条码识别 → 书籍信息编辑 → 波次创建/释放 |
| **订单管理** | 采购订单 → 销售订单 → 出库单 → 发货单,全链路可追溯 |
| **库存管理** | 库存查询(商品维度/仓库维度)、变动记录、盘库盘点 |
| **商品管理** | 商品 CRUD、实拍图片管理、多店铺发布/重试 |
| **店铺管理** | 多平台店铺(拼多多、孔夫子、闲鱼等)管理、授权状态 |
| **系统管理** | 代理账号、员工类型、核价器配置、物流模板、打印机管理 |
---
## 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 组件库(中文 localesmall 尺寸) |
| `@element-plus/icons-vue` | ^2.1.0 | 图标库 |
| `axios` | ^1.7.9 | HTTP 客户端 |
| `crypto-js` | ^4.2.0 | 签名算法MD5/SHA256 |
| `json-bigint` | ^1.0.0 | 大整数精度处理 |
| `@zxing/library` | ^0.21.3 | 条形码/二维码扫描 |
| `jsbarcode` | ^3.12.3 | 条码生成 |
| `qrcode` | ^1.5.4 | QR 码生成 |
### 2.2 工程化
| 工具 | 版本 | 用途 |
|------|------|------|
| `vite` | ^2.5.2 | 构建工具与开发服务器 |
| `typescript` | ^5.5.4 | 类型检查(项目以 JS 为主,部分 .ts 文件) |
| `sass` | ^1.99.0 | CSS 预处理器 |
### 2.3 环境变量(`.env`
| 变量 | 值 | 说明 |
|------|-----|------|
| `VITE_APP_API_KEY` | `psi` | API 签名密钥 |
| `VITE_APP_CLIENT_ID` | `psi` | 客户端 ID |
| `VITE_APP_API_SECRET` | `psi_api_sign_secret` | 签名密钥 |
---
## 3. 项目结构
```
src/
├── api/ # API 层:所有后端接口调用集中于此
│ ├── barcode.js # 条码生成
│ ├── book.js # 书籍信息查询/同步
│ ├── car.js # 小车管理
│ ├── config.js # 核价器配置(直连外部 IP:Port
│ ├── dashboard.js # 仪表盘统计
│ ├── district.js # 行政区划(省/市/区)及运费模板
│ ├── employee.js # 员工/代理管理
│ ├── employeeType.js # 员工类型管理
│ ├── goodsInfo.js # 商品图像信息
│ └── submIllegalBook.js # 提交异常书目
│ ├── inventory.js # 库存记录
│ ├── location.js # 库位管理
│ ├── login.js # 登录
│ ├── logistics.js # 物流模板
│ ├── outbound.js # 出库管理
│ ├── print.js # 打印服务(导出 Lodop 方法)
│ ├── product.js # 商品管理
│ ├── purchase-order.js # 采购订单
│ ├── releaseRecord.js # 发布记录(当前为 Mock 数据)
│ ├── reviewIllegalBook.js # 异常书目审核
│ ├── sales-order.js # 销售订单
│ ├── shipping-order.js # 发货单(含外部快递接口)
│ ├── shop.js # 店铺管理(含外部 API + 内部 API
│ ├── stock-check.js # 盘库管理
│ ├── supplier.js # 供应商管理
│ ├── warehouse.js # 仓库管理
│ └── wave-task.js # 波次任务
├── components/ # 公共组件
│ ├── AdminLayout.vue # 主布局(侧边栏+顶部栏+内容区)
│ ├── goodsPop/index.vue # ISBN 悬停浮窗(书品信息预览)
│ ├── inventory/ # 库存子组件byGoods, byLocation
│ ├── product/ # 商品子组件byGoods, byLocation
│ ├── wave/ # 波次子组件camera, car, bookInfo 等)
│ └── wareHouse/ # 仓库子组件WarehouseList, LocationManager
├── views/ # 页面级组件
│ ├── login/Login.vue # 登录页
│ ├── admin/ # 管理员页面Dashboard, EmployeeList, EmployeeAdd, employeeType
│ ├── wave/Wave.vue # 波次管理主页面
│ ├── warehouse/ # 仓库列表
│ ├── supplier/Supplier.vue # 供应商列表
│ ├── product/Product.vue # 商品列表
│ ├── purchase-order/ # 采购订单
│ ├── sales-order/ # 销售订单
│ ├── shipping-order/ # 发货单
│ ├── outbound/Outbound.vue # 出库管理
│ ├── inventory/Inventory.vue # 库存记录
│ ├── stock-check/ # 盘库管理
│ ├── shop/Shop.vue # 店铺管理
│ ├── car/Car.vue # 小车管理
│ ├── config/config.vue # 核价器配置
│ ├── logistics/index.vue # 物流模板
│ ├── releaseRecord/ # 发布记录
│ ├── reviewIllegalBook/ # 异常书目审核
│ ├── printer-manager/ # 打印机管理
│ ├── shop-settings/ # 店铺设置
│ ├── sorting-settings/ # 分拣设置
│ ├── location/Location.vue # 库位列表
│ ├── scanner/Scanner.vue # 扫码页
│ ├── pdaManage/ # PDA 管理
│ └── wave-task/WaveTask.vue # 波次任务列表
├── router/index.js # 路由配置History 模式 + 路由守卫)
├── store/ # 状态管理
│ ├── index.js # 旧版 storereactive 方式,逐步废弃)
│ └── user.js # Pinia 用户 store
├── utils/ # 工具函数
│ ├── request.js # Axios 封装拦截器、签名、Mock
│ ├── auth.js # Token/UserInfo 的 localStorage 读写
│ ├── sign.js # 签名工具MD5/SHA256参数排序
│ ├── mock.js # Mock 数据
│ ├── clipboard.js # 剪贴板工具
│ ├── daYin/print.ts # Lodop 打印服务
│ ├── daYinPdd/index.ts # 拼多多打印
│ ├── pddUpload.ts # 拼多多图片上传
│ └── ServiceManager.js # 服务管理器
├── App.vue # 根组件
└── main.js # 入口文件(注册 Element Plus / Pinia / Router
```
---
## 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` 中:
| 配置项 | 值 | 说明 |
|--------|-----|------|
| **代理** | `/api``http://192.168.101.213:9090` | 主业务 API |
| **代理** | `/api/print``http://192.168.101.127:8075` | 打印服务 |
| **别名** | `@``./src` | 模块路径别名 |
| **端口** | `5174` | 开发服务器端口 |
| **自定义中间件** | `/kongfz-login` | 孔夫子登录代理(避免跨域) |
---
## 5. 路由与权限
### 5.1 路由模式
`createWebHistory()` — History 模式URL 格式为 `http://host:port/path`
### 5.2 路由表
| 路径 | 组件 | 标题 | 权限 |
|------|------|------|------|
| `/login` | Login.vue | 登录 | 无(已登录自动跳转) |
| `/dashboard` | Dashboard.vue | 仪表盘 | 需认证 |
| `/admin/employees` | EmployeeList.vue | 代理管理 | 管理员 |
| `/admin/employees/add` | EmployeeAdd.vue | 添加代理 | 管理员 |
| `/admin/employee-type` | employeeType.vue | 员工类型管理 | 管理员 |
| `/wave` | Wave.vue | 波次管理 | 需认证 |
| `/warehouse` | WareHouse.vue | 仓库列表 | 需认证 |
| `/supplier` | Supplier.vue | 供应商管理 | 需认证 |
| `/product` | Product.vue | 商品管理 | 需认证 |
| `/purchase-order` | PurchaseOrder.vue | 采购订单 | 需认证 |
| `/sales-order` | SalesOrder.vue | 销售订单 | 需认证 |
| `/outbound` | Outbound.vue | 出库管理 | 需认证 |
| `/shipping-order` | ShippingOrder.vue | 发货单 | 需认证 |
| `/inventory` | Inventory.vue | 库存记录 | 需认证 |
| `/stock-check` | StockCheck.vue | 盘库管理 | 需认证 |
| `/release-record` | releaseRecord.vue | 发布记录 | 需认证 |
| `/shop` | Shop.vue | 店铺管理 | 需认证 |
| `/car` | Car.vue | 小车管理 | 需认证 |
| `/location` | Location.vue | 库位列表 | 需认证 |
| `/review-illegal-book` | ReviewIllegalBook.vue | 异常书目审核 | 管理员 |
| `/testUrl` | config.vue | 核价器配置 | 管理员 |
| `/printer-manager` | PrinterManager.vue | 打印机管理 | 需认证 |
| `/logistics` | logistics/index.vue | 物流模板管理 | 需认证 |
| ... | 其他 | 隐藏菜单路由 | 需认证 |
### 5.3 路由守卫逻辑
1. **URL 参数注入**:检测 `?token=xxx` 参数,自动写入 localStorage 并解析 JWT用于跨系统嵌入
2. **登录守卫**:未登录用户自动重定向到 `/login`
3. **管理员守卫**`requiresAdmin: true` 的路由仅 `role=255` 可访问,否则重定向到 `/dashboard`
### 5.4 角色权限
| role 值 | 身份 | 说明 |
|---------|------|------|
| `255` | 管理员 | 全部功能可用 |
| `128` | 代理 | 仪表盘、波次、仓库、商品等基础功能 |
---
## 6. API 架构
### 6.1 网络拓扑
```
浏览器 ──→ Vite Dev Server (:5174)
├── /api/* ──→ Proxy ──→ http://192.168.101.213:9090 (主业务 API
├── /api/print/* ──→ Proxy ──→ http://192.168.101.127:8075 (打印服务)
├── /kongfz-login ──→ Node.js 中间件 ──→ login.kongfz.com (孔夫子登录)
└── axios 直连 ──→ 核价器 http://{ip}:{port} (用户配置)
──→ https://api.buzhiyushu.cn (店铺列表/快递回填)
──→ https://print.buzhiyushu.cn (快递面单打印)
```
### 6.2 请求封装(`src/utils/request.js`
核心流程:
```
请求发起
├── 请求拦截器
│ ├── 注入 Bearer Token从 localStorage.admin_token 读取)
│ ├── 生成签名参数params/body → MD5 排序签名,可跳过)
│ └── 对象自动转 FormDataPOST/PUT/DELETE
└── 响应拦截器
├── code=200 → 返回 response.data
├── code≠200 → 统一 ElMessage 错误提示
├── HTTP 401 → 清除 token 并跳转登录页
├── HTTP 403/404/500 → 对应错误提示
└── 网络错误 → "检查网络连接"
```
**签名机制**`src/utils/sign.js`
- 参数平铺排序(支持嵌套对象和数组)
- `app_secret + 参数字符串 + app_secret` 进行 MD5 签名
- 自动注入 `app_key`、`client_id`、`timestamp`、`sign_method` 等系统参数
- 通过请求头 `X-Need-Sign: false` 可跳过签名
**大整数精度**
- 使用 `json-bigint` 替换默认的 JSON.parse防止后端返回的 19 位大整数丢失精度
### 6.3 API 模块总览
| 文件 | 接口前缀 | 风格 | 说明 |
|------|---------|------|------|
| `login.js` | `/login/{role}` | request | 管理员/代理登录 |
| `dashboard.js` | `/dashboard/statist` | request | 仪表盘统计 |
| `barcode.js` | `/barcode/generate` | request+FormData | 条码生成 |
| `book.js` | `/getBookInfo`, `/syncBook` | request | 书籍查询/同步 |
| `car.js` | `/car/*` | request | 小车 CRUD |
| `config.js` | 外部 URL `http://{ip}:{port}` | axios 直连 | 核价器(价格查询/Token管理 |
| `district.js` | `/district/*` | request | 省市区数据、运费模板 |
| `employee.js` | `/admin/employee/*` | request | 代理增删改查、积分操作 |
| `employeeType.js` | `/admin/user-type/*` | request | 员工类型管理 |
| `goodsInfo.js` | `/product_log/save` | request+FormData | 提交书目异常 |
| `inventory.js` | `/inventory/*` | request | 库存汇总/明细/变动记录 |
| `location.js` | `/location/*` | request | 库位 CRUD、批量生成 |
| `logistics.js` | `/logistics/*` | request | 物流模板 CRUD |
| `outbound.js` | `/outbound-order/*` | request | 出库单 CRUD、审核、导出 |
| `print.js` | — | 导出 ts 方法 | 打印服务Lodop |
| `product.js` | `/product/*`, `/getSuitBook`, `/ocr` | request | 商品 CRUD、图片管理、OCR |
| `purchase-order.js` | `/purchase-order/*`, `/wave/release` | request | 采购单 CRUD、波次释放 |
| `releaseRecord.js` | — | **Mock** | 发布记录(纯前端模拟数据) |
| `reviewIllegalBook.js` | `/product_log/*` | request | 异常书目查询/删除 |
| `sales-order.js` | `/sales-order/*` | request | 销售订单 CRUD、确认、取消 |
| `shipping-order.js` | `/shipping-order/*` | request | 发货单 CRUD + 外部直连 |
| `shop.js` | `/shop/*` + 外部 URL | request+axios | 店铺 CRUD + 外部列表查询 |
| `stock-check.js` | `/inventory/stock-check/*` | request | 盘库单 CRUD、盘点提交 |
| `submIllegalBook.js` | `/product_log/audit` | request+FormData | 异常书目审核 |
| `supplier.js` | `/supplier/*` | request | 供应商 CRUD |
| `warehouse.js` | `/warehouse/*` | request | 仓库 CRUD |
| `wave-task.js` | `/wave/*` | request | 波次任务/列表 |
### 6.4 列表接口标准化
大部分 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)
}
}
```
### 6.5 Mock 模式
`src/utils/request.js``USE_MOCK = false`。启用后支持模拟数据(商品、卡密、订单、代理等),用于离线开发调试。
---
## 7. 状态管理
### 7.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()` | 方法 | 清除用户信息(登出) |
### 7.2 旧版 Store`src/store/index.js`
基于 Vue `reactive` 的简单 store未使用 Pinia逐步废弃中。
### 7.3 认证状态
认证信息存储于 `localStorage`,通过 `src/utils/auth.js` 统一管理:
| Key | 内容 | 用途 |
|-----|------|------|
| `admin_token` | JWT Token | 管理员 Bearer Token |
| `admin_userInfo` | JSON 用户信息 | 管理员信息(含 role、about_id 等) |
| `embed_mode` | `"true"` | 嵌入模式标志(隐藏导航栏) |
---
## 8. 外部服务集成
### 8.1 核价器Pricer
- **方式**:通过 `axios` 直连(不经过项目主 API连接用户配置的 IP:Port
- **功能**:查询商品价格、设置价格、管理登录 Token
- **文件**`src/api/config.js`,全部为 axios 直连请求
### 8.2 快递打印
- **方式**:通过 `axios` 直连
- **接口**
- `api.buzhiyushu.cn` — 快递账号列表、回填快递单号
- `print.buzhiyushu.cn` — 创建快递面单、获取打印面单
- **特点**:使用独立的 `axios` 实例(不经过 request 拦截器签名)
- **文件**`src/api/shipping-order.js`
### 8.3 店铺列表
- 内部接口(经过代理)和外部接口(`api.buzhiyushu.cn` 直连)两条路径
- 外部接口使用独立 axios 实例 + JSONbig 处理大整数
- **文件**`src/api/shop.js`
### 8.4 孔夫子旧书网登录
- 通过 Vite 开发服务器自定义中间件 `/kongfz-login` 实现
- 模拟浏览器登录流程POST 表单 → 处理重定向 → 提取 PHPSESSID → 获取用户信息
- 绕过浏览器跨域限制
### 8.5 OCR 识别
- 图片上传到 `/ocr` 接口进行文字识别
- 跳过签名(`X-Need-Sign: false`),保持 FormData 中 Blob 数据完整性
- **文件**`src/api/product.js` 中的 `ocrImage()`
### 8.6 Lodop 打印
- `src/utils/daYin/print.ts` — Clodop/Lodop 打印服务封装
- `src/utils/daYinPdd/index.ts` — 拼多多打印服务
---
## 9. 核心业务流程
### 9.1 波次管理流程
```
相机扫码 (camera.vue)
├── 扫描条码 → 查询书籍信息 (getBookInfo)
├── OCR 识别 → 提取书名/作者/出版社 (ocrImage)
├── 生成条码图片 (generateBarcode)
├── 编辑书籍信息 → 同步到系统 (syncBook)
└── 添加商品 → 创建波次 (createWaveOutbound)
└── 释放波次 → 生成采购/出库任务 (releaseWave)
```
### 9.2 采购到出库流程
```
创建采购订单 (createPurchaseOrder)
└── 创建波次 → 释放波次 → 生成波次任务
└── 采购入库 → 库存增加
└── 创建销售订单 (createSalesOrder)
└── 确认销售订单 → 创建出库单 (createOutbound)
└── 审核出库单 → 生成发货单 (createShippingOrder)
└── 填写物流信息 → 回填快递单号 (submitCompanyOrder)
```
### 9.3 盘库流程
```
创建盘库单 (createStockCheck) — 全盘/抽盘
└── 开始盘点 (startStockCheck) → 状态变为"盘点中"
└── 逐条/批量提交盘点结果 (submitCheckItem / batchSubmitCheckItems)
└── 完成盘点 (completeStockCheck) → 状态变为"已完成"
```
### 9.4 店铺商品发布
```
商品录入 → 选择店铺 → 发布商品
└── 查看发布记录(当前为 Mock 数据)
└── 失败重试 (retryRelease)
```
---
## 10. 已知问题与维护
### 10.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` 后缀文件 | 确认后可删除 |
### 10.2 开发规范
- **API 层**:所有后端接口调用集中在 `src/api/`,视图层不直接调用 `request`
- **列表接口**:统一使用 `normalizeListResponse()` 标准化返回格式
- **接口文档**:优先用 JSDoc 注释描述参数和返回值
- **命名**API 函数使用 `fetchXxx`(查询)、`createXxx`(新增)、`updateXxx`(更新)、`deleteXxx`(删除)
### 10.3 添加新模块步骤
1.`src/api/` 下新建 `<module>.js`,定义所有接口函数
2.`src/views/` 下新建页面目录及 `.vue` 组件
3.`src/router/index.js``children` 中添加路由
4. 确保 `meta` 中正确设置 `requiresAuth` / `requiresAdmin`
5.`AdminLayout.vue` 中添加菜单项
---
*本文档随项目维护持续更新*