跨端对齐:授权栏 navigator_only + 组件按页拆分 + 服务器补 permission_options
用户两项裁定落地(均为 ask_user 明确选择):
① 授权栏口径 = navigator_only(照 WebUI 架构)
· 新建 pages/PermissionPanel.ets —— 详情页的决策面板,
对应 MailView.tsx:693 的 PermissionPanel(审批型 / 主动提问 / 已处理 三态)
· 决策入口从授权栏移到 MailDetailPage;MailDetailPage 原来只显示一个
「权限请求」小标签、根本没有决策入口(比 WebUI 少一整块,且反了:
栏里能决策、点进详情反而不能)
· PermissionTab 删掉内联「同意/拒绝」+ 备注框 + decide():
整卡可点 → onOpenMail(对齐 WebUI PermissionList.tsx:81 的 pick())
· PermissionRequest 补 source_account_id(客户端侧记来源,跳详情要定位网关)
② 服务器补 permission_options —— 修一条真实的、跨端共有的缺口
· mails.permission_options 从 INSERT 起就写进去,但**从来没有任何读路径
选过它** ⇒ 详情端点永远返回空。WebUI 的决策面板读 mail.permission_options,
所以提问型的预设选项**两端全部落空**(审批型靠 ['同意','拒绝'] 兜底蒙混)
· GetMailByID 补选该列 + JSON 反序列化(与 cc_list 同款)
③ 组件按页封装(用户要求「以便与 WebUI 一一对应」)
MainPage.ets 4592 → 3192 行
· pages/PermissionTab.ets 720 行 ↔ PermissionList.tsx
· pages/ContactsTab.ets 796 行 ↔ ContactPanel.tsx
· pages/NavDestinations.ets 181 行 ↔ Navigation 壳
· pages/NavShared.ets 65 行 ↔ 跨栏共用件
④ 判据跟着组件搬家(否则静默失效,不是红)
harmony-logic 的 pageCode / harmony-nav 的 navSrc 改为显式文件名单;
harmony-appearance 的 PANE_SOURCES 补 ContactsTab;harmony-contacts 三个
test 并入 ContactsTab;harmony-logic 的决策断言改指 PermissionPanel,
并新增「授权栏不许再有内联决策」两条(navigator_only 的正形状)。
animation-audit:共享元素转场判据从「同文件共址」改为「按 id 找驱动」。
旧形状把 in/out 端必须在同一文件当成代理,而两端**天然在两处**;
抽出写信页(NavDestinations 持有 in 端)后误报。新判据仍要求每个 id
都有 Motion.morph 驱动 —— 变异实测:把驱动换成裸 animateTo 仍判红。
判据:files=34 checks=556 red=1(仅 build-stamp,产物待重构建)
This commit is contained in:
@ -44,7 +44,16 @@ const ETS = join(ROOT, 'client', 'harmony', 'entry', 'src', 'main', 'ets');
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* ★★ 2026-09-23 修:`ContactsTab` 已从 `MainPage.ets` 抽出
|
||||
* (`pages/ContactsTab.ets`)。下面三个判据原来只在 `MAIN` 上找,
|
||||
* 抽出后落在 `ContactsTab` 的代码全部失踪 ⇒ 静默变绿(判了空串)。
|
||||
* 改成把两边并起来 —— 与 `harmony-logic`/`harmony-nav` 的 `PAGE_SOURCES`
|
||||
* 同一个做法(显式名单,不扫整个目录,避免作用域过宽)。
|
||||
*/
|
||||
const MAIN = join(ETS, 'pages', 'MainPage.ets');
|
||||
const CT = join(ETS, 'pages', 'ContactsTab.ets');
|
||||
const ctAndMain = (src) => src; // 占位,下面直接用 code(MAIN)+code(CT)
|
||||
const API = join(ETS, 'api', 'MailApi.ets');
|
||||
const LOGIN = join(ETS, 'pages', 'LoginPage.ets');
|
||||
const GROUP = join(ETS, 'model', 'MailGrouping.ts');
|
||||
@ -79,7 +88,7 @@ test('★ 「写信 / 归档」两个动作在**两种视图**里都有(WebUI
|
||||
* 换个视图就换套确认 UI 只会让人对「自己点了点什么」更没底)。
|
||||
* 鸿蒙两视图都要有 —— 只加一边的话,切到另一边就像"这个功能没了"。
|
||||
*/
|
||||
const src = code(MAIN);
|
||||
const src = code(MAIN) + '\n' + code(CT);
|
||||
const writes = [...src.matchAll(/this\.CardAction\('写信'[\s\S]{0,80}?composeTo\(c\)/g)].length;
|
||||
const archives = [...src.matchAll(/this\.CardAction\('归档'[\s\S]{0,80}?requestArchive\(c\)/g)].length;
|
||||
assert.equal(writes, 2, `「写信」要在卡片视图与列表视图各一处,实际 ${writes} 处`);
|
||||
@ -97,7 +106,7 @@ test('★ 归档要**先确认**,且两种视图共用同一个确认框(不
|
||||
* 文案就会各自漂移,而漂移之后没人会同时看两边。
|
||||
* 判据:确认框的 builder 只有一个定义,两个视图都调它。
|
||||
*/
|
||||
const src = code(MAIN);
|
||||
const src = code(MAIN) + '\n' + code(CT);
|
||||
const defs = [...src.matchAll(/@Builder\s+ArchiveConfirmCard\(/g)].length;
|
||||
assert.equal(defs, 1, `ArchiveConfirmCard 只应有 1 个定义,实际 ${defs} 个`);
|
||||
const calls = [...src.matchAll(/this\.ArchiveConfirmCard\(c\)/g)].length;
|
||||
@ -122,7 +131,7 @@ test('★ 时间戳要按 WebUI 的口径格式化(不是把 ISO 串原样印
|
||||
* —— 不许 `.slice()` 切字符串(那是拿 UTC 的月/日当本地时刻用,
|
||||
* UTC+8 的 09-15 00:30 会显示成 09-14 16:30,而格子/表头全都正常)。
|
||||
*/
|
||||
const main = code(MAIN);
|
||||
const main = code(MAIN) + '\n' + code(CT);
|
||||
assert.doesNotMatch(main, /\+ c\.last_activity\b/,
|
||||
'last_activity 不许原样拼接显示(会印出 ISO 串),要走 shortTimeOf');
|
||||
assert.match(main, /shortTimeOf\(c\.last_activity\)/, '要用 shortTimeOf 格式化');
|
||||
|
||||
Reference in New Issue
Block a user