Project Docs

ItemMark 标签打印与扫码查询系统 · 02-程序设计实现方案.md

在线查看上传的 Markdown 项目文档。

ItemMark 程序设计实现方案

状态:待确认后实施,已吸收 2026-05-09 的确认项

1. 整体方案

ItemMark 采用“单项目、多模块、同域名、路径区分”的设计。

默认部署域名:

text
https://code.zestrade.com

模块路径:

模块路径前缀扫码页扫码逻辑
对外物料信息模块/material-info/material/{code}/material-info/material/{code}查询物料基础信息
武平模块/wuping/wuping/material/{code}查询库存台账

兼容策略:

  • 旧项目 1 已经正常运行,旧二维码和模板优先兼容。
  • /material/{code} 保留给对外物料信息模块,避免旧标签失效。
  • 武平模块所有二维码都加 /wuping 前缀,避免和旧二维码冲突。

2. 目标目录结构

text
ItemMark/
├── README.md
├── .env
├── .env.example
├── docker-compose.yml
├── docs/
├── certs/
│   └── code.zestrade.com/
├── config/
│   ├── nginx.conf
│   ├── modules/
│   │   ├── material-info.env
│   │   └── wuping.env
│   └── templates/
│       ├── material-info/
│       │   └── label_config.xlsx
│       └── wuping/
│           └── label_config.xlsx
├── data/
│   ├── admin/
│   │   └── itemmark_admin.db
│   ├── material-info/
│   │   └── itemmark.db
│   └── wuping/
│       └── itemmark.db
├── tools/
│   └── create_label_config.py
├── sync/
│   ├── Dockerfile
│   ├── scheduler.py
│   ├── sync_runner.py
│   ├── db_u8.py
│   ├── db_sqlite.py
│   ├── qr_gen.py
│   ├── logger.py
│   ├── requirements.txt
│   └── freetds.conf
└── web/
    ├── Dockerfile
    ├── main.py
    ├── settings.py
    ├── requirements.txt
    ├── db/
    │   ├── admin_db.py
    │   ├── material_db.py
    │   └── u8_ledger_db.py
    ├── routers/
    │   ├── admin.py
    │   ├── api.py
    │   ├── material_info.py
    │   └── wuping.py
    ├── services/
    │   ├── module_config_service.py
    │   ├── material_service.py
    │   ├── ledger_service.py
    │   ├── label_template_service.py
    │   ├── qr_service.py
    │   └── sync_service.py
    └── templates/
        ├── admin/
        │   ├── index.html
        │   ├── modules.html
        │   └── sync.html
        ├── material_info/
        │   ├── detail.html
        │   ├── print.html
        │   ├── batch.html
        │   └── batch_print.html
        └── wuping/
            ├── ledger_detail.html
            ├── print.html
            ├── batch.html
            └── batch_print.html

3. 配置设计

3.1 全局配置

.env 保存全局部署配置:

ini
APP_NAME=ItemMark
BASE_DOMAIN=https://code.zestrade.com
ADMIN_DB_PATH=./data/admin/itemmark_admin.db
WEB_HOST=0.0.0.0
WEB_PORT=18089
HOST_WEB_PORT=18089
LOG_LEVEL=INFO

说明:

  • 可以从旧项目复制真实 .env 作为初始配置来源。
  • 整合后会把模块级 U8 配置拆到模块配置中。

3.2 模块配置

每个模块独立配置。配置来源优先级:

  1. 后台页面保存到 data/admin/itemmark_admin.db 的模块配置。
  2. config/modules/{module}.env
  3. 代码默认值。

模块配置字段:

字段说明默认值
module_key模块标识material-info / wuping
module_name模块名称对外物料信息 / 武平
base_path模块路径前缀/material-info / /wuping
qr_base_url二维码前缀https://code.zestrade.com/...
sqlite_path模块 SQLite 路径./data/{module}/itemmark.db
u8_hostU8 地址192.168.1.135
u8_portU8 端口1433
u8_databaseU8 账套对外物料信息默认 UFDATA_104_2018,武平默认 UFDATA_105_2019
u8_userU8 账号testreadonly
u8_passwordU8 密码从旧配置复制或页面维护
template_path标签模板./config/templates/{module}/label_config.xlsx
detail_type扫码详情类型material_info / ledger
ledger_enabled是否启用台账武平为 true

