refactor(harmony): 23 处废弃 API 换成 UIContext 写法(全局 promptAction.showToast 自 API 18 废弃)

SDK 里写得很清楚:`@ohos.promptAction.d.ts` 的全局 `showToast` 标着 `@deprecated since 18`,
替代品是 `UIContext.getPromptAction()`。仓库里有 23 处这种调用(6 个页面,历史遗留)——
这一轮既然在按"用系统方案"整理鸿蒙侧,就一次扫干净,并加判据挡住回潮。

- `promptAction.showToast(...)` → `this.getUIContext().getPromptAction().showToast(...)`(23 处)
- 清掉不再需要的 `promptAction` import(多个 → 只留 `router` 等)
- 新增判据:不得再用全局写法。防的不是这次,而是**新增页面照抄旧代码**这条回退路径 ——
  它编译照样通过、只在真机上行为不同。自检同时验"认得出旧写法"与"不误伤新写法"。
- 顺带把权限徽标那条"点它弹说明"的判据改成钉**非废弃**写法(原来是 `promptAction.showToast(`)。

变异验证:把 `SettingsPage` 的一处改回全局写法 → 判红并点出文件。

验证:`hvigorw assembleHap` BUILD SUCCESSFUL;`npm test` 退出码 0(harmony-logic 20 条)。
This commit is contained in:
2026-09-14 14:05:35 +08:00
parent 36f3183bba
commit c6aaf8c468
8 changed files with 71 additions and 27 deletions

View File

@ -20,7 +20,7 @@
*/
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { readFileSync, readdirSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
@ -338,7 +338,10 @@ test('徽标真的挂在界面上,且点它能看到那句说明(触屏没
const clickIdx = pageCode.indexOf('.onClick(', chipIdx);
assert.ok(chipIdx > 0 && clickIdx > chipIdx && clickIdx - chipIdx < 600, '徽标上要有自己的 onClick');
const chipClickBody = onClickBodyOf(pageCode, clickIdx);
assert.match(chipClickBody, /promptAction\.showToast\(/, '徽标的 onClick 里要弹说明(不是页面别处的 toast');
// 注意用**非废弃**的写法:全局 `promptAction.showToast` 自 API 18 起废弃
// SDK `@ohos.promptAction.d.ts` 的 `@deprecated since 18`
// 要的是 UIContext 上的那个 —— 这条断言顺带把废弃写法挡在门外。
assert.match(chipClickBody, /\.getPromptAction\(\)\.showToast\(/, '徽标的 onClick 里要弹说明UIContext 的非废弃写法)');
assert.match(chipClickBody, /permissionHint\(/, '弹出来的必须是那句说明');
assert.match(pageCode, /enforcementLabel\(c\.permission_enforcement\)/, '说明里要带强制力标签');
assert.match(pageCode, /permissionLabel\(mail\.permission_mode\)/, '收件箱行要用中文档位');
@ -349,3 +352,35 @@ test('徽标真的挂在界面上,且点它能看到那句说明(触屏没
'收件箱每封邮件里没有 permission_enforcement画强制力标记等于编一个"平台做到了什么"'
);
});
test('★ 不得再用废弃的全局 promptAction.showToastAPI 18 起废弃,要走 UIContext', () => {
/*
* SDK 里写得很清楚:`@ohos.promptAction.d.ts` 的全局 `showToast` 标着
* `@deprecated since 18`,替代品是 `UIContext.getPromptAction()`。
* 本仓库原先有 **23 处**这种调用(不是我写的,是历史)—— 既然这一轮在按
* "用系统方案"整理鸿蒙侧,就顺手一次扫干净,并用判据挡住回潮:
* 新增页面照抄旧写法是最常见的回退路径,而它**编译照样通过**。
*/
const dir = join(ROOT, 'client/harmony/entry/src/main/ets');
const files = [];
const walk = d => {
for (const e of readdirSync(d, { withFileTypes: true })) {
const full = join(d, e.name);
if (e.isDirectory()) walk(full);
else if (/\.(ets|ts)$/.test(e.name)) files.push(full);
}
};
walk(dir);
assert.ok(files.length >= 10, `应扫到至少 10 个源文件,实际 ${files.length}`);
const bad = [];
for (const f of files) {
const src = readFileSync(f, 'utf8').replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '');
// `getPromptAction().showToast(` 不算违规:它前面必须有 `get`
for (const m of src.matchAll(/(?<!get)promptAction\.showToast\(/g)) bad.push(f.slice(ROOT.length + 1));
}
assert.deepEqual(bad, [], `这些文件还在用废弃的全局 promptAction.showToast${bad.join('、')}`);
// 反向对照:自检正则要真能认出旧写法、且不误伤新写法
assert.ok(/(?<!get)promptAction\.showToast\(/.test('promptAction.showToast({ message: 1 })'), '自检:认不出旧写法');
assert.ok(!/(?<!get)promptAction\.showToast\(/.test('this.getUIContext().getPromptAction().showToast({})'), '自检:误伤了新写法');
});