chore: 批量完成项目多模块迭代优化

1. 废弃半成品库存表并统一库存主表
2. 修复列表排序与搜索大小写不敏感问题
3. 新增用户最近登录时间、工单BOM名称字段
4. 完善角色管理、工位选择器功能
5. 增加拧紧数据补录、成品自动回流WMS能力
6. 统一导出时间范围校验规则
7. 丰富物料/备料单筛选条件
8. 调整菜单与权限命名适配产品型号业务
This commit is contained in:
SunYF
2026-09-08 11:44:04 +08:00
parent 06689970e2
commit e852c7cd37
96 changed files with 4528 additions and 542 deletions
+36 -30
View File
@@ -3,16 +3,16 @@
// 说明:这里的"数据来源"特指该字段的数据由谁产生、从哪个系统/页面来,帮助跑通真实流程。
export const helpProductType = {
title: '产品型(档案维护)',
title: '产品型(档案维护)',
overview:
'产品型 = 企业要生产哪些产品的分类档案,是整条产线的源头基础数据。\n\n主数据链条:产品型 → 工单(选产品型) → 物料清单(给该产品编码配料) → 日排产 → 备料单 → 库房出库 → 产线生产。\n\n关系说明(几对几):\n· 产品型 ↔ 工单:1 对 N。一个产品型可以建多个工单(同一型号今天做一批、明天做一批,工单号不同、产品编码相同)。\n· 产品型 ↔ 物料清单:按产品编码 1 对 1。同型号产品共用一份 BOM。\n· 产品型 ↔ 备料单:间接。备料单由「日排产 × 该产品 BOM」算出,与产品型无直接约束。\n· 强约束:工单/物料清单都挂在产品编码下,产品型编码变了,下游关联会断,建议建好后不要改。\n· 与 WMS 的关系:两套系统解耦。本页(MES)维护产品与 BOM;WMS(库房)维护物料档案与库存,靠「物料编码」对齐;成品编码由人员手动录入 WMS 实现两系统对齐。',
'产品型 = 企业要生产哪些产品的分类档案,是整条产线的源头基础数据。\n\n主数据链条:产品型 → 工单(选产品型号+BOM) → 物料清单(给该产品编码配料) → 日排产 → 备料单 → 库房出库 → 产线生产 → 完工成品自动回流 WMS 入库。\n\n关系说明(几对几):\n· 产品型 ↔ 工单:1 对 N。一个产品型可以建多个工单(同一型号今天做一批、明天做一批,工单号不同、产品编码相同)。\n· 产品型 ↔ 物料清单:1 对多(选用制)。同型号可并存多份 BOM(不同厂家供货/含半成品结构),用「BOM 名称」区分,工单建单时选定一份,备料/装机都按工单锁定的那份算。\n· 产品型 ↔ 备料单:间接。备料单由「日排产 × 工单锁定的 BOM」算出,与产品型无直接约束。\n· 强约束:工单/物料清单都挂在产品编码下,产品型编码变了,下游关联会断,建议建好后不要改。\n· 与 WMS 的关系:两套系统解耦。产品/物料编码主数据以 WMS 为单一来源,MES 实时拉取(WMS 不可达时允许手填、仅提示不强校验);成品完工后由系统自动生成 SN 回流 WMS 入库,无需人工对账。',
fields: [
{ name: '名称', source: '手工填写。用户自定义,无上游来源。', purpose: '产品型的中文名,用于识别与下拉展示', fill: '如:智能电表、断路器、配电柜' },
{ name: '名称', source: '手工填写。用户自定义,无上游来源。', purpose: '产品型的中文名,用于识别与下拉展示', fill: '如:智能电表、断路器、配电柜' },
{
name: '编码',
source: '系统自动生成 + 可手动修改。新建时会自动带出(格式 PROD-YYYYMMDD-序号),你可直接使用或改为自定义编码;编辑时保留已存值。一个产品编码可对应多个工单(同一型号今天做一批、明天做一批,工单号不同,产品编码相同)。',
purpose: '产品唯一编码。它是 MES 内部识别该产品的标识,决定该产品的物料清单(BOM)内容,也是工单、备料、拧紧、追溯的挂靠键。',
fill: '建议用有意义的编码,如 METER-01。要点:①编码与 WMS 是两套系统、互相解耦,MES 这边独立维护,WMS 那边各自单独录入;②成品入库时,由操作人员把本编码**手动录入 WMS**,两系统靠人工对;③如产品编码就是"产品型",则直接沿用该类型编码即可;④建好后不要随意改,否则下游工单/追溯的关联会断。'
fill: '建议用有意义的编码,如 METER-01。要点:①编码主数据以 WMS(库房) 为单一来源,本系统实时从 WMS 拉取物料/产品档案;WMS 不可达时允许手填、仅提示不强校验;②成品完工后系统自动生成 SN 并回流 WMS 入库,无需人工对;③如产品编码就是"产品型",则直接沿用该类型编码即可;④建好后不要随意改,否则下游工单/追溯的关联会断。'
},
{ name: '类别', source: '手工填写。可选,无上游来源。', purpose: '产品所属大类,便于分类统计', fill: '如:计量表 / 开关柜;可空' },
{ name: '启用', source: '开关选择。默认开启。', purpose: '启用后才允许在新建工单/备料的下拉里被选到', fill: '默认开启;暂时停产的可关闭(不删除,保留档案)' },
@@ -23,15 +23,16 @@ export const helpProductType = {
export const helpWorkOrder = {
title: '工单管理(新建 / 编辑 / 删除工单)',
overview:
'工单 = 一个"合同/生产批次"的唯一载体,是生产执行和仓库出库挂靠的核心对象。\n\n全流程:先有产品型 → 建工单(选产品型、定数量、勾选工位组合) → 进"物料清单"给该产品配料 → 到"日排产"排哪天产多少 → 仓库按排产备料出库 → 产线装配/拧紧/报工 → 完工。\n工单号会贯穿 备料单、拧紧查询、手动报工、工件追溯、操作日志 全链路。\n\n查询:支持按 工单号 / 产品编码 / 产品名称(模糊) / 状态 组合筛选。\n删除:仅「已创建 / 待排产 / 已发布」且无排产、备料、生产数据的工单可删除(操作列「删除」),生产中或已完成的工单不可删除。',
'工单 = 一个"合同/生产批次"的唯一载体,是生产执行和仓库出库挂靠的核心对象。\n\n全流程:先有产品型 → 建工单(选产品型号、选定 BOM、定数量、勾选工位组合) → 进"物料清单"给该产品配料 → 到"日排产"排哪天产多少 → 仓库按排产备料出库 → 产线装配/拧紧/报工 → 完工(成品 SN 系统自动生成,并自动回流 WMS 入库为"成品"品类)。\n工单号会贯穿 备料单、拧紧查询、手动报工、工件追溯、操作日志 全链路。\n\n查询:支持按 工单号 / 产品编码 / 产品名称(模糊) / 状态 组合筛选;列表有 BOM 列显示各工单选用的 BOM 名称。\n删除:仅「已创建 / 待排产 / 已发布」且无排产、备料、生产数据的工单可删除(操作列「删除」),生产中或已完成的工单不可删除。',
sections: [
{
title: '工单基本信息',
fields: [
{ name: '工单号', source: '系统自动生成(WO+时间戳),可手工改。新建时自动带出。', purpose: '唯一标识一个工单,备料/出库/报工/追溯都挂在此号下', fill: '一般不用改;如改动须保证唯一' },
{ name: '产品型', source: '下拉选择。数据来自"产品型"页面已启用的记录。', purpose: '说明这批生产的是什么产品,并决定物料清单内容', fill: '先到"产品型"页面建好记录再选择' },
{ name: '产品编码', source: '手工填写。通常与所选产品类型的编码一致。', purpose: '产品唯一编码,用于展示与追溯', fill: '如 METER-01,与产品类型编码对齐' },
{ name: '产品名称', source: '手工填写。通常与产品类型名称一致。', purpose: '产品中文名,用于展示', fill: '如 智能电表' },
{ name: '产品型', source: '下拉选择。数据来自"产品型"页面已启用的记录。', purpose: '说明这批生产的是什么产品,并决定物料清单内容', fill: '先到"产品型"页面建好记录再选择' },
{ name: 'BOM 名称', source: '下拉选择。按所选产品编码实时拉取该型号下并存的 BOM(显示名称+料数),可输入新名创建。', purpose: '本工单选用哪一份 BOM;后续备料算料、装机绑定校验都锁定这一份,不同厂家料单互不串', fill: '一般选「默认」或对应厂家的料单名;不选则用「默认」' },
{ name: '产品编码', source: '手工填写。通常与所选产品型号的编码一致。', purpose: '产品唯一编码,用于展示与追溯', fill: '如 METER-01,与产品型号编码对齐' },
{ name: '产品名称', source: '手工填写。通常与产品型号名称一致。', purpose: '产品中文名,用于展示', fill: '如 智能电表' },
{ name: '数量', source: '手工填写整数。', purpose: '本工单生产总数量(合同台数),决定需求量与排产上限', fill: '整数 ≥1,如 100' },
{ name: '工位组合', source: '勾选 12 个工位(工位1~工位12)。', purpose: '本工单要经过的工位集合,PLC 按此组合下发控制产线', fill: '勾选要经过的工位即可,系统自动按 1→12 顺序执行(传送带不回走);半成品再上线可只勾漏做的工位' },
{ name: '状态', source: '新建时选"已创建",后续由流程推进。', purpose: '工单生命周期:创建→发布→生产→完成', fill: '新建时选"已创建";也可在列表操作列点「状态」快捷流转(发布/开工/完工)' }
@@ -64,9 +65,10 @@ export const helpDailyPlan = {
export const helpBom = {
title: '物料清单(产品 BOM',
overview:
'物料清单 = 生产 1 台该产品需要哪些物料、各用多少。\n按产品编码维护:同型号产品今天做一批、明天做一批,工单号不同、产品编码相同,共用这一份 BOM。\n仓库(库房)按工单取其产品的 BOM 计算备料/出库需求量,并强约束累计出库 ≤ 需求总量。\n\n与 WMS 的关系:本页(MES)只维护「产品由哪几种料、各用几个」;每种物料叫什么、规格、是精密件(SN)还是结构件(批次)、库存有多少,统一在 WMS(库房)的「物料档案」里维护,两套系统互相解耦、通过物料编码对齐。\n\n编码对应规则:本页的「物料编码」必须与 WMS 物料档案里的「编码」完全一致;「管理方式」也要对应(精密件=SN 逐件,结构件=批次)。编码对不上,WMS 将无法为对应工单备料/出库。\n\n数据链路:先建「产品型」→ 到本页选产品编码,为它逐条添加物料 → 之后仓库才能为对应工单领料。',
'物料清单 = 生产 1 台该产品需要哪些物料、各用多少。\n按产品编码 + BOM 名称」维护:同一产品编码可并存多份 BOM(选用制)——不同厂家供货、含半成品的结构差异,都用不同的 BOM 名称区分(缺省叫「默认」,不用 V1/V2 版本号)。\n工单建单时选定其中一份,之后该工单的备料算料、装机绑定校验都锁定这份 BOM,不同厂家的料单互不串。\n\n与 WMS 的关系:本页(MES)只维护「产品由哪几种料、各用几个」;每种物料叫什么、规格、是精密件(SN)还是结构件(批次)、库存有多少,统一在 WMS(库房)的「物料档案」里维护,两套系统互相解耦、通过物料编码对齐。\n\n编码对应规则:本页的「物料编码」必须与 WMS 物料档案里的「编码」完全一致;「管理方式」也要对应(精密件=SN 逐件,结构件=批次)。编码对不上,WMS 将无法为对应工单备料/出库。\n\n保护规则:某份 BOM 一旦被工单选用过,就不允许再从中移除物料(防止历史工单追溯断链);新建/改名的 BOM 名称在本页「BOM 名称」下拉直接输入即可创建。\n\n数据链路:先建「产品型」→ 到本页选产品编码 + 命名 BOM,逐条添加物料 → 建工单时选定 BOM → 仓库才能为对应工单领料。',
fields: [
{ name: '产品编码', source: '下拉选择。来自「产品类型」里建的编码。', purpose: '要为哪个产品配置物料清单', fill: '在查询区或「添加物料」弹窗里选择产品编码' },
{ name: 'BOM 名称', source: '下拉选择/输入(可搜索,输入新名即创建)。缺省「默认」。', purpose: '同一产品编码下多份 BOM 的区分名,工单建单时按此选定', fill: '如「默认」「A厂料单」「含半成品」;同一型号下名称唯一' },
{ name: '产品编码', source: '下拉选择。来自「产品型号」里建的编码。', purpose: '要为哪个产品配置物料清单', fill: '在查询区或「添加物料」弹窗里选择产品编码' },
{ name: '物料编码', source: '手工填写。必须与 WMS(库房) 物料档案的编码一致。', purpose: '该物料在库房的全库唯一编码,两系统靠它关联', fill: '如 螺丝=GJ-LUOSI-M16;编码对不上 WMS 将无法备料' },
{ name: '物料名称', source: '手工填写。', purpose: '物料中文名,便于识别', fill: '如 十字螺丝、主控芯片' },
{ name: '规格', source: '手工填写。', purpose: '物料规格型号', fill: '如 M16×80 / SMT-48脚' },
@@ -101,39 +103,42 @@ export const helpMaterial = {
}
export const helpPlc = {
title: '工位组合下发(业务说明',
title: '工位组合下发(下发录入 / 下发记录',
overview:
'这个菜单做什么用:把某工单/工件的「工位组合」写入西门子 S7-1214 PLC,产线传送带据此只停靠勾选的工位,其余工位不加工。\n\n什么时候用:一个工件进线/上线时,需要告诉 PLC「这件货要走哪几个工位」,就在这里下发。\n\n为什么单独一个菜单:产线偶尔需要人工干预——比如本该走 3 号工位却做成了半成品,人工在此改成只补第 2 工位重上线,完成闭环。一切交给人工自行判断。\n\n核心约束:系统遵循「上一条未收到完成信号,不下发下一条」,确保产线不串序。\n\n数据链路:工单(含工位组合) → 本页下发到 S7-1214 → PLC 驱动传送带/工位 → 收到完成信号再下发下一条。',
'这个菜单做什么用:把某工单/工件的「工位组合」写入西门子 S7-1214 PLC,产线传送带据此只停靠勾选的工位,其余工位不加工。\n\n页面分两个页签:「下发录入」(默认打开)、「下发记录」(点击才加载,可按工单号/状态筛选)。\n\n操作流程:选工单号 → 下拉选出该工单已上线未完工的工件 SN(也可扫码/手输) → 系统按工件实际进度自动带出「当前工位」(只读) → 工位组合中 ≤ 当前工位的编号视为已完成,自动剔除且禁选 → 勾选剩余要走的工位 → 下发。\n\n为什么单独一个菜单:产线偶尔需要人工干预——比如本该走 3 号工位却做成了半成品,人工在此只勾剩余工位重上线,完成闭环。\n\n核心约束:系统遵循「上一条未收到完成信号,不下发下一条」,确保产线不串序。\n\n数据链路:工单(含工位组合) → 本页下发到 S7-1214 → PLC 驱动传送带/工位 → 收到完成信号再下发下一条。',
fields: [
{ name: '工单号', source: '下拉选择/输入。来自工单。', purpose: '当前生产的工单,追溯依据', fill: '选择或输入工单号' },
{ name: '工件SN', source: '扫码枪扫描。来自工件条码。', purpose: '当前流经的工件唯一序列号', fill: '扫码枪扫入;可空(按工单整体下发)' },
{ name: '当前工位', source: '手动填写。', purpose: '当前要下发的工位(1~12)', fill: '输入 1~12 的整数' },
{ name: '工位组合', source: '勾选 12 个工位。通常与工单的工位组合一致。', purpose: '该工件要经过的工位,PLC 控制停靠', fill: '勾选即可,按工位号顺序执行' }
{ name: '工单号', source: '下拉选择/输入。来自工单。', purpose: '当前生产的工单,选中后带出该工单可下发的工件 SN', fill: '选择或输入工单号' },
{ name: '工件SN', source: '下拉选择(该工单已上线未完工的 SN,可搜索),也可扫码枪扫入手输。', purpose: '当前流经的工件唯一序列号', fill: '优先下拉选已上线 SN;扫码手输时须是已上线的工件才能带出当前工位' },
{ name: '当前工位', source: '自动带出(只读)。按所选工件的实际生产进度识别。', purpose: '从哪一站开始继续下发', fill: '无需填写;未带出说明工件未上线或 SN 有误' },
{ name: '工位组合', source: '勾选 12 个工位;≤当前工位的编号已禁选(视为完成)。', purpose: '该工件要经过的工位,PLC 控制停靠', fill: '勾选剩余要走的工位即可,按工位号顺序执行' }
]
}
export const helpTorque = {
title: '拧紧数据(查询/录入',
title: '拧紧数据(补录 / 记录查询)',
overview:
'接收丹尼科尔拧紧工具的采集结果(扭矩/角度/时间/结果/操作人),用于质量追溯。\n数据在工位终端点"工位完成上报"后由拧紧枪数据同步到 MES本页可查询,也可手工补录。',
'接收丹尼科尔拧紧工具的采集结果(扭矩/角度/时间/结果/操作人),用于质量追溯。\n\n页面分两个页签:「拧紧补录」(默认打开) 补录设备漏传/手工修正的历史数据;「记录查询」(点击才加载) 按 SN / 工单号(均不区分大小写) 查询拧紧记录。\n\n实时采集不在本页:数据在工位终端/PLC 报工时由拧紧枪自动同步到 MES本页补录仅用于设备漏传或手工修正历史,补录记录操作人自动标记「(补录)」并写入操作日志。',
fields: [
{ name: 'SN', source: '扫码枪/手工。来自工件条码。', purpose: '被拧紧的工件唯一序列号', fill: '扫码枪扫描' },
{ name: '工单号', source: '自动带出/选择。来自工单。', purpose: '该工件所属工单', fill: '选择工单号' },
{ name: '工位', source: '手填写。', purpose: '拧紧发生在哪道工位', fill: '如 3' },
{ name: '扭矩', source: '拧紧枪自动采集(丹尼科尔工具)。', purpose: '实际拧紧扭矩(N·m),判定是否达标', fill: '工具自动带出;补录时手填' },
{ name: '角度', source: '拧紧枪自动采集。', purpose: '实际旋转角度(°),判定滑牙/屈服', fill: '工具自动带出;补录时手填' },
{ name: '操作人', source: '登录账号自动带出。', purpose: '执行拧紧的人,用于追溯', fill: '默认当前登录用户,可改' }
{ name: '工单号 / SN', source: '补录必填,手工填写。', purpose: '补录记录挂靠的工单与工件', fill: '设备漏传时补填对应工单号与 SN' },
{ name: '工', source: '手工填写。', purpose: '拧紧发生在哪道工位', fill: '如 5,可空' },
{ name: '螺丝号', source: '手填写。', purpose: '同一工件多颗螺丝时区分第几颗', fill: '如 S1,可空' },
{ name: '扭矩(N·m) / 角度(°)', source: '正常由拧紧枪自动采集;补录时手工填写。', purpose: '实际拧紧扭矩与旋转角度,判定是否达标', fill: '按实际值填写' },
{ name: '结果', source: '单选 OK/NG。', purpose: '拧紧判定结果', fill: '默认 OK' },
{ name: '补录原因', source: '手工填写,必填。', purpose: '说明为何补录,留痕审计', fill: '如:设备漏传 / 手工修正' },
{ name: '查询(SN / 工单号)', source: '「记录查询」页签筛选条件,不区分大小写。', purpose: '只看指定工件/工单的拧紧记录', fill: '可空=全部' }
]
}
export const helpScan = {
title: '手动报工(工位工序步骤完成上报)',
overview:
'每个工位完成本工位的工序步骤后,在【手动报工】页选择工位、扫入工件SN,系统该工位「启用」工艺流程自动展开其工序步骤(扭矩/角度/尺寸等采集项),人工录入提交。\n提交后写报工实绩 + 步骤数据,系统按步骤考核标准自动判定 OK/NG。\n\n数据链路:工艺流程(为工位维护工序步骤考核标准) → 手动报工页选工位扫SN 自动载入该工位工序步骤 → 逐参数录入 → 判 OK/NG → 工件追溯可见。',
'页面分两个页签:「报工录入」(默认打开)、「报工记录」(点击才加载,分页)。\n\n录入流程:选择工位、扫入/输入工件 SN,系统自动载入该工位「启用」工艺流程工序步骤(扭矩/角度/尺寸等采集项),逐参数录入提交提交后写报工实绩 + 步骤数据,系统按考核标准自动判定 OK/NG。\n\n装机绑定:若该产品在本工序配置了需绑定的装配物料(BOM「装配工序」),会出现装机绑定区——精密件扫 SN、结构件扫/输批次号,逐项绑齐(已绑/需绑)后才允许提交报工;未配置物料则不校验。\n\n数据链路:工艺流程(工序步骤+考核标准) + BOM 装机配置 → 本页选工位扫 SN 自动载入 → 绑料+录参数 → 判 OK/NG → 工件追溯可见。',
fields: [
{ name: '工位', source: '下拉选择(1~12)。', purpose: '哪个工位在报工,自动带出该工位的工序步骤', fill: '选择工位 1~12' },
{ name: '工件SN', source: '扫码枪扫描。来自工件条码。', purpose: '工件的唯一序列号,报工对象', fill: '扫码枪扫入,触发载入工序步骤' },
{ name: '各步骤采集值', source: '手工填写 或 拧紧枪自动带出(视采集方式)。字段由【工艺流程】的工序步骤人为定义。', purpose: '收集该工位的扭矩/角度/尺寸等参数,按标准判定合格与否', fill: '逐条填采集值,未维护标准的步骤仅记录' }
{ name: '工位', source: '下拉选择(1~12)。', purpose: '哪个工位在报工,选择后自动载入该工位的工序步骤', fill: '选择工位 1~12' },
{ name: '工件SN', source: '扫码枪扫描或手输。来自工件条码。', purpose: '工件的唯一序列号,报工对象', fill: '扫码枪扫入,与工位一起触发自动载入' },
{ name: '各步骤采集值', source: '手工填写 或 拧紧枪自动带出(视采集方式)。字段由【工艺流程】的工序步骤人为定义。', purpose: '收集该工位的扭矩/角度/尺寸等参数,按标准判定合格与否', fill: '逐条填采集值,未维护标准的步骤仅记录' },
{ name: '装机绑定(物料/已绑/需绑)', source: '来自 BOM 的「装配工序」配置(按工单锁定的 BOM 过滤)。', purpose: '该工件本工序应装哪些料;精密件按 SN、结构件按批次绑定,齐套后才允许报工', fill: '在绑定输入框扫码或录入后点「绑定」,绑齐后提交报工' },
{ name: '报工记录查询(SN / 工单号)', source: '「报工记录」页签筛选条件,分页查看。', purpose: '查历史报工实绩', fill: '可空=全部' }
]
}
@@ -255,10 +260,11 @@ export const helpProcessFlow = {
export const helpPerformance = {
title: '绩效报表(工人工作量统计)',
overview:
'按 操作人 × 日期 × 工位 汇总每个工人的完成/合格/NG 数量,用于工作量与绩效统计。\n\n页面提供「按人 / 按工位 / 明细」三个视图切换:按人看每人汇总,按工位看每工位汇总,明细看逐条记录;三者均受上方筛选条件约束,顶部汇总卡为当前筛选的总计。\n\n数据来源:全部由工位终端/手动报工的「工位完成上报」自动写入报工实绩(workpiece_process),本页只读统计,不手工录入。\n\n数据链路:工位终端报工(写报工实绩) → 本页按人/天/工位聚合 → 出报表。',
'按 操作人 × 日期 × 工位 汇总每个工人的完成/合格/NG 数量,用于工作量与绩效统计。\n\n页面提供「按人 / 按工位 / 明细」三个页签:按人看每人汇总,按工位看每工位汇总,明细看逐条记录(含工序名);三个视图各自独立分页,均受上方筛选条件约束。\n\n筛选与导出:支持 操作人 / 工位 / 日期范围 组合筛选(默认近 90 天);顶部汇总卡随查询刷新;「导出 xlsx」一次导出三个 sheet(按人/按工位/明细),导出遵循统一时间硬规则(时间范围为空默认近 3 个月、只传一端报错、跨度超 1 年报错)。\n\n数据来源:全部由工位终端/手动报工的「工位完成上报」自动写入报工实绩(workpiece_process),本页只读统计,不手工录入。',
fields: [
{ name: '操作人', source: '筛选条件。来自报工实绩的 operator 字段(工位终端登录人)。', purpose: '只看某个工人的工作量', fill: '输入姓名/账号,可空=全部' },
{ name: '日期范围', source: '筛选条件。来自报工实绩的产生时间。', purpose: '按时间段统计', fill: '选择起止日期,可空=全部' },
{ name: '工位', source: '下拉选择(工位1~工位12)。', purpose: '只看某个工位的报工情况', fill: '可空=全部工位' },
{ name: '日期范围', source: '筛选条件。来自报工实绩的产生时间,默认近 90 天。', purpose: '按时间段统计', fill: '选择起止日期;导出时同一范围' },
{ name: '完成数', source: '自动汇总。该 操作人×日期×工位 的报工次数。', purpose: '工作量核心指标', fill: '只读' },
{ name: '合格数/NG数', source: '自动汇总。按报工实绩 result 字段(OK/NG)分类计数。', purpose: '质量指标,OK+NG=完成数', fill: '只读' },
{ name: '合格率', source: '自动计算 = 合格数/完成数。', purpose: '质量表现', fill: '只读' }