3.3 推荐初始模块配置

对外物料信息模块:

ini
MODULE_KEY=material-info
MODULE_NAME=对外物料信息
BASE_PATH=/material-info
QR_BASE_URL=https://code.zestrade.com
SQLITE_PATH=./data/material-info/itemmark.db
U8_HOST=192.168.1.135
U8_PORT=1433
U8_DATABASE=UFDATA_104_2018
U8_USER=testreadonly
U8_PASSWORD=
TEMPLATE_PATH=./config/templates/material-info/label_config.xlsx
DETAIL_TYPE=material_info
LEDGER_ENABLED=false

武平模块:

ini
MODULE_KEY=wuping
MODULE_NAME=武平
BASE_PATH=/wuping
QR_BASE_URL=https://code.zestrade.com/wuping
SQLITE_PATH=./data/wuping/itemmark.db
U8_HOST=192.168.1.135
U8_PORT=1433
U8_DATABASE=UFDATA_105_2019
U8_USER=testreadonly
U8_PASSWORD=
TEMPLATE_PATH=./config/templates/wuping/label_config.xlsx
DETAIL_TYPE=ledger
LEDGER_ENABLED=true

3.4 物料主数据和账套口径

物料基础信息在 104、105 等账套之间通用。104 账套是集团主账套、贸易账套,首版作为默认物料主数据来源;105 账套是子公司工厂账套,武平模块使用 105 查询出入库和库存结存。

实现策略:

  • material-info 默认从 104 同步物料基础信息。
  • wuping 默认也可以同步物料基础信息到自己的模块库,但同步 SQL 和字段结构与 104 一致。
  • 首版确认保留模块 SQLite 隔离,降低影响项目 1 已调试模板和旧二维码的风险。
  • 如果后续希望减少重复数据,可以再增加共享物料主数据表。
  • 台账查询永远使用当前模块配置的账套,武平默认 UFDATA_105_2019

4. 路由设计

4.1 页面路由

全局:

text
GET /                         首页/模块入口
GET /admin                    管理入口
GET /admin/sync               同步管理页面
GET /admin/modules            模块配置页面

对外物料信息模块:

text
GET /material/{code}                         兼容旧二维码,展示物料信息
GET /material-info/material/{code}           新模块路径,展示物料信息
GET /material-info/batch                     批量打印选择
GET /material-info/print/{code}              单张打印
GET /material-info/batch/print?codes=...     批量打印
GET /material-info/qr/{code}                 二维码图片

武平模块:

text
GET /wuping/material/{code}                  展示库存台账
GET /wuping/batch                            批量打印选择
GET /wuping/print/{code}                     单张打印
GET /wuping/batch/print?codes=...            批量打印
GET /wuping/qr/{code}                        二维码图片

4.2 API 路由

text
GET  /api/modules
GET  /api/{module}/material/{code}
GET  /api/{module}/materials?keyword=&limit=&offset=
POST /api/{module}/materials/by-codes
GET  /api/{module}/label-config
GET  /api/{module}/sync/status
POST /api/{module}/sync/run
GET  /api/{module}/sync/config
PUT  /api/{module}/sync/config
GET  /api/health

武平模块:

text
GET /api/wuping/material/{code}/ledger?start_date=&end_date=

兼容旧项目 1:

text
GET /api/material/{code}
GET /api/materials

5. 二维码设计

二维码必须由模块决定。

对外物料信息模块:

text
https://code.zestrade.com/material/{material_code}

说明:

  • 使用旧项目 1 的扫码路径。
  • 最大程度兼容项目 1 已经打印出去的标签和已调试好的模板。

武平模块:

text
https://code.zestrade.com/wuping/material/{material_code}

说明:

  • 明确带 /wuping 前缀。
  • 扫码进入库存台账页。

二维码图片接口也按模块区分:

text
/material-info/qr/{material_code}
/wuping/qr/{material_code}

6. 标签模板设计

每个模块独立读取 Excel 配置:

text
config/templates/material-info/label_config.xlsx
config/templates/wuping/label_config.xlsx

