新增质量模块(工艺执行书 / 样茧试缫)与报表中心

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

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

其他:同步工作进度 1-11 文档、开发数据库快照、.gitignore 忽略运行日志目录
This commit is contained in:
yanpeng200212
2026-10-22 10:30:37 +08:00
parent 8c4c464362
commit a8890c81e9
92 changed files with 14785 additions and 70 deletions
+133
View File
@@ -0,0 +1,133 @@
# 工作进度-8:模板源码在线编辑(免下载 / 上传)
> 时间:2026-10-20(承接工作进度-7)
> 触发:用户提出「能不能直接编辑对应报表的模板文件然后保存,而不是下载 → 改 → 上传 → 保存」
---
## 一、结论
可以。模板本来就以文本存在库里(`sys_report_files.design_content`,TEXT),
之前只是没有「写回文本」的入口,只能整文件上传。本次新增:
- 后端一个接口:`PUT /api/sys/report/{id}/template/content`,请求体 `{ "content": "<模板全文>" }`
- 前端「模板源码」由**只读**改为**可编辑**,配「保存模板 / 格式化 / 撤销修改 / 放大编辑」
原来的「上传 .grf / 下载 .grf」保留不动(用于本机设计器排版、外部模板导入)。
---
## 二、方案取舍
| 方案 | 说明 | 结论 |
|---|---|---|
| 现状:下载 → 本地改 → 上传 | 需要本地装锐浪设计器或文本编辑器,来回一次文件 | 保留,不再作为主路径 |
| **在线编辑模板源码 + 保存** | 文本表单直接改 `.grf` 内容,保存即入库,刷新预览立即生效 | ✅ 本次实现 |
| 内嵌可视化设计器(拖控件、改属性) | 需要对 `.grf` 全量解析 / 回写;GR7 设计器格式是 `_WR` 压缩文本,无解码器 | 不做(见工作进度-5 遗留) |
---
## 三、后端
### 3.1 DTO(`ReportDtos.cs`)
```csharp
public class ReportTemplateContentDto { public string? Content { get; set; } }
```
### 3.2 Service(`IReportService` / `ReportService.SaveTemplateContentAsync`)
```csharp
public async Task<int> SaveTemplateContentAsync(long id, string content)
{
var entity = ... ?? throw new F9NotFoundException("报表不存在");
var text = NormalizeTemplateContent(content); // 去 BOM / trim,空内容拦截
if (head.StartsWith('{') || head.StartsWith('['))
JsonDocument.Parse(text); // JSON 语法校验,失败抛 F9OperationException
await SaveTemplateAsync(entity, text); // 复用「有则更新 ReportFile,无则新建并绑定」
...
return text.Length;
}
```
- 与上传接口走同一套落库逻辑(`SaveTemplateAsync`),因此「新建 / 更新 / 绑定 `report_file_id`」行为一致
- 校验规则:
| 内容形态 | 服务端行为 |
|---|---|
| `{...}` / `[...]`(GR6 JSON 模板) | 语法校验,不合法直接 400「模板 JSON 不合法:…」 |
| `_WR...`(GR7 设计器压缩文本) | 原样保存(无法在服务端校验) |
| 空 / 仅空白 | 400「报表模板内容为空」 |
### 3.3 接口(`SysReportController`)
```
PUT /api/sys/report/{id}/template/content
Body: { "content": "..." }
200 → { code: 200, data: { id, size, hasTemplate: true }, message: "模板已保存" }
404 → 报表不存在 400 → 内容为空 / JSON 不合法
```
与已有接口的关系:
| 方法 | 路由 | 用途 |
|---|---|---|
| GET | `/{id}/template` | 渲染库 / 前端读模板 |
| POST | `/{id}/template` | 上传 .grf 文件(设计器回传) |
| **PUT** | **`/{id}/template/content`** | **在线编辑后保存文本(本次新增)** |
| GET | `/{id}/template/download` | 下载 .grf 给本机设计器 |
---
## 四、前端
### 4.1 `ReportEditor.vue` —— 「模板源码」页
- 去掉 `readonly`;`v-model="templateSource"` 直接编辑
- 新增状态:`templateSaved`(已入库内容,用于判定「未保存」)、`templateSaving`、`wrUnlocked`、`sourceMaximized`
- 工具条:
| 按钮 / 标签 | 行为 |
|---|---|
| `JSON 模板` / `_WR 压缩模板` | 当前模板形态提示 |
| `未保存` | `templateSource !== templateSaved` 时显示 |
| 格式化 | `JSON.parse` + `JSON.stringify(…, '\t')`;非 JSON 禁用 |
| 撤销修改 | 确认后恢复为上次保存内容 |
| 放大编辑 | 整屏弹窗编辑同一份文本(同一 v-model) |
| 保存模板 | 前端先校验 JSON,再 `PUT /sys/report/{id}/template/content` |
- 保存成功后:重新拉取模板 → `hasTemplate = true` → 重置预览(提示点「刷新预览」)→ `emit('saved')`
- 「保存报表」时若模板源码有未保存修改,会先弹确认:`先保存模板` / `忽略模板修改`,避免手改内容被静默丢弃
- `_WR` 压缩模板默认**只读**,需勾「允许编辑」才可改,保存前再二次确认(无本地校验能力)
- 报表未保存时提示「请先保存报表,再编辑模板源码」;已保存但无模板时也可以直接粘贴 JSON 保存(相当于无文件新建模板)
### 4.2 预览缓存
`grhtml5` 拉模板是普通 GET,容易被浏览器缓存。预览 URL 追加 `_t=Date.now()`(编辑器与报表中心都加),保证改完模板点「刷新预览」能看到新内容。
### 4.3 `views/report/manage/index.vue` —— 列表页入口
- 每行新增「编辑模板」:选中该报表并让右侧工作台**直接打开「模板源码」页**(`ReportEditor` 新增 `openSource` prop,配合 `designerKey` 强制重载)
- 「上传模板 / 下载模板」保留
---
## 五、验证
| 项 | 结果 |
|---|---|
| 后端 `dotnet build`(输出到独立目录避开运行中进程锁定) | ✅ 0 错误 |
| `IReportService` / `ReportService` / DTO / Controller 改动 | ✅ 编译通过 |
| 前端 IDE 诊断(`ReportEditor.vue`、`manage/index.vue`、`center/index.vue`) | ✅ 0 诊断 |
| 前端 `npm run build` | ⚠ 当前环境无 node/npm,未执行;需在本机 `cd web && npm run build` 复核 |
> 运行中的 `F9WebAiTest.Api` 仍在用旧程序集,**需重启后端**后新接口才生效。
---
## 六、遗留
1. **无语法高亮 / 行号**:目前是 `el-input textarea`,后续可换 CodeMirror / Monaco(需新增前端依赖)。
2. **无模板历史版本**:手工改坏后无法一键回滚,只能重新「生成模板」或重新上传;建议后续给 `sys_report_files` 加版本表。
3. **`_WR` 仍不能结构化编辑**:需要锐浪的解码 / 编码算法,暂以「允许编辑 + 风险提示」兜底。
4. **保存模板不刷新明细字段 / 报表参数页签**:手改 `DetailGrid.Recordset.Field` 后,左栏字段列表仍是旧值(点「识别明细列与报表参数」可同步)。