图书进销存系统 — 技术文档
项目名称:Cards(图书进销存管理后台)
版本:1.0.0
最后更新:2026-06-15
项目路径:D:\project\psi_web
目录
- 项目概述
- 技术栈
- 项目结构
- 构建与部署
- 路由与权限
- API 架构
- API 接口详表
- 状态管理
- 工具函数
- 外部服务集成
- 核心业务流程
- 打印服务
- 数据模型
- 已知问题与维护
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 开发服务器
npm run dev
# → http://localhost:5174 (host: 0.0.0.0)
4.2 生产构建
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 守卫依次执行:
- URL 参数登录(嵌入模式):检测
window.location.search 中的 token 参数
- 自动写入
localStorage.admin_token
- 设置
localStorage.embed_mode = 'true'(隐藏导航栏)
- 解析 JWT Payload(base64)提取
id、username、role、about_id
- 用于跨系统嵌入(如从其他系统以 iframe 嵌入本系统)
- 标题设置:
document.title = "{meta.title} - 进销存系统"
- 登录页处理:已登录用户自动跳转
/dashboard
- 仪表盘鉴权:无
adminUserInfo 跳转 /login
- 黑名单模式鉴权:
- 所有非公开页面(未标记
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 类(单例导出),配置来自环境变量:
{
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 }:
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 添加新模块步骤
- 在
src/api/ 下新建 <module>.js,定义所有接口函数(含 JSDoc 注释)
- 在
src/views/ 下新建页面目录及 .vue 组件
- 在
src/router/index.js 的 children 中添加路由
- 确保
meta 中正确设置 requiresAuth / requiresAdmin
- 在
AdminLayout.vue 中添加菜单项(如需显示在侧边栏)
- 实现
normalizeListResponse() 标准化列表返回
14.4 维护日志
| 日期 |
操作 |
| 2026-06-15 |
更新技术文档,补充完整 API 接口表、路由表、新模块 |
| 2026-06-03 |
初始技术文档创建 |
本文档随项目维护持续更新