模板服务接口:

  • get_label_config(module_key)
  • get_visible_fields(module_key)
  • get_template_path(module_key)

实施策略:

  • 对外物料信息模块直接复制项目 1 的 config/label_config.xlsx
  • 武平模块复制项目 2 的 config/label_config.xlsx
  • 代码读取模板时传入 module_key,避免两个模块共享同一个模板。

7. 数据库设计

7.1 模块业务库

每个模块一个 SQLite:

text
data/material-info/itemmark.db
data/wuping/itemmark.db

首版业务表沿用:

text
material_label_items

原因:

  • 两个旧项目表结构一致。
  • 降低迁移风险。
  • 便于复制旧数据库作为参考或临时回滚。

7.2 管理库

统一管理库:

text
data/admin/itemmark_admin.db

建议表:

sql
module_configs(
  module_key TEXT PRIMARY KEY,
  module_name TEXT NOT NULL,
  base_path TEXT NOT NULL,
  qr_base_url TEXT NOT NULL,
  sqlite_path TEXT NOT NULL,
  template_path TEXT NOT NULL,
  detail_type TEXT NOT NULL,
  ledger_enabled INTEGER NOT NULL,
  u8_host TEXT NOT NULL,
  u8_port INTEGER NOT NULL,
  u8_database TEXT NOT NULL,
  u8_user TEXT NOT NULL,
  u8_password TEXT,
  updated_at TEXT
);

sync_configs(
  module_key TEXT PRIMARY KEY,
  enabled INTEGER NOT NULL,
  mode TEXT NOT NULL,
  cron_expr TEXT,
  interval_minutes INTEGER,
  run_times TEXT,
  updated_at TEXT
);

sync_runs(
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  module_key TEXT NOT NULL,
  status TEXT NOT NULL,
  started_at TEXT,
  finished_at TEXT,
  extracted_count INTEGER DEFAULT 0,
  inserted_count INTEGER DEFAULT 0,
  updated_count INTEGER DEFAULT 0,
  failed_count INTEGER DEFAULT 0,
  elapsed_seconds REAL,
  error_message TEXT
);

8. 同步设计

8.1 同步逻辑

同步核心逻辑参数化:

text
run_sync(module_config)

流程:

  1. 读取模块配置。
  2. 连接模块指定的 U8 数据库。
  3. 抽取物料基础资料。默认物料主数据口径来自 104 主账套;模块可按自己的配置改为其他账套。
  4. 按模块二维码规则生成 qr_url
  5. 写入模块自己的 SQLite。
  6. 写入 sync_runs 执行记录。

8.2 自动同步

itemmark-sync 容器负责自动同步:

  • 启动时读取 sync_configs
  • 每分钟检查配置是否变化。
  • 根据每个模块自己的计划触发同步。
  • 同一模块运行中时跳过新的触发。

8.3 手动同步

Web 页面点击“立即同步”:

  • 调用 POST /api/{module}/sync/run
  • 后端创建后台任务执行 run_sync(module_config)
  • 前端轮询 GET /api/{module}/sync/status 查看进度。

实现注意:

  • 手动同步和自动同步共用同一套同步锁。
  • 同一模块不能并发同步。
  • 不同模块可以并行同步。

9. U8 台账设计

武平模块沿用旧项目 2 的 U8 台账 SQL:

  • 期初结存
  • 采购入库单
  • 调拨入库单
  • 调拨出库单
  • 材料出库单
  • 销售出库单

要求:

  • 使用武平模块自己的 U8 配置。
  • 武平模块默认账套为 UFDATA_105_2019,可在后台改为其他账套。
  • SQL Server 2008 R2 兼容,不使用 OFFSET/FETCH
  • 查询失败时页面降级显示基础信息。

9.1 后台权限策略

首版后台页面不做登录保护:

  • /admin
  • /admin/sync
  • /admin/modules

原因:当前需求明确不需要登录。

风险控制建议:

  • 当前确认暂不做 Nginx IP 白名单。
  • 后续如后台暴露风险变高,可再通过内网访问、VPN 或 Nginx IP 白名单限制后台路径。
  • 后端日志不得打印 U8 密码。
  • 页面展示密码时默认脱敏,只在编辑时允许重新填写。

10. Docker 和 Nginx 设计

Docker 服务:

