ItemMark 程序设计实现方案
状态:待确认后实施,已吸收 2026-05-09 的确认项
1. 整体方案
ItemMark 采用“单项目、多模块、同域名、路径区分”的设计。
默认部署域名:
https://code.zestrade.com模块路径:
| 模块 | 路径前缀 | 扫码页 | 扫码逻辑 |
|---|---|---|---|
| 对外物料信息模块 | /material-info | /material/{code} 和 /material-info/material/{code} | 查询物料基础信息 |
| 武平模块 | /wuping | /wuping/material/{code} | 查询库存台账 |
兼容策略:
- 旧项目 1 已经正常运行,旧二维码和模板优先兼容。
/material/{code}保留给对外物料信息模块,避免旧标签失效。- 武平模块所有二维码都加
/wuping前缀,避免和旧二维码冲突。
2. 目标目录结构
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.html3. 配置设计
3.1 全局配置
.env 保存全局部署配置:
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 模块配置
每个模块独立配置。配置来源优先级:
- 后台页面保存到
data/admin/itemmark_admin.db的模块配置。 config/modules/{module}.env。- 代码默认值。
模块配置字段:
| 字段 | 说明 | 默认值 |
|---|---|---|
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_host | U8 地址 | 192.168.1.135 |
u8_port | U8 端口 | 1433 |
u8_database | U8 账套 | 对外物料信息默认 UFDATA_104_2018,武平默认 UFDATA_105_2019 |
u8_user | U8 账号 | testreadonly |
u8_password | U8 密码 | 从旧配置复制或页面维护 |
template_path | 标签模板 | ./config/templates/{module}/label_config.xlsx |
detail_type | 扫码详情类型 | material_info / ledger |
ledger_enabled | 是否启用台账 | 武平为 true |
3.3 推荐初始模块配置
对外物料信息模块:
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武平模块:
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=true3.4 物料主数据和账套口径
物料基础信息在 104、105 等账套之间通用。104 账套是集团主账套、贸易账套,首版作为默认物料主数据来源;105 账套是子公司工厂账套,武平模块使用 105 查询出入库和库存结存。
实现策略:
material-info默认从 104 同步物料基础信息。wuping默认也可以同步物料基础信息到自己的模块库,但同步 SQL 和字段结构与 104 一致。- 首版确认保留模块 SQLite 隔离,降低影响项目 1 已调试模板和旧二维码的风险。
- 如果后续希望减少重复数据,可以再增加共享物料主数据表。
- 台账查询永远使用当前模块配置的账套,武平默认
UFDATA_105_2019。
4. 路由设计
4.1 页面路由
全局:
GET / 首页/模块入口
GET /admin 管理入口
GET /admin/sync 同步管理页面
GET /admin/modules 模块配置页面对外物料信息模块:
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} 二维码图片武平模块:
GET /wuping/material/{code} 展示库存台账
GET /wuping/batch 批量打印选择
GET /wuping/print/{code} 单张打印
GET /wuping/batch/print?codes=... 批量打印
GET /wuping/qr/{code} 二维码图片4.2 API 路由
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武平模块:
GET /api/wuping/material/{code}/ledger?start_date=&end_date=兼容旧项目 1:
GET /api/material/{code}
GET /api/materials5. 二维码设计
二维码必须由模块决定。
对外物料信息模块:
https://code.zestrade.com/material/{material_code}说明:
- 使用旧项目 1 的扫码路径。
- 最大程度兼容项目 1 已经打印出去的标签和已调试好的模板。
武平模块:
https://code.zestrade.com/wuping/material/{material_code}说明:
- 明确带
/wuping前缀。 - 扫码进入库存台账页。
二维码图片接口也按模块区分:
/material-info/qr/{material_code}
/wuping/qr/{material_code}6. 标签模板设计
每个模块独立读取 Excel 配置:
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:
data/material-info/itemmark.db
data/wuping/itemmark.db首版业务表沿用:
material_label_items原因:
- 两个旧项目表结构一致。
- 降低迁移风险。
- 便于复制旧数据库作为参考或临时回滚。
7.2 管理库
统一管理库:
data/admin/itemmark_admin.db建议表:
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 同步逻辑
同步核心逻辑参数化:
run_sync(module_config)流程:
- 读取模块配置。
- 连接模块指定的 U8 数据库。
- 抽取物料基础资料。默认物料主数据口径来自 104 主账套;模块可按自己的配置改为其他账套。
- 按模块二维码规则生成
qr_url。 - 写入模块自己的 SQLite。
- 写入
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 服务:
itemmark-web
itemmark-sync端口:
宿主机 18089 -> 容器 18089端口约束:
- ItemMark Web 应用自身不使用
8000、8080、3000、5000等常用端口。 - 首版统一使用
18089作为容器监听端口和宿主机映射端口。 https://code.zestrade.com对外 HTTPS 访问仍由 Nginx 提供;非常用端口要求只约束 ItemMark 应用服务端口。
Nginx:
- 使用
https://code.zestrade.com。 - 根路径反向代理到
itemmark-web。 - 证书和私钥可以复制旧项目已有文件。
示例:
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 相对路径约束
所有运行时路径使用相对路径,配置中不得写入开发机绝对路径或服务器绝对路径。
允许的路径形式:
./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不允许的路径形式:
/Users/mac/Desktop/ItemMark/...
/opt/ItemMark/...
/app/data/...Docker 容器内部路径可以由 Dockerfile 和 Compose 挂载实现,但业务配置和代码读取入口应基于项目相对路径解析。
12. 实施步骤
- 编码前按
2026-04-20-LLM-写代码规范.md写明假设、成功标准和验证方式。 - 按目标结构创建 ItemMark 项目。
- 复制项目 1 模板和物料信息扫码页面能力到
material-info模块。 - 复制项目 2 台账查询能力到
wuping模块。 - 建立模块配置服务和管理库。
- 改造同步逻辑为模块参数化。
- 实现同步管理页面和 API。
- 实现模块化二维码生成。
- 实现模块化标签配置读取。
- 保留
/material/{code}兼容路由。 - 完成 Docker Compose 和 Nginx 配置,应用端口使用
18089。 - 执行语法检查、Docker 配置检查和本地功能验证。
13. 验证命令
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功能验证:
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. 已识别风险
/material/{code}必须保留给旧项目 1 兼容,武平模块不能占用该路径。- 两个模块使用同一域名时,二维码生成必须严格按模块配置,不能共用旧的
QR_BASE_URL。 - 后台页面保存 U8 密码,需要避免在普通日志中打印密码。
- 手动同步和自动同步必须加锁,避免同一模块并发写 SQLite。
- 项目 1 已在 Linux OS 正常运行,整合部署前应备份旧目录、旧数据库和旧 Nginx 配置。
- 旧证书私钥可以复制,但部署文档要写清证书位置和权限。