20 KiB
20 KiB
图书进销存系统 — 技术文档
项目名称:Cards(图书进销存管理后台)
版本:1.0.0
最后更新:2026-06-03
项目路径:D:\project\cards_web
目录
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 组件库(中文 locale,small 尺寸) |
@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 # 旧版 store(reactive 方式,逐步废弃)
│ └── 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 开发服务器
npm run dev
# → http://localhost:5174 (host: 0.0.0.0)
4.2 生产构建
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 路由守卫逻辑
- URL 参数注入:检测
?token=xxx参数,自动写入 localStorage 并解析 JWT,用于跨系统嵌入 - 登录守卫:未登录用户自动重定向到
/login - 管理员守卫:
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 排序签名,可跳过)
│ └── 对象自动转 FormData(POST/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 }:
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 添加新模块步骤
- 在
src/api/下新建<module>.js,定义所有接口函数 - 在
src/views/下新建页面目录及.vue组件 - 在
src/router/index.js的children中添加路由 - 确保
meta中正确设置requiresAuth/requiresAdmin - 在
AdminLayout.vue中添加菜单项
本文档随项目维护持续更新