Files
yanpeng200212 a8890c81e9 新增质量模块(工艺执行书 / 样茧试缫)与报表中心
质量模块:
- 11 张工艺执行书表:封面、试产、选剥茧(含混茧明细)、试缫与大样、煮茧(含分车间配温、副煮车间)、自动缫(含大样)、后缫
- 10 张样茧试缫表:原料小样/综合样主表 + 选茧、解舒、茧幅、切剖、清洁洁净、茧丝百回纤度
- 服务与接口、主控指针回写(列表 √ 标记)、封面编号自增、报表数据包
- 前端 8 张报表打印版式、7 类工艺单据与 6 类调查录入弹窗、字段驱动表单/表格组件
- 菜单种子新增「质量」目录,样茧子表增加 YjssType 判别列,避免原料小样与综合样自增 Id 重号串数据

报表中心:
- 报表模板管理、锐浪 grhtml5 加载与预览、全屏设计面板、数据源 Provider(落丝记录、职工花名册)

其他:同步工作进度 1-11 文档、开发数据库快照、.gitignore 忽略运行日志目录
2026-10-22 10:30:37 +08:00

168 lines
9.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 工作进度-2:报表查询控件体系(Web 版 Page_ReportQueryTool 同构化)
> 时间:2026-10-19(承接工作进度-1)
> 范围:修复报表编辑器 / 报表中心缺陷 + 建立 Web 端「自定义控件注册中心」与「选择页」机制
> 参考实现:WinForms 端 `F9.Common.Report.Pages.Page_ReportQueryTool`、`F9.Common.Report.SelectPages`、`F9GlobalUIHelper`
---
## 一、本轮目标
1. 修复编辑报表页首开报「请求失败」、明细字段 / 模板参数不显示
2. 把 WinForms 端「按 `ControlType` 分发创建控件」的机制,在 Web 端做成**可注册、可扩展的控件模块**
3. 庄口类参数改为**打开选择页**(不再用下拉塞全量数据)
4. 部门控件按**口径**取数(不是一把全量)
5. 修复编辑器「添加参数后看不到新参数」
---
## 二、缺陷修复清单
| # | 现象 | 根因 | 解决 |
|---|---|---|---|
| 1 | 首次进编辑报表报「请求失败」,明细字段 / 模板参数暂无数据 | `GET /sys/report/{id}/template` 返回**裸 .grf JSON**(无 `ApiResult` 包装),`request.js` 拦截器强制 `data.code === 200` → 判失败 → 前端兜底空模板 | 拦截器放行非 ApiResult 响应(`!('code' in data)` 时原样返回) |
| 2 | 报表中心点击后**整页空白** | `select/index.js` 写了 `export { F9SelectPage } from './F9SelectPage.vue'`;**.vue 只有默认导出** → `SyntaxError` → vue-router 导航抛错 → 白屏 | 先 `import` 再具名导出 |
| 3 | 编辑器「添加参数后看不到新参数」 | `.left` 用 `max-height: calc(100% - 320px)` + 内层 `overflow`,两层滚动把新卡片截在可视区外 | 改「tab 头固定 + 内容区独立滚动」;`addParm` 后 `scrollIntoView` |
| 4 | 前缫车间控件列出**全部 38 个部门** | 部门控件直接 `GET /sys/department` 全量,未实现 F9 的口径过滤与建树 | 新建 `utils/departments.js`(Web 版 `F9GlobalUIHelper`) |
| 5 | 落丝记录庄口用下拉塞 1000 条 | 原实现 `pageSize:1000` 拉全量 | 改为打开「工艺庄口选择页」 |
---
## 三、Web 自定义控件模块
WinForms 端结构:
```
GetParamControl(prm)
├─ ControlType 以 "F9" → GetParamControlOfF9(...) // 业务选择页 / 业务下拉
└─ ControlType 以 "AntdUI" → GetParamControlOfAntdUI(...) // 基础控件
→ 每个分支创建控件 + 注册取值函数 _paramGetValudFuncs
```
Web 端同构为「**控件定义注册中心 + 统一渲染组件**」:
| 文件 | 说明 | 对应 WinForms |
|---|---|---|
| `web/src/utils/gridreport/controls/registry.js` | `registerControl / getControlDef / groupedControlOptions / resolveControlDef / fallbackDef` + 取值工具(`toOptions / apiOptions / registryOptions / pickRows / rowLabel`) | `_paramGetValudFuncs` |
| `web/src/utils/gridreport/controls/antdControls.js` | 一个 type 一个函数 + `ANTD_BUILDERS` 分发 | `GetParamControlOfAntdUI` |
| `web/src/utils/gridreport/controls/f9Controls.js` | 顶部注入数据源,一个 type 一个函数 + `F9_BUILDERS` 分发 | `GetParamControlOfF9` |
| `web/src/utils/gridreport/controls/index.js` | 装配注册两组控件;`parseStaticDs / fetchServiceDs / loadParamOptions` | `GetParamControl` |
| `web/src/components/report/F9ParamControl.vue` | 统一渲染(input / select / multiselect / date / yearmonth / year / picker / 树形下拉) | 控件实例 |
| `web/src/utils/departments.js` | 部门口径 + 建树 + 默认选中 | `F9GlobalUIHelper` |
**已注册控件 38 个**(6 个 AntdUI + 32 个 F9),编辑器「控件类型」下拉按 group 分组自动列出。
### kind 映射与取值口径
| Web kind | 渲染 | F9 对应 | 取值 |
|---|---|---|---|
| `input` | el-input | `AntdUI.Input` | 文本 |
| `select` | el-select / **el-tree-select**(`tree: true`) | `AntdUI.Select`、各 `F9-*-SELECT` | key(部门为 Id) |
| `multiselect` | el-select multiple | `AntdUI.SelectMultiple`、`F9-WMS-SS-PICI-KCSTATUS` | `"a,b,c"`(对齐 `string.Join(",")`) |
| `date` / `yearmonth` / `year` | el-date-picker | `AntdUI.DatePicker*` | `YYYY-MM-DD` / `YYYY-MM` / `YYYY` |
| `picker` | 只读框 + 选择按钮 → 选择页 / 远程搜索 | `ShowModalPage(Page_XXX_Select)` | 记录 **Id** |
| `picker-multiple` | 同上多选 | `F9-GYZK-SELECT-MUTIPLE` | `"1,2,3"` |
选项优先级:`Ds_Static` → `Ds_Service` → 控件 `loader` → 静态 `options`;
picker 优先级:**选择页 `page`** > 内建远程搜索 `search` > 降级文本输入。
新增控件只需两步,无需改页面:
```js
registerControl({
type: 'F9-MY-SELECT', kind: KIND.SELECT, group: 'F9 自定义', label: '我的选择',
loader: async () => [{ key: '1', value: '选项一' }],
});
```
---
## 四、选择页机制(对应 F9.Common.Report.SelectPages)
| 文件 | 说明 |
|---|---|
| `web/src/components/select/F9SelectPage.vue` | 通用选择页:过滤条件(变更即重查)+ 关键字 + 分页表格 + 单选/多选 + 未选校验 —— 对应 `F9ModalPageUserControl_Medium` + `f9AntdUITable` 的 `QueryData` / `ValidCustom` |
| `web/src/components/select/CraftZhuangKouSelect.vue` | 工艺庄口选择页 —— 对应 `Page_CraftZhuangKou_SelectV2`(庄口编号 / 名称 / 产地 / 排序 / 备注 / 年度,年度过滤,`GET /api/craftzhuangkou`) |
| `web/src/components/select/index.js` | 选择页注册中心 `registerSelectPage / getSelectPage` —— 对应 `ResolvePage<T>()` |
复用方式:
```vue
<CraftZhuangKouSelect v-model="visible" @confirm="onPicked" /> <!-- 业务页面 -->
{ type: 'F9-GYZK-SELECT', kind: KIND.PICKER, page: 'CraftZhuangKou', valueField: 'id', labelField: 'productionDisplayName' } <!-- 报表控件 -->
```
已落地:**落丝记录(lsjl)庄口**改为打开选择页;`F9-GYZK-SELECT` / `F9-GYZK-SELECT-MUTIPLE` 绑定该页。
---
## 五、部门口径(Web 版 `F9GlobalUIHelper`)
| F9 方法 / 查询 | Web 实现 |
|---|---|
| `Department_GetAllCacheAsync` | `getAllDeps()`(缓存) |
| `GetDepartmentByDutyTypeWithoutRightQuery(types)` | `depsByDuty()`(只保留自身 DutyType 命中) |
| `GetDepartmentOfSiyeQuery(includeSiye)` | `depsOfSiye()`(丝业中心 + 全部子孙) |
| `GetDepartmentForEmployee/Kaoqin/XinziQuery` | `depsOfLoginUser()`(本部门 + 子孙;管理员=全部)+ `removeCompany()` |
| `Dep_GenerateSelectItems` | `buildDepTree()`(SortOrder → Code → Name,父不在集合内即为根) |
| `Dep_Select_SelectDep(sel, depId)` | `defaultFromUser: true` → 默认选中登录用户部门 |
| 控件 | 口径 | 实测(38 个部门) |
|---|---|---|
| `F9-DEP-QS-SELECT` | DutyType=前缫(25) | 前缫车间#26 → 前缫一~四车间#31-34 |
| `F9-DEPARTMENT_SIYE` | 丝业 | 丝业生产中心#2 + 全部子孙 |
| `F9-DEP-EMPLOYEE-SELECT` / `F9-DEP-XZ-SELECT` / `F9-DEPARTMENT_KAOQIN` | 职工 / 薪资 / 考勤(默认登录部门) | 管理员=全部,否则本部门+子孙 |
| `F9-DEP-ALL-SELECT`(新增) | 全部 | 完整部门树 |
lsjl 车间下拉同步改为 `depOptions({ duty: [DUTY.前缫] }, { flat: true })`,替换原 `name.includes('前缫')`。
---
## 六、交互与布局修复(编辑器)
```css
.left { display: flex; flex-direction: column; overflow: hidden; }
.left :deep(.el-tabs) { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.left :deep(.el-tabs__header) { flex: 0 0 auto; }
.left :deep(.el-tabs__content) { flex: 1 1 auto; min-height: 0; overflow: auto; }
.config-src { flex: 0 0 auto; }
```
`addParm()` 后 `activeLeftTab = 'params'` + `nextTick` 滚动到最后一张卡片(实测:连续添加 5 个后 `LAST_VISIBLE=YES`)。
---
## 七、调试方法(本轮建立的验证手段)
无 Node/npm 环境,用无头 Edge 验证 SPA 运行时:
```powershell
# 1) 临时诊断页 web/public/__diag.html:登录写 localStorage → iframe 打开目标页 → 模拟点击 → 输出 DOM 断言
# 2) 抓控制台
msedge --headless=new --virtual-time-budget=45000 --enable-logging=stderr --v=1 --dump-dom "http://localhost:5173/__diag.html"
```
用该方法定位了 #2(白屏 SyntaxError)与 #3(滚动)等问题;诊断页用完即删。
另:动态 `import('/src/utils/departments.js')` 可在诊断页内直接单测模块逻辑(验证部门口径即用此法)。
---
## 八、当前状态
| 项 | 状态 |
|---|---|
| 报表中心(树 + 查询面板 + 多 Tab 预览) | 正常,切换报表参数随报表切换 ✅ |
| 报表管理 / 全屏编辑器 | 正常(配置/参数/设计/源码/预览)✅ |
| 自定义控件注册中心 | 38 个控件,编辑器下拉自动分组 ✅ |
| 选择页(工艺庄口) | 报表控件 + lsjl 业务页均已接入 ✅ |
| 部门口径 | 前缫 / 丝业 / 职工 / 考勤 / 薪资 / 全部 ✅ |
| 落丝记录庄口 | 改为选择页 ✅ |
## 九、遗留与后续建议
1. **部门缓存**:`getAllDeps()` 有内存缓存,部门增删后需 `clearDepCache()`(可在部门管理保存后调用)
2. **选择页覆盖**:职工 / 物资目录目前用内建远程搜索弹窗,如需与 F9 一致的选择页可再注册 `EmployeeSelect` / `WuziMuluSelect`
3. **Web 端无对应接口的 F9 控件**:样茧试缫(`F9-QC-YJSS-*`)、生丝批次枚举(`SSPiciKucunStatusEnum` 等)走注册表或 `Ds_Static`,界面上有降级提示
4. **picker 取 Id**:报表 Provider 需按 Id 解析参数(庄口 / 职工 / 物资均为 Id)
5. **规范**:新增 `.vue` 再导出必须 `import X from './X.vue'` 后具名导出,禁止 `export { X } from './X.vue'`