136 lines
12 KiB
Markdown
136 lines
12 KiB
Markdown
# F9 智慧缫丝系统 —— CodeBuddy 持续工作存档
|
||
|
||
> 本文件为 CodeBuddy 开发日志归档(每日一份),归档日期:2026-08-15。
|
||
> 新对话开始后:先读本文件 + `功能清单` + `项目说明`,按「任务状态」继续推进,无需重新调研。
|
||
|
||
最后更新:2026-08-15
|
||
|
||
---
|
||
|
||
## 一、任务状态总览(按用户约定的优先级 1→2→3)
|
||
|
||
| 序号 | 任务 | 状态 | 说明 |
|
||
|---|---|---|---|
|
||
| 1 | 通用打印接入主前端 | 🔄 **进行中(方案已定,代码未写)** | 三步:后端取行数据接口 → openprint 外部打印模式 → web 打印按钮 |
|
||
| 2 | 简易工作流(采购/领料审批闭环) | ⏳ 待做 | 4 张表已有,缺服务+API+前端审批 UI |
|
||
| 3 | 专业业务逻辑(自动定级/能耗分摊/成本盈亏/断料预警) | ⏳ 待做 | 依赖任务 1/2 部分能力 |
|
||
|
||
已完成的里程碑:
|
||
- ✅ 动态 CRUD 体系(后端 EntityCatalog + CrudService + DataController,前端 CrudPage + table-map 配置驱动)
|
||
- ✅ openprint 打印设计器全链路(模板设计→数据源内省→预览/打印,推 PDF 到本地客户端)
|
||
- ✅ 工作台接真实数据(WorkBenchController + workbench/index.vue 重写)
|
||
|
||
---
|
||
|
||
## 二、项目架构速查
|
||
|
||
### 2.1 三端结构
|
||
| 端 | 目录 | 技术栈 | 端口 | 说明 |
|
||
|---|---|---|---|---|
|
||
| PC 前端 | `web/` | Vue3 + Element Plus + ECharts + Pinia | vite dev 5173 | 代理 `/api` → localhost:5136 |
|
||
| 后端 | `server/` | .NET 10 + FreeSql (v3.5.311) | 5136 | MySQL 云库 `f9web`(116.198.221.105) |
|
||
| 打印设计器 | `openprint/` | Vue3 + Naive UI + Vite | 5227 | 对接 F9 的 `PrintApiController`,推 PDF(base64) 到本地客户端 `127.0.0.1:18888` |
|
||
| 电视大屏 / 小程序 | — | — | — | 未开始(按项目说明先完成 PC 端) |
|
||
|
||
### 2.2 后端关键约定
|
||
- **表命名**:模块前缀 + 下划线,如 `CRM_Customer`、`RawMaterial_Instock`、`Common_Workflow`、`RepCenter_ReportDesign`;实体类同前缀,如 `RawMaterial_Instock`。
|
||
- **默认字段**:`id`、`flag`(0=删除,>0 有效,<0 无效,-1=作废)、`addtime`、`adder`、`updatetime`、`updater`、`memo`。
|
||
- **序列化**:`Program.cs` 全局 CamelCase + 忽略 null(即 C# 属性 `OrderNo` → JSON `orderNo`)。
|
||
- **响应信封**:普通 API 用 `ApiResult`;**`PrintApiController`(`api/print`)返回裸 JSON** `{items,total}`(openprint 的 http-client 已按此解析,主前端 axios 也可透传)。
|
||
- **动态查询**:`DataController` 用 `EntityCatalog`(表名→实体 Type 反射映射)+ `CrudService<T>` 泛型反射调用,`GetList/GetById/Add/Update/Delete` 等通用接口。
|
||
- **工作流表**(已有,未做服务):`Common_Workflow`(流程定义)/ `Common_WorkflowNode`(节点)/ `Common_WorkflowInstance`(实例)/ `Common_WorkflowTask`(任务,`Status==0` 待办、`UserId` 当前处理人)。
|
||
|
||
### 2.3 web 前端关键约定
|
||
- **Token 存储**:localStorage key = **`f9mes_token`**(`web/src/stores/user.js` 的 `TOKEN_KEY`)。
|
||
- **API 封装**:`web/src/api/request.js`(axios 拦截器注入 Bearer);`web/src/api/index.js` 集中导出(含已新增的 `getWorkBenchSummary`)。
|
||
- **配置驱动 CRUD**:`web/src/config/table-map.js` 定义每张表的列/表单配置,`web/src/components/CrudPage.vue` 是通用页面组件,菜单由 `InitDataService` 生成。
|
||
|
||
### 2.4 openprint 关键约定
|
||
- **对接开关**:`openprint/src/main.ts` 仅当配置 `VITE_OPENPRINT_API_BASE` 时才切换云端仓库(HttpRepository/HttpDataSource);`.env` 中配 `VITE_OPENPRINT_API_BASE` + `VITE_OPENPRINT_API_TOKEN`。
|
||
- **HttpClient token**:构造时静态传入(`http-client.ts` 的 `HttpOptions.token`),**构造后不可变**;若改运行时 token 需改构造时机或加 setter。
|
||
- **绑定 Path 约定**:后端 `PrintService.BuildFields` 生成 `Path = "{TableId}.{PropName}"`(如 `RawMaterial_Instock.OrderNo`);openprint 的 `expression.ts`/`data-binder.ts` 按路径取值。**注意**:序列化后 JSON 为 camelCase,而 Path 是 PascalCase,取值器需兼容(大小写不敏感取 key 或按 camelCase 注入)。
|
||
- **打印出口**:`PrintDialog.vue` 的 `doPrint()`:`store.buildTemplate()` + `buildPreviewData(dsStore.activeFields)` → `buildPrintPayload({template, data})` → 推本地客户端(POST `/print`,`127.0.0.1:18888`)。**当前用假数据**,是接入真实数据的关键改造点。
|
||
- **数据源内省**:`PrintApiController` 的 `data-sources`/`fields` 由 `PrintService` 按实体类前缀分组(ModuleNames 字典),字段缓存 TTL 10 分钟。
|
||
|
||
---
|
||
|
||
## 三、任务 1:通用打印接入主前端(进行中)
|
||
|
||
### 3.1 目标
|
||
表单通用打印:主前端任意 CRUD 列表 → 选中一行 → 选打印模板 → 打开 openprint 用**该行真实数据**打印(针式/A4 均支持,设计器已具备)。
|
||
|
||
### 3.2 已锁定的三步方案(代码未写,按序实施)
|
||
|
||
**Step A — 后端:取行数据接口**
|
||
- 位置:`PrintApiController.cs` 新增(或新 controller),路由建议 `GET api/print/data/{table}/{id}`。
|
||
- 实现:基于 `EntityCatalog` 动态取实体 Type → FreeSql 按 `id` 查询单行 → 输出结构匹配绑定 Path:`{ "<TableId>": { "<camelCaseProp>": value, ... } }`(如 `{ "rawMaterial_Instock": { "orderNo": "...", ... } }` 或 PascalCase 表名,需与 PrintService.BuildFields 生成的 Path 前缀一致,建议直接复用 BuildFields 的 TableId)。
|
||
- 返回裸 JSON(同 PrintApiController 风格,走 openprint http-client 的 json() 直接拿对象)。
|
||
|
||
**Step B — openprint:外部打印模式**
|
||
- 解析 URL 参数:`?print=1&template=<templateId>&table=<tableId>&row=<rowId>&token=<token>`。
|
||
- 启动流程(main.ts 或 App.vue):检测 `print=1` 时 → 用 URL 的 token(或 localStorage)替换 HttpClient 的 token → 加载模板(designer store `loadTemplate`)→ 调 `api/print/data/{table}/{row}` 拉真实数据 → 注入到 dataSource store 供 `doPrint` 使用(如新增 `externalData` 状态,`PrintDialog.doPrint()` 优先用它替代 `buildPreviewData`)→ 自动打开打印弹窗。
|
||
- 注意:`designer.ts` 有 `loadTemplate({id,name,data})`/`buildTemplate()`/`setRepository()`/`restoreLastTemplate()`;`dataSource.ts` 的 `activeFields` 决定字段列表;只读模式下应隐藏设计工具栏(TopToolbar 需加 `readonly`/`external` 模式判断)。
|
||
- token:主前端 web 存于 localStorage `f9mes_token`,openprint 与 web 同源部署时可直接读;跨端口时用 URL 传 token 更稳(注意 URL 长度与泄露,内网 MES 可接受)。
|
||
|
||
**Step C — web:CrudPage 打印按钮**
|
||
- `CrudPage.vue` 工具栏加「打印」按钮(选中一行时可用)→ 弹窗列出该表可用模板(调 `api/print/templates` 按 `tableId` 过滤)→ 确认后 `window.open` openprint 打印 URL:`http://localhost:5227/?print=1&template={id}&table={tableName}&row={rowId}&token={token}`。
|
||
- 需要后端提供"按表过滤模板"的能力(`PrintApiController.templates` 若支持 tableId 查询则直接用,否则加参数)。
|
||
|
||
### 3.3 关键文件清单
|
||
- 后端:`server/src/F9MES.Api/Controllers/PrintApiController.cs`、`server/src/F9MES.Application/Print/PrintService.cs`、`server/src/F9MES.Api/Common/EntityCatalog.cs`、`server/src/F9MES.Api/Controllers/DataController.cs`
|
||
- openprint:`src/main.ts`、`src/App.vue`、`src/config/backend.ts`、`src/repository/http-client.ts`(token 构造点)、`src/design/stores/designer.ts`(loadTemplate)、`src/design/stores/dataSource.ts`、`src/design/modals/PrintDialog.vue`(doPrint)、`src/design/toolbar/TopToolbar.vue`(showPrint 挂载)、`src/design/preview/preview-data.ts`(buildPreviewData)、`src/core/layout-engine/expression.ts` + `data-binder.ts`(取值)
|
||
- web:`src/components/CrudPage.vue`、`src/api/index.js`、`src/config/table-map.js`、`src/stores/user.js`(token)
|
||
|
||
---
|
||
|
||
## 四、任务 2:简易工作流(待做)
|
||
|
||
- 现状:4 张表(Common_Workflow/Node/Instance/Task)已有,`WorkBenchController` 已统计 `Common_WorkflowTask`(Status==0 && UserId==当前用户)为待办。
|
||
- 要做:
|
||
1. 后端:工作流服务(流程定义 CRUD、节点配置、发起实例、提交/审批/驳回/撤回流转)、API(建议 `api/workflow/...`)。
|
||
2. 前端:审批中心页面(我的待办、我发起的、流程配置);在采购单、领料申请等表单接审批。
|
||
3. 关联:任务 1 打印对审批单据同样适用。
|
||
|
||
---
|
||
|
||
## 五、任务 3:专业业务逻辑(待做)
|
||
|
||
按优先级从高到低建议:
|
||
1. **断料预警**(原料库存超期/不足,工作台预警列表已预留位置)
|
||
2. **自动定级**(Lims 检验数据 → 调用定级标准自动判定生丝等级,标准表需先建/已有则复用)
|
||
3. **能耗分摊**(Enms 抄表 → 按投料量/产量/机台时长分摊到庄口 → 推成本)
|
||
4. **成本盈亏**(BizBoss 生产成本分摊 + 分庄口盈亏统计)
|
||
|
||
---
|
||
|
||
## 六、工程实践与坑位(必读)
|
||
|
||
1. **编译锁定**:后端进程运行时 DLL 被锁,`dotnet build` 会报 MSB3027/MSB3021 → 用 `dotnet build -o build_tmp` 验证编译,完成后删临时目录;**改动后端必须重启服务才生效**。
|
||
2. **FreeSql 陷阱**:非空 DateTime 没有 `.HasValue`;空集合时 `.Where(x => ids.Contains(...))` 会生成非法 SQL,需先 `if (list.Count > 0)` 守卫。
|
||
3. **JSON 大小写**:后端全局 camelCase,openprint 绑定 Path 是 PascalCase,取值需兼容。
|
||
4. **openprint 是独立应用**:改动它用 `npm run dev`(端口 5227)独立调试;主前端 web 是 vite dev(5173)。
|
||
5. 数据库连接(项目说明):MySQL `116.198.221.105` 库 `f9web` 用户 `f9web`;阿里云 OSS(bbit-f9-web);天气用 Open-Meteo。
|
||
6. 项目要求:类/文件命名带模块前缀、各模块类放各自文件夹、公共类放 Common;界面 MES 风格、高可配置、表单必须支持打印、表单带简易工作流。
|
||
|
||
---
|
||
|
||
## 七、本轮对话已完成的工作(2026-08 中旬)
|
||
|
||
### 7.1 工作台真实数据(已完成 ✅)
|
||
- 新增 `server/src/F9MES.Api/Controllers/WorkBenchController.cs`:`GET api/workbench/summary`,聚合统计卡(今日产丝=ProHou_Daily.OutputWeight 合计、在线机组=ProQian_Machine 启用且运行、待办=工单+工作流待办、预警数)+ 近 30 天趋势 + 庄口占比 + 待办列表(工单/审批)+ 预警列表。
|
||
- `web/src/api/index.js`:新增 `getWorkBenchSummary`。
|
||
- `web/src/views/workbench/index.vue`:重写,4 统计卡/趋势折线/庄口占比饼图/待办与预警列表全部接真实数据,无数据时占位,保留天气+快捷入口。
|
||
- 已用 `-o build_tmp` 验证编译通过;**需重启后端生效**。
|
||
|
||
### 7.2 openprint 全链路调研(已完成,结论见第三节)
|
||
已通读:PrintApiController / PrintService / EntityCatalog / DataController / http-repo / http-datasource / http-client / backend.ts / main.ts / App.vue / TopToolbar / PrintDialog / designer store / dataSource store / preview-data / expression / data-binder / CrudPage / table-map / request.js / user store / 两端 vite 配置。结论已沉淀到第三节。
|
||
|
||
---
|
||
|
||
## 八、下一步行动(新对话从这里开始)
|
||
|
||
1. 先读本文件 + `功能清单` + `项目说明`(若工作区未加载)。
|
||
2. 按 **3.2 的 Step A → B → C** 依次实施任务 1(打印接入),每步完成后用 `dotnet build -o build_tmp` / `npm run build` 验证,openprint 与 web 可分别 `npm run dev` 联调。
|
||
3. 完成后再推进任务 2(简易工作流)。
|
||
4. 任何大改动前更新本文件「最后更新」日期与任务状态。
|