49755ef0
李曜臣
6-12代码优化
|
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
```bash
curl -X POST "http://flus-test.3ffoodsafety.com/api/app/us-app-labeling/preview" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"locationId": "550e8400-e29b-41d4-a716-446655440000",
"labelCode": "LBL0001",
"productId": "PROD001",
"baseTime": "2026-05-13T09:00:00"
}'
```
### 响应片段(示例)
```json
{
"labelId": "20260513-3",
"locationId": "550e8400-e29b-41d4-a716-446655440000",
"labelCode": "LBL0001",
"labelLastEdited": "2026-06-01T08:30:09",
"template": { }
}
```
若该门店在 `2026-05-13` 已有 2 条打印记录,预览返回 `20260513-3`;当日首条预览为 `20260513-1`。
|
49755ef0
李曜臣
6-12代码优化
|
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
```sql
SELECT Id, LocationId, PrintedAt, CreationTime
FROM fl_label_print_task
WHERE LocationId = '{locationId}'
AND IFNULL(PrintedAt, CreationTime) >= CURDATE()
AND IFNULL(PrintedAt, CreationTime) < DATE_ADD(CURDATE(), INTERVAL 1 DAY)
ORDER BY IFNULL(PrintedAt, CreationTime), Id;
```
当日行数 + 1 应与 preview 返回的 `-n` 部分一致。
---
|
14afbc16
李曜臣
2026-6-22
|
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
|
## 二、Company 自动生成元素(预览/打印填充)
### 背景
模板编辑器中的 **Company** 控件属于「按门店自动取数」类型。用户点击打印时,后端应:
- **始终**展示当前门店所属 **Company 名称**(`fl_partner.PartnerName`)
- **仅当模板元素 config 中勾选** Address / City / State / Zip / Email 时,才追加对应行;未勾选或库中无值则不展示该字段
勾选状态**不落独立表**,保存在 **`fl_label_template_element.ConfigJson`**(通过 `POST/PUT /api/app/label-template` 的 `elements[].config` 写入)。公司主数据来自 **`fl_partner`**。
> 本次**不提供** Web 属性面板 UI;需通过 **label-template 保存接口** 或 SQL 维护 `config`。
### 元素识别规则
满足以下任一条件即视为 Company 自动生成元素(`PartnerCompanyDisplayHelper.IsCompanyAutoElement`):
| 条件 | 说明 |
|------|------|
| `typeAdd = "auto_Company"` | 标准 Company 控件 |
| `valueSourceType = "AUTO_DB"` 且 `typeAdd` 以 `auto_` 开头且含 `Company` | 兼容命名 |
常见组合:`elementType = "TEXT_STATIC"`,`valueSourceType = "AUTO_DB"`,`typeAdd = "auto_Company"`。
### 模板 config(勾选字段)
写入 `elements[].config`(JSON),支持两种等价写法(可混用):
**方式 A:数组 `companyIncludeFields`**
| 数组值 | 含义 | 数据来源(`fl_partner`) |
|--------|------|--------------------------|
| `address` | 街道地址 | `Street` |
| `city` | 城市 | `City` |
| `state` | 州/省 | `StateCode` |
| `zip` | 邮编 | `ZipCode` |
| `email` | 邮箱 | `ContactEmail` |
**方式 B:布尔开关**
`includeAddress` / `includeCity` / `includeState` / `includeZip` / `includeEmail`(`true` 表示勾选)
**示例(保存模板时)**
```json
{
"elementType": "TEXT_STATIC",
"valueSourceType": "AUTO_DB",
"typeAdd": "auto_Company",
"name": "Company",
"config": {
"companyIncludeFields": ["address", "city", "state", "zip", "email"]
}
}
```
或:
```json
"config": {
"includeAddress": true,
"includeCity": true,
"includeState": true,
"includeZip": true,
"includeEmail": false
}
```
### 展示文本格式
后端将解析结果写入 **`template.elements[].config.text`**(多行,`\n` 分隔):
| 行序 | 内容 | 规则 |
|------|------|------|
| 第 1 行 | 公司名 | **固定输出**(有 `PartnerName` 时) |
| 第 2 行 | 街道 | 仅勾选 `address` 且 `Street` 非空 |
| 第 3 行 | 城市, 州, 邮编 | 勾选 city/state/zip 中任一项时,按「City, StateCode, ZipCode」逗号拼接(空段跳过) |
| 第 4 行 | 邮箱 | 仅勾选 `email` 且 `ContactEmail` 非空 |
**渲染示例**
```
Acme Foods Inc
123 Main Street
New York, NY, 10001
sales@acme.com
```
若仅勾选公司名(无任何 include),则 `text` 仅一行公司名。
### 门店 → Company 解析
1. 入参 **`locationId`**(`location.Id`,Guid 字符串)
2. 查 `location` 表取 **`Partner`** 字段
3. 在 **`fl_partner`** 中按 **`Id = Partner`** 或 **`PartnerName = Partner`** 匹配(未删除)
4. 匹配失败时不抛错,`config.text` 保持原样(不填充)
### 入参要求
| 场景 | `locationId` |
|------|----------------|
| 模板**不含** Company 自动生成元素 | 可选(App preview 仍必填门店,与原有逻辑一致) |
| 模板**含** Company 自动生成元素 | **`LabelPreviewResolveInputVo.locationId` 必填**;缺失返回 **400**:`预览/打印需要 locationId 以填充 Company 信息` |
**App 调用链**:`UsAppLabelPreviewInputVo.locationId` → 内部 `LabelAppService.PreviewAsync(LabelPreviewResolveInputVo)` 时须**原样传入** `locationId`。
受影响接口(均通过 `LabelAppService.PreviewAsync` 渲染模板):
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/app/us-app-labeling/preview` | App 预览 |
| POST | `/api/app/us-app-labeling/print` | App 打印(落库前解析模板) |
| POST | `/api/app/label/preview`(或管理端等价预览) | Web 预览;含 Company 元素时 Body 须带 `locationId` |
重打 **`reprint`** 使用历史任务 `RenderTemplateJson` 快照,**不再**重新解析 Company。
### 出参变更
无新增顶层字段;变更在 **`template.elements[]`** 内:
| 字段 | 变更 |
|------|------|
| `elements[].config.text` | Company 元素由后端按上文规则写入多行文本 |
### 数据库与脚本
| 项 | 说明 |
|----|------|
| `fl_partner.PartnerName` | 公司名(必有) |
| `fl_partner.Street` / `City` / `StateCode` / `ZipCode` / `ContactEmail` | 可选展示字段 |
| `location.Partner` | 门店归属 Company 键(Id 或名称) |
| DDL | `scripts/fl_partner_add_address_columns.sql`(缺地址列时执行) |
模板适用范围(Company/Region/Location 三维 scope)见 **`项目相关文档/6-4代码优化.md`**,与本节「元素内 Company 自动填值」相互独立。
### 请求示例(含 Company 的 preview)
```bash
curl -X POST "http://flus-test.3ffoodsafety.com/api/app/us-app-labeling/preview" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"locationId": "550e8400-e29b-41d4-a716-446655440000",
"labelCode": "LBL0001",
"productId": "PROD001"
}'
```
响应 `template.elements` 中 Company 元素片段示例:
```json
{
"elementType": "TEXT_STATIC",
"typeAdd": "auto_Company",
"valueSourceType": "AUTO_DB",
"config": {
"companyIncludeFields": ["address", "city", "state", "zip"],
"text": "Acme Foods Inc\n123 Main Street\nNew York, NY, 10001"
}
}
```
### 涉及代码(Company)
| 文件 | 说明 |
|------|------|
| `Helpers/PartnerCompanyDisplayHelper.cs` | 识别元素、解析 config、格式化文本、门店→Partner |
| `Services/LabelAppService.cs` | `PreviewAsync` 填充 Company 的 `config.text` |
| `Dtos/Label/LabelPreviewResolveInputVo.cs` | 新增 `locationId` |
| `Services/UsAppLabelingAppService.cs` | preview/print 调用预览时传入 `locationId` |
### 验证步骤(Company)
1. 确认门店 `location.Partner` 能关联到有效 `fl_partner` 记录(地址列已执行 DDL)。
2. 模板含 `auto_Company` 元素,`config` 勾选若干 include 字段;保存后查 `fl_label_template_element.ConfigJson`。
3. 调用 **preview**,Body 带正确 `locationId`:`template.elements` 中 Company 的 `config.text` 行数与勾选一致。
4. 去掉 `locationId` 或传空 → 返回 400(仅当模板含 Company 元素时)。
5. 执行 **print**,检查 `fl_label_print_task.RenderTemplateJson` 内 Company `text` 与预览一致。
#### SQL 抽查
```sql
-- 门店归属 Company
SELECT l.Id, l.Partner, p.PartnerName, p.Street, p.City, p.StateCode, p.ZipCode, p.ContactEmail
FROM location l
LEFT JOIN fl_partner p ON (p.Id = l.Partner OR p.PartnerName = l.Partner) AND p.IsDeleted = 0
WHERE l.Id = '{locationId}' AND l.IsDeleted = 0;
-- 模板 Company 元素 config
SELECT e.Id, e.TypeAdd, e.ValueSourceType, e.ConfigJson
FROM fl_label_template_element e
JOIN fl_label_template t ON t.Id = e.TemplateId
WHERE t.TemplateCode = '{templateCode}' AND e.IsDeleted = 0
AND e.TypeAdd = 'auto_Company';
```
---
|