49755ef0
李曜臣
6-12代码优化
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
|
# 5-27 代码优化
本文档说明 **2026-05-27** 对美国版接口的变更。
1. **修复** App 管理员级联选店接口 **404**(`admin-scope-regions` 等 Query 传参无法命中路由,见 [us-app-auth-路由修复](#us-app-auth-管理员选店路由-404-修复))。
2. 同步修复 Web **`auth-scope`** 同类路由(`regions` / `locations` 使用 Query 传 `partnerId`、`groupId`)。
3. **App Label Report 页**(`pages/more/label-report`):完善 **`get-label-report`**,支持 **7d / 30d / 90d / 自定义日期**(见 [app-label-report](#app-label-report-标签报表))。
4. **泰额版** `POST /api/app/th-app-auth/login`:修复登录成功后因 **主库无 LoginLog 表** 导致 500(见 [th-app-auth-login](#泰额版-th-app-auth-登录))。
> 级联选店业务见 `5-26代码优化.md` → **us-app-auth** / **auth-scope** 章节。
---
## us-app-auth 管理员选店路由 404 修复
### 问题现象
```http
GET /api/app/us-app-auth/admin-scope-regions?partnerId=3a217015-4def-3813-01bf-05e4c8c09be6
Authorization: Bearer {app_token}
```
返回 **404 Not Found**(未进入业务逻辑,非 400 权限错误)。
### 根因
项目使用 **`YiConventionalRouteBuilder`**:当 Action **仅有一个** 以 `Id` 结尾的参数(如 `partnerId`)时,约定路由会生成 **路径参数**,例如:
```text
GET /api/app/us-app-auth/admin-scope-regions/{partnerId}
```
客户端若用 **Query** `?partnerId=...` 调用,路径不匹配 → **404**。
`admin-scope-locations` 同时有 `partnerId` + `groupId` 两个 `*Id` 参数时,约定路由通常 **不会** 把 Id 放进路径,故 Query 方式有时能通;为统一行为,已改为显式路由。
### 修复方式
在 `UsAppAuthAppService` / `AuthScopeAppService` 上为级联选店方法增加 **显式** `[HttpGet]` / `[HttpPost]` 模板(与 `forgot-password` 相同写法),**强制** `partnerId`、`groupId` 走 **Query**。
### 正确接口地址(修复后)
| 步骤 | 方法 | 路径 | Query |
|------|------|------|-------|
| 公司 | GET | `/api/app/us-app-auth/admin-scope-companies` | 无 |
| Region | GET | `/api/app/us-app-auth/admin-scope-regions` | **`partnerId`**(必填) |
| 门店 | GET | `/api/app/us-app-auth/admin-scope-locations` | **`partnerId`**、**`groupId`**(必填) |
| 确认选店 | POST | `/api/app/us-app-auth/select-admin-scope-location` | Body JSON |
**鉴权**:App 登录 Token(`client_kind=us-app`)+ 平台管理员。
### Region 列表 — 正确示例
```http
GET /api/app/us-app-auth/admin-scope-regions?partnerId=3a217015-4def-3813-01bf-05e4c8c09be6 HTTP/1.1
Host: localhost:19001
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
**响应**:`AuthScopeRegionOptionDto[]`
```json
[
{
"id": "fl_group_id_east",
"groupName": "East Region",
"partnerId": "3a217015-4def-3813-01bf-05e4c8c09be6",
"state": true
}
]
```
### 门店列表 — 正确示例
```http
GET /api/app/us-app-auth/admin-scope-locations?partnerId=3a217015-4def-3813-01bf-05e4c8c09be6&groupId=fl_group_id_east HTTP/1.1
Authorization: Bearer {app_token}
```
### 兼容说明(不推荐)
修复前若误按约定路由调用,Region 可能需写成路径参数:
```http
GET /api/app/us-app-auth/admin-scope-regions/3a217015-4def-3813-01bf-05e4c8c09be6
```
**请统一使用 Query `?partnerId=`**,与文档及 App 封装一致。
### Web auth-scope(同步修复)
| 方法 | 路径 | Query |
|------|------|-------|
| GET | `/api/app/auth-scope/companies` | 无 |
| GET | `/api/app/auth-scope/regions` | `partnerId` |
| GET | `/api/app/auth-scope/locations` | `partnerId`、`groupId` |
| POST | `/api/app/auth-scope/select-location` | Body |
| GET | `/api/app/auth-scope/current-scope` | 无 |
### 联调注意
| 现象 | 处理 |
|------|------|
| 仍 404 | 确认已部署含本修复的后端;路径勿多写 `/us-app-auth` 前缀(完整路径见上表) |
| 400「请使用 App 登录令牌」 | 使用 `POST /api/app/us-app-auth/login` 返回的 Token |
| 400「仅管理员可使用」 | 换管理员账号 |
| 200 但 `[]` 空数组 | 该公司下无 `fl_group` 或数据未录入 |
### 推荐调用顺序(App 管理员)
```text
POST /api/app/us-app-auth/login
→ GET /api/app/us-app-auth/admin-scope-companies
→ GET /api/app/us-app-auth/admin-scope-regions?partnerId={公司Id}
→ GET /api/app/us-app-auth/admin-scope-locations?partnerId={公司Id}&groupId={区域Id}
→ POST /api/app/us-app-auth/select-admin-scope-location
→ GET /api/app/us-app-auth/my-locations
```
---
## App Label Report 标签报表
**应用服务**:`UsAppLabelingAppService`
**接口**:`POST /api/app/us-app-labeling/get-label-report`
**页面**:App `Label Report`(指标卡 + Labels by Category + Print Volume Trends + Most Used Products)
### 鉴权与数据范围
| 项 | 说明 |
|----|------|
| Token | App 登录 `POST /api/app/us-app-auth/login` |
| 门店 | Body **`locationId`**(当前选中门店;管理员可先 `select-admin-scope-location`) |
| 管理员 / Partner | 当前门店 **全部** 打印任务 |
| 其它角色 | 仅 **`CreatedBy == 当前用户`** 的任务 |
### 请求体(UsAppLabelReportQueryInputVo)
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| locationId | string | **是** | 门店 Guid |
| **period** | string | 否 | **`7d`**(默认)/ **`30d`** / **`90d`** / **`custom`** |
| startDate | date | custom 时必填 | 含当天,如 `2026-05-20` |
| endDate | date | custom 时必填 | 含当天,默认今天 |
| keyword | string | 否 | 产品名 / 标签分类名模糊匹配 |
**周期与 App UI 对应**
| App 按钮 | period |
|----------|--------|
| Last 7 Days | `7d` |
| Last 30 Days | `30d` |
| Last 90 Days | `90d` |
| Custom + Start/End | `custom` + `startDate` + `endDate` |
**区间规则**(含起止日当天):
| period | 起止(结束日 = 今天或 endDate) |
|--------|--------------------------------|
| 7d | 共 7 个自然日(今天往前 6 天) |
| 30d | 共 30 个自然日 |
| 90d | 共 90 个自然日 |
| custom | `startDate` ~ `endDate`(最长 366 天) |
### 请求示例
**最近 7 天**
```http
POST /api/app/us-app-labeling/get-label-report HTTP/1.1
Authorization: Bearer {app_token}
Content-Type: application/json
```
```json
{
"locationId": "3a21220f-db37-3e32-7390-d55f64cd62a8",
"period": "7d"
}
```
**最近 30 天**
```json
{
"locationId": "3a21220f-db37-3e32-7390-d55f64cd62a8",
"period": "30d"
}
```
**自定义日期**(对应 UI Start / End)
```json
{
"locationId": "3a21220f-db37-3e32-7390-d55f64cd62a8",
"period": "custom",
"startDate": "2026-05-20",
"endDate": "2026-05-27"
}
```
### 响应体(ReportsLabelReportOutputDto)
#### appliedRange(本次实际统计区间)
| 字段 | 说明 |
|------|------|
| period | `7d` / `30d` / `90d` / `custom` |
| startDate | `yyyy-MM-dd` |
| endDate | `yyyy-MM-dd` |
| dayCount | 自然日天数 |
| trendDescription | 趋势图副标题(英文,如 `Daily label printing volume for the last 7 days.`) |
#### summary(四张指标卡)
| 字段 | UI 对应 |
|------|---------|
| totalLabelsPrinted | Total Labels Printed |
| totalLabelsPrintedChangeRate | 相对 **上一同长度周期** 变化率(%,如 `20.1` 表示 +20.1%) |
| mostPrintedCategoryName / mostPrintedCategoryCount | Most Printed Category |
| topProductName / topProductCount | Top Product |
| avgDailyPrints | Avg. Daily Prints |
| avgDailyPrintsChangeRate | 日均相对上一周期变化率 |
#### labelsByCategory(Labels by Category 柱状图)
`{ categoryId, categoryName, count }[]`,按 `count` 降序。分类来自 **标签分类**(`fl_label_category`)。
#### printVolumeTrend(Print Volume Trends)
`{ date, count }[]`:**整个查询区间内每日**打印量(7d 返回 7 个点,30d 返回 30 个点,以此类推;无数据日为 `0`)。
#### mostUsedProducts(Most Used Products 表格)
| 字段 | UI 列 |
|------|-------|
| productName | Product Name |
| categoryName | Category(产品分类名) |
| totalPrinted | Total Printed |
| usagePercent | Usage %(占当期总打印量百分比) |
### 响应示例(节选)
```json
{
"appliedRange": {
"period": "7d",
"startDate": "2026-05-21",
"endDate": "2026-05-27",
"dayCount": 7,
"trendDescription": "Daily label printing volume for the last 7 days."
},
"summary": {
"totalLabelsPrinted": 2543,
"totalLabelsPrintedPrevPeriod": 2118,
"totalLabelsPrintedChangeRate": 20.06,
"mostPrintedCategoryName": "Dairy",
"mostPrintedCategoryCount": 450,
"topProductName": "Whole Milk",
"topProductCount": 182,
"avgDailyPrints": 363.29,
"avgDailyPrintsPrevPeriod": 302.57,
"avgDailyPrintsChangeRate": 20.07
},
"labelsByCategory": [
{ "categoryName": "Dairy", "count": 450 },
{ "categoryName": "Meat", "count": 380 }
],
"printVolumeTrend": [
{ "date": "2026-05-21", "count": 72 },
{ "date": "2026-05-22", "count": 85 }
],
"mostUsedProducts": [
{
"productName": "Whole Milk",
"categoryName": "Dairy",
"totalPrinted": 182,
"usagePercent": 7.16
}
]
}
```
### 与旧版差异(本次优化)
| 项 | 优化前 | 优化后 |
|----|--------|--------|
| period | 仅 `startDate`/`endDate`,默认约 30 天 | 显式 **`7d`/`30d`/`90d`/`custom`** |
| printVolumeTrend | 仅区间内 **最后 7 天** | **整个查询区间**按日汇总 |
| appliedRange | 无 | 回显实际区间与趋势副标题 |
| 路由 | 仅约定路由 | 增加 **`[HttpPost("us-app-labeling/get-label-report")]`** 显式路径 |
### 联调注意
| 现象 | 处理 |
|------|------|
| 404 | 确认路径为 **`POST .../get-label-report`**(非 GET) |
| custom 报错 | 须同时传 `startDate`、`endDate` |
| 趋势只有 7 个点但选了 30d | 部署含本修复的后端 |
| 指标全 0 | 该门店/角色在区间内无打印任务;检查 `locationId` |
| 分类名为空 | 打印任务未关联标签分类 |
> 更完整的权限说明见 **`5-18接口优化.md`** → us-app-print-log / get-label-report 章节。
---
## 泰额版 th-app-auth 登录
**应用服务**:`ThAppAuthAppService`(泰额模块 `FoodLabeling.Th.Application`)
**路径**:`POST /api/app/th-app-auth/login`(已加显式路由 `[HttpPost("th-app-auth/login")]`)
### 问题现象
日志显示登录逻辑已执行成功(查租户、用户、`userlocation` 均有 SQL),但请求最终 **500**:
```text
MySqlException: Table 'antis-foodlabeling-host.loginlog' doesn't exist
```
浏览器还可能提示:
```text
Request origin http://saas-test.3ffoodsafety.com does not have permission to access the resource.
```
### 根因
1. **LoginLog**:泰额 App 在**租户库**校验用户,但登录后发布了 `LoginEvent`,在 **UoW 提交阶段** 向**当前连接(主库 host)** 插入 `LoginLog`;主库 `antis-foodlabeling-host` 未建该表 → 整单失败。
2. **CORS**:`App:CorsOrigins` 未包含 `http://saas-test.3ffoodsafety.com`。
### 修复说明
| 项 | 处理 |
|----|------|
| 泰额 App 登录 | **不再发布** `LoginEvent`,避免写 host 库 `LoginLog` |
| `LoginEventHandler` | 外层 try/catch + `autoSave: true`;写库失败仅打 Warning,不影响 Web 登录 |
| CORS | `appsettings.json` 的 `App:CorsOrigins` 增加 `saas-test.3ffoodsafety.com`(http/https) |
| 路由 | `th-app-auth/login`、`th-app-auth/my-locations` 显式 `[HttpPost]` / `[HttpGet]` |
### 请求示例
```http
POST /api/app/th-app-auth/login
Content-Type: application/json
```
```json
{
"tenantId": "11111111-1111-1111-1111-111111111111",
"email": "admin@example.com",
"password": "YourPassword1!"
}
```
### 部署注意
1. 重新发布 **泰额版** `Yi.Abp.Web`(含 `FoodLabeling.Th.Application`、`Yi.Framework.Rbac.Domain`)。
2. 生产环境若域名不同,在 **`App:CorsOrigins`**(或 `appsettings.Production.json`)中追加前端 Origin,分号分隔。
3. 若需在**主库**记录 Web 管理员登录日志,可在 host 库执行 RBAC 初始化脚本创建 `LoginLog` 表(泰额 App 登录不依赖该表)。
> 多租户登录完整说明见 **`5-19泰额版.md`**。
---
## 变更记录
| 日期 | 说明 |
|------|------|
| 2026-05-27 | 泰额 th-app-auth/login:取消 LoginEvent;修复 host 无 LoginLog 导致 500;CORS 增加 saas-test 域名 |
| 2026-05-27 | App Label Report:`get-label-report` 支持 7d/30d/90d/custom;趋势按全区间按日汇总;出参 `appliedRange` |
| 2026-05-27 | 修复 us-app-auth / auth-scope 级联选店 404:显式路由,partnerId/groupId 使用 Query |
| 2026-05-27 | 补充 `5-27代码优化.md` 接口说明与 curl 示例 |
|