feat(audit): 提升可读性 —— 操作对象补全物料名、详情降噪、字段字典补齐
业务方反馈两点:操作对象太干瘪、详情快照噪音太多。
1. 操作对象补全为「SKU - 物料名称 (规格型号)」
库里 target_name 大多只存了 SKU('0000002270'),入库类甚至存的是内部
标识('stock_buy ID:1667'),业务人员完全看不懂。
补全走两条路径,**正确性优先**:
· 快照里的 base_id(CREATE/DELETE 的库存行)—— 权威,零歧义
· target_id 唯一命中一张股票表 —— 实测与上一条 1230/1230 完全一致
★ 撞号一律放弃:target_id 同时命中 2 张股票表时解出的 base_id
24/27 是错的、命中 3 张时 44/44 全错。补一个**错的**物料名比不补更糟 ——
那是"看起来完全可信的错误答案",业务方会照着它去找不相干的物料。
实测 300 条撞号行 0 条被补,300 条唯一命中行全部补上。
target_name 原值保留(target_keyword 搜索仍按它匹配),新增 target_display
供展示。前端去掉灰显的 #target_id —— 业务人员不需要看数据库主键。
2. 详情快照降噪
· 前端过滤空值:null / '' / [] / {} / '-'。判据**严格**:false 和 0
不算空(`is_returned: false`、`quantity: 0` 是明确的业务事实,
用真值判断会把它们一起吃掉,那是在篡改数据)。
· 过滤纯技术字段:id / created_at / updated_at / target_id / module_name
及 pgvector 的 `*embedding`(单条可达数 KB)。清单由后端下发
(labels.hiddenFields),前端不硬编 —— 它会随新表增长,再存一份必然漂移。
embedding 类按后缀拦截,新表加向量列不必改代码。
· 变更对比表过滤「等于没改」的行(null ↔ 空串)。
3. 字段字典补齐:168 项
实测快照里出现过但字典没有的字段全部补上(buyer_email / currency /
in_date / exchange_rate / dosage / loss_rate / child / parent /
production_* / return_* / *_threshold 等 60+ 个)。
现在快照字段缺中文名的数量为 **0** —— 详情页不会再裸露英文。
4. 摘要优化
· changes_of 丢掉无意义变更(null ↔ 空串)。库里 98 条记录带这种变更,
写进摘要就是「备注:空→空」,纯噪音还挤占截断长度。
· CREATE/DELETE 摘要改为核心属性**按槽位取值**:
新增(入库):入库数量 10 件、库位 ZZTEST
而不是「新增:SKU、base、状态… 等 29 个字段」。
· 槽位只有数量与位置两个,**不含物料** —— 物料由「操作对象」列承担,
同一屏里再来一遍是重复。数量字段也按槽位只取一个:
in_quantity / stock_quantity / available_quantity 值往往相同,
取三个会得到三个一样的数字。
· 数字去掉无意义的 .0(10.0 → 10);单位取自物料主数据,
纯数字的占位单位(库里有一批 unit='1')丢弃。
验证:33 + 16 项断言全过,含「补全的物料与快照 base_id 零冲突」「撞号行
一律不补」「快照字段缺中文名 0 个」「摘要无空→空」「导出口径与列表一致」;
vue-tsc --noEmit 与 vite build 均 exit=0。
日报回归:三天附件 490.5K / 193.4K / 10.3K,6 列结构未变。
This commit is contained in:
@ -200,8 +200,130 @@ FIELD_LABELS = {
|
||||
'target_code': '目标编码',
|
||||
'user_agent': '浏览器标识',
|
||||
'ip_address': 'IP地址',
|
||||
'visibility_level': '可见级别',
|
||||
'is_archived': '是否归档',
|
||||
|
||||
# --- 采购 / 入库(stock_* 表)---
|
||||
# 这几个是实测缺失最多的:采购入库快照整表展开,缺一个就漏一排英文。
|
||||
'buyer_email': '采购邮箱',
|
||||
'in_date': '入库日期',
|
||||
'currency': '币种',
|
||||
'exchange_rate': '汇率',
|
||||
'inspection_status': '质检状态',
|
||||
'inspection_report': '质检报告',
|
||||
'inspection_report_link': '质检报告链接',
|
||||
'quality_status': '质检状态',
|
||||
'quality_report_link': '质检报告链接',
|
||||
'arrival_photo': '到货照片',
|
||||
'product_photo': '成品照片',
|
||||
'global_print_id': '全局打印ID',
|
||||
'base': '基础物料',
|
||||
'detail_link': '详情链接',
|
||||
'original_link': '原始链接',
|
||||
'supplier_link': '供应商链接',
|
||||
'request_id': '申请ID',
|
||||
'purchase_request': '采购申请',
|
||||
'order_id': '订单ID',
|
||||
'is_ordered': '是否已下单',
|
||||
'sale_price': '销售价',
|
||||
'location': '库位',
|
||||
'common_name': '通用名',
|
||||
'material': '物料',
|
||||
'images': '图片',
|
||||
|
||||
# --- 生产(半成品/成品)---
|
||||
'work_order_code': '工单号',
|
||||
'bom_code': 'BOM编号',
|
||||
'production_manager': '生产负责人',
|
||||
'production_date': '生产日期',
|
||||
'production_start_time': '生产开始时间',
|
||||
'production_end_time': '生产结束时间',
|
||||
'production_time_range': '生产时间段',
|
||||
'raw_material_cost': '原材料成本',
|
||||
'manual_cost': '人工成本',
|
||||
|
||||
# --- BOM ---
|
||||
'loss_rate': '损耗率',
|
||||
'dosage': '用量',
|
||||
'parent': '父件',
|
||||
'child': '子件',
|
||||
'version': '版本',
|
||||
'bom_remark': 'BOM备注',
|
||||
'child_bom_no': '子BOM编号',
|
||||
'child_bom_version': '子BOM版本',
|
||||
|
||||
# --- 退回 / 借还 ---
|
||||
'return_signature': '归还签名',
|
||||
'return_location': '归还库位',
|
||||
'borrow_signature': '借出签名',
|
||||
'current_holder_id': '当前持有人ID',
|
||||
'current_holder_name': '当前持有人',
|
||||
'borrower_id': '借用人ID',
|
||||
'dispatch_operator': '发放操作人',
|
||||
'source_return_id': '来源退回ID',
|
||||
|
||||
# --- 预警设置 ---
|
||||
'yellow_threshold': '黄色阈值',
|
||||
'red_threshold': '红色阈值',
|
||||
'yellow_emails': '黄色预警邮箱',
|
||||
'red_emails': '红色预警邮箱',
|
||||
'last_notified_at': '上次通知时间',
|
||||
|
||||
# --- 审批 ---
|
||||
'approver_name': '审批人',
|
||||
'approval_status': '审批状态',
|
||||
|
||||
# --- 盘点 / 扫码(长尾,实测仅个位数条记录,但不补就会在详情里裸露英文)---
|
||||
'diff_qty': '差异数量',
|
||||
'stock_qty': '库存数量',
|
||||
'scan_time': '扫码时间',
|
||||
'session_id': '会话标识',
|
||||
'uuid': '唯一标识',
|
||||
'image_url': '图片地址',
|
||||
'user_id': '用户ID',
|
||||
'type': '类型',
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# 6. 详情快照里**不展示**的纯技术字段
|
||||
#
|
||||
# ★ 判据:这些字段对业务人员零信息量,且常常极端冗长。
|
||||
# 典型是 image_embeddings 表的 `embedding`(1536 维向量),一条快照里
|
||||
# 塞进去就是几 KB 的乱码;`target_id` / `module_name` 则是审计层的元数据,
|
||||
# 被早期快照采集误带进了业务对象。
|
||||
#
|
||||
# ★ 只收「纯技术」的。链接/图片**不收**:那是业务内容,用户点进去是有用的;
|
||||
# 它们在"变更对比"里已经被 IGNORED_CHANGE_FIELDS 单独处理了。
|
||||
#
|
||||
# ★ 这份清单放在后端而不是前端硬编:它会随新表增长,前端再存一份必然漂移。
|
||||
# 前端经 GET /audit/labels 的 hiddenFields 取。
|
||||
# =============================================================================
|
||||
HIDDEN_SNAPSHOT_FIELDS = frozenset({
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'tenant_id',
|
||||
'target_id', # 审计层元数据,不是业务字段
|
||||
'module_name',
|
||||
'embedding', # pgvector 向量列,单条可达数 KB
|
||||
'img_embedding',
|
||||
'arrival_image_embedding',
|
||||
'qc_report_image_embedding',
|
||||
'image_embedding',
|
||||
})
|
||||
|
||||
|
||||
def is_hidden_snapshot_field(key):
|
||||
"""
|
||||
该字段是否属于「不该在详情快照里展示」的纯技术字段。
|
||||
|
||||
★ 除名单本身,还按**后缀**拦截 `*embedding`:向量列在各表命名不一
|
||||
(img_embedding / arrival_image_embedding / qc_report_image_embedding…),
|
||||
逐个登记必然漏。新表加向量列时不必再改这里。
|
||||
"""
|
||||
k = str(key or '').strip().lower()
|
||||
return k in HIDDEN_SNAPSHOT_FIELDS or k.endswith('embedding')
|
||||
|
||||
|
||||
def field_label(key):
|
||||
"""字段名 → 中文;未命中时原样返回字段名"""
|
||||
@ -552,4 +674,6 @@ def labels_payload():
|
||||
# 否则会「下拉显示『入库』、表格显示『库存管理』」。
|
||||
# ★ 含英文历史值,前端不再自带一份 moduleMap。
|
||||
'moduleDisplay': module_display_map(),
|
||||
# 详情快照里不展示的纯技术字段(前端过滤用,见 HIDDEN_SNAPSHOT_FIELDS)
|
||||
'hiddenFields': sorted(HIDDEN_SNAPSHOT_FIELDS),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user