text
itemmark-web
itemmark-sync

端口:

text
宿主机 18089 -> 容器 18089

端口约束:

  • ItemMark Web 应用自身不使用 8000808030005000 等常用端口。
  • 首版统一使用 18089 作为容器监听端口和宿主机映射端口。
  • https://code.zestrade.com 对外 HTTPS 访问仍由 Nginx 提供;非常用端口要求只约束 ItemMark 应用服务端口。

Nginx:

  • 使用 https://code.zestrade.com
  • 根路径反向代理到 itemmark-web
  • 证书和私钥可以复制旧项目已有文件。

示例:

nginx
server {
    listen 443 ssl;
    server_name code.zestrade.com;

    ssl_certificate     ./certs/code.zestrade.com/code.zestrade.com.crt;
    ssl_certificate_key ./certs/code.zestrade.com/code.zestrade.com.key;

    location / {
        proxy_pass http://127.0.0.1:18089;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

11. 旧项目资料迁移策略

允许复制:

  • 旧项目真实 .env
  • 旧项目数据库文件。
  • 旧项目证书和私钥。
  • 项目 1 已调试好的标签配置。
  • 项目 2 已实现的库存台账查询代码和模板。

迁移原则:

  • 旧项目 1 正在生产运行,整合时优先保证旧二维码路径和标签打印效果不变。
  • 旧数据库可复制到 data/legacy/ 备份,也可作为初始检查数据。
  • 首次正式运行仍重新从 U8 同步,避免新旧数据混杂。
  • 证书路径在部署文档中明确,Docker 项目内可保存证书副本。

11.1 相对路径约束

所有运行时路径使用相对路径,配置中不得写入开发机绝对路径或服务器绝对路径。

允许的路径形式:

text
./data/admin/itemmark_admin.db
./data/material-info/itemmark.db
./data/wuping/itemmark.db
./config/modules/material-info.env
./config/templates/material-info/label_config.xlsx
./certs/code.zestrade.com/code.zestrade.com.key
./logs/sync.log

不允许的路径形式:

text
/Users/mac/Desktop/ItemMark/...
/opt/ItemMark/...
/app/data/...

Docker 容器内部路径可以由 Dockerfile 和 Compose 挂载实现,但业务配置和代码读取入口应基于项目相对路径解析。

12. 实施步骤

  1. 编码前按 2026-04-20-LLM-写代码规范.md 写明假设、成功标准和验证方式。
  2. 按目标结构创建 ItemMark 项目。
  3. 复制项目 1 模板和物料信息扫码页面能力到 material-info 模块。
  4. 复制项目 2 台账查询能力到 wuping 模块。
  5. 建立模块配置服务和管理库。
  6. 改造同步逻辑为模块参数化。
  7. 实现同步管理页面和 API。
  8. 实现模块化二维码生成。
  9. 实现模块化标签配置读取。
  10. 保留 /material/{code} 兼容路由。
  11. 完成 Docker Compose 和 Nginx 配置,应用端口使用 18089
  12. 执行语法检查、Docker 配置检查和本地功能验证。

13. 验证命令

bash
python3 -m py_compile sync/*.py web/*.py web/routers/*.py web/services/*.py web/db/*.py
python3 tools/create_label_config.py --module material-info
python3 tools/create_label_config.py --module wuping
docker-compose config

功能验证:

text
https://code.zestrade.com/
https://code.zestrade.com/admin/sync
https://code.zestrade.com/material-info/batch
https://code.zestrade.com/material/{code}
https://code.zestrade.com/wuping/batch
https://code.zestrade.com/wuping/material/{code}

14. 已识别风险

  1. /material/{code} 必须保留给旧项目 1 兼容,武平模块不能占用该路径。
  2. 两个模块使用同一域名时,二维码生成必须严格按模块配置,不能共用旧的 QR_BASE_URL
  3. 后台页面保存 U8 密码,需要避免在普通日志中打印密码。
  4. 手动同步和自动同步必须加锁,避免同一模块并发写 SQLite。
  5. 项目 1 已在 Linux OS 正常运行,整合部署前应备份旧目录、旧数据库和旧 Nginx 配置。
  6. 旧证书私钥可以复制,但部署文档要写清证书位置和权限。