577 lines
20 KiB
Markdown
577 lines
20 KiB
Markdown
# AGI 接力规划 · 批次 B1–B6
|
||
|
||
本文件是给执行模型的施工单。每一批都标注了**精确文件、改动点、验收命令**。
|
||
上一轮(B0)已完成 38 个文件的修复 + 4 个门禁脚本,全绿。
|
||
|
||
当前基线(执行前请先复现):
|
||
|
||
```bash
|
||
npm test
|
||
# {"errors":0,"warnings":0,"status":"passed"}
|
||
# {"schemaCount":59,"collectionCount":27,"missingSchemaCount":3,"fieldDriftCount":73}
|
||
# {"source":1,"mapped":1,"conflicts":0}
|
||
# {"status":"passed","checks":7}
|
||
```
|
||
|
||
---
|
||
|
||
## B1 — 让门禁可信(P0,必须最先做)
|
||
|
||
**为什么最先做**:现在 73 条 fieldDrift 里混着大量误报,执行模型照着修会改错文件。门禁不可信,后面全是盲改。
|
||
|
||
### B1-1 `scripts/data-contract-report.js` 修正字段归属
|
||
|
||
现状 `collectFields` 只认 `collectionList: "x"` 一种写法,且用 `/field\s*=/` 匹配。
|
||
|
||
真实例子(已核实):
|
||
|
||
```text
|
||
pages/uni-stat/pay-order/ranking/ranking.vue:35 group-field="sum(total_fee) as total_fee,..."
|
||
```
|
||
|
||
`group-field=` 里含 `field=`,被正则抓成「字段」,于是产出 `uni-pay-orders.sum(total_fee)` 这类假漂移。
|
||
|
||
改动点:
|
||
|
||
1. 正则改为 `/[\s"]field\s*=\s*["']/g`,用前置边界排除 `group-field` / `groupField`。
|
||
2. 跳过聚合表达式:字段名含 `(` 或 `)` 的直接丢弃。
|
||
3. 集合归属按优先级取:`collectionList: "x"` → `collection: "x"` → `collectionList: [db.collection('x')...]`。
|
||
4. 同一页面若出现多个 collection(如 `uni-data-select` 的辅助集合),只把**主 `unicloud-db` 绑定的集合**用于 field 归属;辅助集合只登记不比对字段。
|
||
|
||
### B1-2 `scripts/quality-check.js` 同步修正
|
||
|
||
`checkCollectionContracts` 用了同类正则,会把辅助集合也算进去。同步 B1-1 的集合归属规则,避免产出噪音 warning。
|
||
|
||
### B1-3 区分「真漂移」与「schema 缺字段」
|
||
|
||
对每条漂移,输出三态而不是一刀切:
|
||
|
||
```text
|
||
drift-kind: missing-in-schema | page-field-typo | aggregate-expression
|
||
```
|
||
|
||
聚合表达式(B1-1 已过滤)不应再出现在报告。
|
||
|
||
**验收**
|
||
|
||
```bash
|
||
npm run check:contracts
|
||
# 期望 fieldDriftCount 从 73 显著下降;uni-pay-orders.sum(*) 全部消失
|
||
rg 'sum\(' reports/data-contract-report.md # 期望无输出
|
||
```
|
||
|
||
---
|
||
|
||
## B2 — 会崩的真实缺陷(P1)
|
||
|
||
以下 3 条是**已确认的空值崩溃点**,与本轮报告真伪无关。
|
||
|
||
### B2-1 `pages/system/user/list.vue:251`
|
||
|
||
```js
|
||
const roleArr = item.role.map(item => item.role_name)
|
||
```
|
||
|
||
`item.role` 在联表未命中、或用户无角色时为 `undefined` → `TypeError`。
|
||
|
||
改法(沿用本轮 `tags` 的写法):
|
||
|
||
```js
|
||
const roleArr = Array.isArray(item.role) ? item.role.map(r => r && r.role_name).filter(Boolean) : []
|
||
```
|
||
|
||
同时 `item.tags` 映射后要保证是数组,避免模板 `v-for` 报错。
|
||
|
||
### B2-2 `pages/system/role/list.vue:131`
|
||
|
||
```js
|
||
item.permission = item.permission.map(pItem => pItem.permission_name).join('、')
|
||
```
|
||
|
||
`permission` 为空数组或缺失即崩。改为:
|
||
|
||
```js
|
||
const list = Array.isArray(item.permission) ? item.permission : []
|
||
item.permission = list.map(p => p && p.permission_name).filter(Boolean).join('、')
|
||
```
|
||
|
||
### B2-3 `pages/system/user/list.vue:283` 生产日志
|
||
|
||
```js
|
||
console.log(JSON.stringify(db.command.or(...)))
|
||
```
|
||
|
||
删除;若需排障,包进 `process.env.NODE_ENV !== 'production'`。
|
||
|
||
**另外两处调试日志**(同类,一并清理):
|
||
|
||
- `pages/uni-stat/device/activity/activity.vue:210` `console.log('query: ', query)`
|
||
- `pages/uni-stat/device/trend/trend.vue:328` 同上
|
||
- `pages/uni-stat/pay-order/ranking/ranking.vue:188` `console.log('where: ', where)`
|
||
|
||
**验收**
|
||
|
||
```bash
|
||
rg -n 'console\.log' pages --glob '*.vue' | grep -v '//' | grep -v NODE_ENV
|
||
# 期望只剩 cms-temp/add.vue 的上传日志(B4-2 处理)
|
||
```
|
||
|
||
---
|
||
|
||
## B3 — 统计页错误态统一(P1,工作量最大)
|
||
|
||
### B3-1 仍在吞错的页面(已核实 `console.error` 计数)
|
||
|
||
```text
|
||
pages/uni-stat/page-ent/page-ent.vue
|
||
pages/uni-stat/page-res/page-res.vue
|
||
pages/uni-stat/page-content/page-content.vue
|
||
pages/uni-stat/event/event.vue
|
||
pages/uni-stat/channel/channel.vue
|
||
pages/uni-stat/scene/scene.vue
|
||
```
|
||
|
||
### B3-2 统一契约
|
||
|
||
每个查询区块必须落到四态,禁止 `console.error` 后什么都不做:
|
||
|
||
```js
|
||
// data
|
||
loading: false,
|
||
errorMessage: '',
|
||
|
||
// 查询前
|
||
this.loading = true
|
||
this.errorMessage = ''
|
||
|
||
// catch
|
||
this.errorMessage = err && (err.message || err.errMsg) || '数据加载失败'
|
||
this.tableData = [] // 必须清空,否则旧数据显示成新结果
|
||
|
||
// finally
|
||
this.loading = false
|
||
```
|
||
|
||
模板侧把 `errorMessage` 喂给表格与图表组件(`uni-stat/device/overview` 已有现成写法,照抄):
|
||
|
||
```vue
|
||
<uni-table :loading="loading" :emptyText="errorMessage || '暂无数据'">
|
||
```
|
||
|
||
### B3-3 复用入口
|
||
|
||
不要在 6 个页面各写一份。先在 `js_sdk/uni-stat/util.js` 增加:
|
||
|
||
```js
|
||
export function createStatQueryState(extra = {}) {
|
||
return {
|
||
loading: false,
|
||
errorMessage: '',
|
||
...extra
|
||
}
|
||
}
|
||
```
|
||
|
||
页面 `data()` 展开即可。若执行模型判断收益不足,可退化为「6 页各自统一命名」,但**命名必须一致**,否则后续无法批量替换。
|
||
|
||
**验收**
|
||
|
||
```bash
|
||
rg -c 'errorMessage' pages/uni-stat/**/*.vue | wc -l # 覆盖页面数应增加
|
||
rg -n "console\.error" pages/uni-stat --glob '*.vue' # 期望只剩兜底日志,且都伴随 errorMessage 赋值
|
||
```
|
||
|
||
---
|
||
|
||
## B4 — 搜索与表单可用性(P1/P2)
|
||
|
||
### B4-1 搜索框存在但搜不到东西
|
||
|
||
以下页面渲染了搜索输入,但 `dbSearchFields = []`,点搜索只是刷新列表:
|
||
|
||
```text
|
||
pages/system/app/list.vue → ['appid', 'name', 'description']
|
||
pages/uni-id-log/list.vue → ['username', 'device_uuid', 'ip', 'appid']
|
||
pages/comment/list.vue → ['content']
|
||
pages/comment_like/list.vue → ['comment_id', 'user_id']
|
||
pages/comment_operation_logs/list.vue → ['content', 'user_id']
|
||
pages/opendb-search-hot/list.vue → ['content']
|
||
pages/opendb-search-log/list.vue → ['content', 'device_id', 'user_id']
|
||
```
|
||
|
||
若某页判定不该支持全文搜索(例如纯日志页),则**移除搜索框**,不要留假入口。
|
||
|
||
### B4-2 `pages/cms-temp/add.vue` 图片上传链路
|
||
|
||
现状 8 处 `console.log`,且 `updateImage` 用 `success` 回调 + 未捕获异常。
|
||
`edit.vue` 已在 B0 改成 `try/catch + await` 写法,**照 `edit.vue` 的写法重写 `add.vue` 的 `updateImage`**,并删除全部调试日志。
|
||
|
||
### B4-3 `topWindow.vue` 死代码
|
||
|
||
`windows/topWindow.vue:146-151` 的 `showPasswordPopup()` 调用了不存在的 `this.$refs.passwordPopup`。
|
||
模板中只有 `errorLogsPopup`。删除该死方法(修改密码入口已由 `changePassword()` 承担)。
|
||
|
||
### B4-4 `leftWindow.vue` 路由行为
|
||
|
||
`windows/leftWindow.vue:71-97`:
|
||
|
||
- 内链用 `uni.redirectTo` 破坏返回栈 → 改 `uni.navigateTo`
|
||
- H5 外链 `window.open(url)` 缺 `noopener` → `window.open(url, '_blank', 'noopener,noreferrer')`
|
||
- 跳转失败提示补充菜单名与目标 URL,便于定位配置错误
|
||
|
||
### B4-5 列表 key
|
||
|
||
以下页面仍在用数组下标作 key,筛选/排序后会串行状态:
|
||
|
||
```text
|
||
pages/system/role/list.vue:40
|
||
pages/system/permission/list.vue:45
|
||
pages/system/user/list.vue:52
|
||
pages/system/tag/list.vue:37
|
||
pages/opendb-search-hot/list.vue:29
|
||
pages/opendb-search-log/list.vue:30
|
||
pages/comment*/list.vue
|
||
pages/uni-id-log/list.vue:37
|
||
pages/uni-stat/pay-order/ranking/ranking.vue:45
|
||
```
|
||
|
||
统一改 `:key="item._id"`(无 `_id` 的聚合结果用 `item.user_id` 等业务主键)。
|
||
|
||
**验收**
|
||
|
||
```bash
|
||
npm run check:vue3 # 必须保持 passed
|
||
rg -n ':key="index"' pages --glob '*.vue' # 期望大幅减少
|
||
```
|
||
|
||
---
|
||
|
||
## B5 — 数据与 schema 合同落地(P2)
|
||
|
||
### B5-1 真实漂移(非误报,已核实)
|
||
|
||
```text
|
||
pages/uni-stat/error/app/app.vue:47 collection: uni-stat-app-crash-logs
|
||
```
|
||
|
||
页面 field 中的以下字段在 schema 里需逐个核对:
|
||
|
||
```text
|
||
_id, name, uni_platform, create_date, count, app_launch_count, start_time, day_count
|
||
```
|
||
|
||
处理原则:**schema 是合同,页面是消费方**。若字段确实由统计跑批写入但 schema 漏声明 → 补 schema;若页面写了不存在的字段 → 删页面字段。
|
||
|
||
```text
|
||
pages/uni-stat/page-rule/page-rule.vue:17 collection: uni-stat-pages
|
||
field="title,path,page_rules,appid"
|
||
```
|
||
|
||
同样逐个核对 `uni-stat-pages.schema.json`。
|
||
|
||
### B5-2 缺失索引的集合
|
||
|
||
有 schema 但无 `*.index.json`(列表来自实测):
|
||
|
||
```text
|
||
opendb-search-hot ← 搜索热词高频查询
|
||
opendb-search-log ← 日志量大
|
||
opendb-sms-log ← 短信日志,按 task_id/status 查
|
||
opendb-sms-task
|
||
cms-temp ← 文章外键关联
|
||
opendb-news-articles / opendb-news-categories
|
||
read-news-log
|
||
uni-id-scores
|
||
uni-stat-run-errors
|
||
opendb-tempdata
|
||
```
|
||
|
||
优先补前 5 个。索引字段依据代码实际查询条件推导,不要凭空造:
|
||
|
||
```text
|
||
opendb-search-log → content? 否;建 create_date desc、device_id、user_id
|
||
opendb-sms-log → task_id、status、mobile
|
||
opendb-sms-task → create_date desc
|
||
cms-temp → 无强需求,可延后
|
||
```
|
||
|
||
### B5-3 `comment*` 三集合决策(**需要人工确认,禁止自动执行**)
|
||
|
||
`comment` / `comment_like` / `comment_operation_logs` 在仓库内**没有任何 schema**,
|
||
但页面完整实现了增删改查。二选一:
|
||
|
||
| 方案 | 动作 | 风险 |
|
||
|---|---|---|
|
||
| A. 新建 schema | 按页面字段补 3 份 schema + 权限 + 索引 | 若云端实际用的是 `opendb-news-comments`,会造成双写分裂 |
|
||
| B. 改用官方表 | 页面 field 映射到 `opendb-news-comments` 等 | 字段语义差异大,`content`↔`comment_content`、`create_time`↔`comment_date`,改完需重建数据 |
|
||
|
||
**执行模型不得自行选择**。先在 `reports/` 输出决策报告,列出两方案的字段映射表,等确认。
|
||
|
||
### B5-4 `cms-temp` 权限种子缺口
|
||
|
||
schema 已引用:
|
||
|
||
```text
|
||
CREATE_CMS_TEMP / UPDATE_CMS_TEMP / DELETE_CMS_TEMP
|
||
```
|
||
|
||
但 `uniCloud-alipay/database/uni-id-permissions.init_data.json` 是空数组 `[]`,
|
||
即非 admin 角色**没有任何途径获得这些权限**。
|
||
|
||
处理:
|
||
|
||
- 若只允许超管维护模板 → 把 schema 简化为 `'admin' in auth.role`,去掉悬空权限点;
|
||
- 若要支持授权运营 → 在 `init_data.json` 补 3 条权限记录。
|
||
|
||
当前 schema 用 `'admin' in auth.role || 'CREATE_CMS_TEMP' in auth.permission`,
|
||
admin 可用、权限点悬空但无害。**建议明确化**,避免后续误判为已支持细粒度授权。
|
||
|
||
### B5-5 `opendb-sms-log` 部署影响
|
||
|
||
本轮已修 `ccreate_date` → `create_date`、`mobile` int → string、`task_id` 外键表名。
|
||
这些是**破坏性 schema 变更**:线上若已有 `ccreate_date` 数据,改名后旧数据不可见。
|
||
|
||
补齐迁移脚本或在 changelog 明确标注「需人工核对线上数据后再上传 schema」。
|
||
|
||
---
|
||
|
||
## B6 — 仓库与依赖卫生(P3)
|
||
|
||
### B6-1 云函数版本元数据
|
||
|
||
7 个云函数 `package.json` 仍是 `2.4.25`,根项目已 `2.5.1`:
|
||
|
||
```text
|
||
uni-upgrade-center / ext-storage-co / uni-stat-receiver / uni-sms-co
|
||
uni-analyse-searchhot / uni-portal / uni-stat-cron
|
||
```
|
||
|
||
先确认这是官方插件兼容元数据还是漏同步。若是漏同步 → 统一 2.5.1;若语义是「基于哪个版本的插件」→ **不要动**,只在 README 说明。
|
||
|
||
### B6-2 `unpackage/` 被纳入版本控制
|
||
|
||
约 1367 个已跟踪文件位于 `unpackage/`,属 HBuilderX 生成物。
|
||
|
||
```bash
|
||
git rm -r --cached unpackage
|
||
printf 'unpackage/\nreports/\n.zcode/\n' >> .gitignore
|
||
```
|
||
|
||
> 注意:`reports/` 若希望留痕(便于对比各轮门禁结果),可只忽略 `reports/*.json`,保留 `.md`。
|
||
|
||
### B6-3 `App.vue` 扩展存储占位域名
|
||
|
||
`App.vue:66` `domain: "cdn.example.com"` 未替换时开启扩展存储会上传失败。
|
||
至少加一行注释指向配置项,或在 `admin.config.js` 集中管理。
|
||
|
||
---
|
||
|
||
## 执行顺序与并行建议
|
||
|
||
```text
|
||
B1 ──► B2 ──► B3 ──► B4 ──► B5 ──► B6
|
||
门禁 崩溃点 错误态 可用性 数据合同 仓库卫生
|
||
```
|
||
|
||
- **B1 必须单线程先做**,它是其他批次的可信度前提。
|
||
- B2 / B4 可并行(不同文件)。
|
||
- B3 涉及 6+ 页面,建议一个执行模型专做,避免风格分裂。
|
||
- B5-3 遇阻立即停下出报告,不要自行决策。
|
||
|
||
## 每批完成后的强制动作
|
||
|
||
```bash
|
||
npm test # 四项全绿才允许进入下一批
|
||
git diff --check # 无空白错误
|
||
```
|
||
|
||
并在 `changelog.md` 追加对应条目。
|
||
|
||
## 交付物清单
|
||
|
||
| 批次 | 主要文件 |
|
||
|---|---|
|
||
| B1 | `scripts/data-contract-report.js`、`scripts/quality-check.js` |
|
||
| B2 | `pages/system/user/list.vue`、`pages/system/role/list.vue`、4 处日志 |
|
||
| B3 | `js_sdk/uni-stat/util.js` + 6–12 个 `pages/uni-stat/**` |
|
||
| B4 | `pages/cms-temp/add.vue`、`windows/topWindow.vue`、`windows/leftWindow.vue`、7 个 list 页 |
|
||
| B5 | `uniCloud-alipay/database/*.index.json`、`*.schema.json`、`reports/*decision*.md` |
|
||
| B6 | `.gitignore`、7 个云函数 `package.json`(待确认)、`App.vue` |
|
||
|
||
---
|
||
|
||
# 补遗 · B7(二轮勘察新增,优先级高于 B3)
|
||
|
||
以下 6 条是二轮实测确认的缺陷,**B7-1 与 B7-4 应插到 B2 之前或并列 B2**。
|
||
|
||
## B7-1 菜单环导致浏览器假死(P0,已复现)
|
||
|
||
**已用 Node 复现 `INFINITE LOOP`。**
|
||
|
||
成因链完整,三个环节都缺防护:
|
||
|
||
1. `components/uni-data-menu/util.js` 的 `getParentIds`:
|
||
|
||
```js
|
||
while (currentItem && currentItem.parent_id) {
|
||
parentArr.push(currentItem.parent_id)
|
||
currentItem = menuList.find(item => item.menu_id === currentItem.parent_id)
|
||
}
|
||
```
|
||
|
||
无 `visited` 集合。数据一旦成环(A→B、B→A),`find` 永远命中,死循环。
|
||
|
||
2. 该函数被 `buildMenus` 的 `sort` 比较器调用 → **排序期间**触发,页面直接卡死,连报错都没有。
|
||
|
||
3. `pages/system/menu/add.vue` / `edit.vue` 的 `parent_id` 是**自由文本输入**:
|
||
|
||
```text
|
||
js_sdk/validator/opendb-admin-menus.js → parent_id 只校验 format: string
|
||
opendb-admin-menus.schema.json → parentKey 只是表单渲染提示,不是 DB 约束
|
||
```
|
||
|
||
即:在菜单管理里把某菜单的父级填成它自己,保存,刷新左侧菜单 → 假死。全程无需任何特殊权限。
|
||
|
||
**改动点**
|
||
|
||
```text
|
||
components/uni-data-menu/util.js
|
||
· getParentIds 加 visited Set,命中已访问节点立即 return []
|
||
· buildMenu 递归加 visited 参数,同一 menu_id 不重复下钻
|
||
· buildMenus 的 sort 比较器不要每次重算 getParentIds —— 预先算一次存 Map,
|
||
否则 O(n² log n)(配合 B7-2 的 pageSize=20000 是灾难)
|
||
|
||
pages/system/menu/add.vue + edit.vue
|
||
· 保存前校验 parent_id !== menu_id
|
||
· 保存前用已加载的 menus 走一遍祖先链,判定是否会成环,成环则阻止提交并提示
|
||
|
||
pages/system/menu/list.vue
|
||
· getParents / getChildren 两个递归同样加 visited
|
||
```
|
||
|
||
**验收**:构造 A→B、B→A 的两条数据,菜单页必须能正常渲染并提示数据异常,不得卡死。
|
||
|
||
## B7-2 `menu/list.vue` 性能与一致性(P1)
|
||
|
||
```text
|
||
:126 const pageSize = 20000
|
||
:211 getParents 递归无环保护
|
||
:221 getChildren 递归无环保护
|
||
:277 enableChange 乐观更新:
|
||
item.enable = !item.enable
|
||
db.collection(...).update({enable}) ← 无 await、无 catch、无回滚
|
||
```
|
||
|
||
`enableChange` 失败时 UI 已切换,形成假成功;刷新后又变回去,用户会反复点。
|
||
|
||
**改动**:先 `await` 成功再改 UI,或失败回滚 + toast。递归函数加 visited。
|
||
|
||
## B7-3 发布页注入面(P1)
|
||
|
||
`uni-portal/createPublishHtml/index.js:8` 显式关闭转义:
|
||
|
||
```js
|
||
TE.defaults.escape = false
|
||
```
|
||
|
||
模板中以下插值**未经转义直接进输出**:
|
||
|
||
| 模板位置 | 上下文 | 风险 |
|
||
|---|---|---|
|
||
| `{@h5.url@}` ×2 | `href="{@h5.url@}"` | 未做协议白名单,`javascript:` 可注入 |
|
||
| `{@name@}` | `<title>` / `<h2>` | HTML 注入 |
|
||
| `{@introduction@}` | `<p>` | HTML 注入 |
|
||
| `{@description@}` | `<pre>` | HTML 注入 |
|
||
| `{@android_url@}` `{@ios_url@}` | `href` | 同 h5.url |
|
||
| `{@icon_url@}` `{@$data[$value].qrcode_url@}` | `src` | 属性逃逸 |
|
||
|
||
数据源是应用管理表单(`pages/system/app/add.vue` 的 `name` / `introduction` / `description` / `h5.url`),**由后台账号填写**。所以这是**管理员权限后的持久化注入**,不是匿名入口——但多管理员/低权运营场景下依然是真实攻击面,且发布页是对外公开的。
|
||
|
||
**改动**:在 `createPublishHtml` 渲染前对字段做上下文相关处理:
|
||
|
||
```text
|
||
文本节点(title/h2/p/pre) → HTML 实体转义 & < > " '
|
||
属性值(href/src) → 属性转义 + URL 协议白名单(仅 http/https/cloud)
|
||
JS 字符串(若有 window.$app)→ JSON.stringify
|
||
```
|
||
|
||
不要全局打开 `TE.defaults.escape = true`(模板本身含合法 HTML),要按字段处理。
|
||
|
||
## B7-4 `batch-sms` watcher 崩溃 + 变量语义(P1)
|
||
|
||
`components/batch-sms/batch-sms.vue:177-190`:
|
||
|
||
```js
|
||
const template = this.smsTemplate.find(t => t.value === smsDataModel.templateId)
|
||
let content = smsDataModel.templateData.reduce((res, param) => {
|
||
const reg = new RegExp(`\\$\\{${param.field}\\}`)
|
||
return res.replace(reg, ($1) => param.value || $1) // ← 同 B0 已修的后端问题
|
||
}, template.content) // ← template 可能 undefined
|
||
```
|
||
|
||
两处缺陷:
|
||
|
||
1. `template` 未命中 → `template.content` 直接 `TypeError`。模板被删/切库/加载失败即触发。
|
||
2. `param.value || $1` 把 `0`、`false`、空字符串当作缺失 —— B0 已在 `build-template-data.js` 修了同类问题,**前端这份漏了**,两端语义必须一致。
|
||
|
||
**改动**:`template` 判空提前 return;`param.value === undefined || param.value === null ? $1 : String(param.value)`。
|
||
|
||
## B7-5 死文件 `pay-order/components/test.vue`(P1)
|
||
|
||
已实测**无任何引用**(`rg` 全仓零命中)。内容:
|
||
|
||
```js
|
||
getChartData(query) { } // 空方法
|
||
watch: { query: { handler() { this.options.pageCurrent = 1 } } } // options 未定义 → 一旦挂载必崩
|
||
```
|
||
|
||
`data()` 里也没有 `options`。
|
||
|
||
**改动**:直接删除文件(无引用,零风险)。若判定要保留,必须补 `options` 并实现 `getChartData`。
|
||
|
||
## B7-6 `js.vue` sourceMap 入口判定(P2)
|
||
|
||
```text
|
||
:312 sourceMapEnabled() { return true } ← method,非 computed
|
||
:40 v-if="sourceMapEnabled" ← 模板取到的是函数对象,恒 truthy
|
||
:66 v-if="sourceMapEnabled"
|
||
:81 v-if="sourceMapEnabled"
|
||
:395 getAllData(query) { if (query.indexOf("appid") === -1) ... }
|
||
```
|
||
|
||
两个问题:
|
||
|
||
1. `sourceMapEnabled` 是 method 却被当 computed 用,恒真。原意(注释掉的 `return !!this.uniStat.uploadSourceMapCloudSpaceId`)应是**按配置决定**。结果是所有用户都看到上传入口,点了才失败。
|
||
2. `query.indexOf("appid")` 是**字符串包含判断**,不是字段存在判断。`query` 是拼接串,若某字段值里含 `appid` 子串会误通过;`appid` 存在但为空串也可能漏判。
|
||
|
||
**改动**:`sourceMapEnabled` 改为 computed,同时判断配置 + `$hasPermission`;`getAllData` 改为 `if (!this.query.appid) return`(其他统计页已是此写法)。
|
||
|
||
---
|
||
|
||
## 已核对:不是问题(执行模型勿动,避免白干)
|
||
|
||
| 项 | 实测结论 |
|
||
|---|---|
|
||
| i18n 缺失 | **无缺失**。`i18n/{en,zh-Hans,zh-Hant}.json` 共 47 key,三语齐全,缺翻译 0 条 |
|
||
| `pages/demo/icons/icons.vue` | **不可删**。`pages/system/menu/edit.vue:53` 依赖它做图标选择器 |
|
||
| `pages/demo/table/table` | 在 `pages.json` 注册,静态菜单注释掉了;保留即可 |
|
||
| `uni-stat-app-crash-logs` 大量字段漂移 | 部分为 B1 误报;真实部分见 B5-1,需逐字段核对 schema |
|
||
| `unpackage/` 体积 | 确为生成物,见 B6-2 |
|
||
|
||
## 更新后的执行顺序
|
||
|
||
```text
|
||
B1 门禁可信
|
||
├─► B7-1 菜单环假死 ← P0,插到最前
|
||
├─► B2 空值崩溃
|
||
└─► B7-4 batch-sms 崩溃
|
||
└─► B7-3 发布页转义
|
||
└─► B7-2 菜单性能
|
||
└─► B3 统计错误态
|
||
└─► B4 可用性
|
||
└─► B5 数据合同
|
||
└─► B6/B7-5/B7-6 卫生
|
||
```
|
||
|
||
B1 仍必须最先行(否则 B5 全是盲改);B7-1 是唯一会让**用户浏览器卡死**的缺陷,建议紧接着做。
|