Files
MailUI4Agents/client/harmony/entry/src/main/ets/pages/SettingsPage.ets
JianFeeeee c6aaf8c468 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 条)。
2026-09-14 14:05:35 +08:00

270 lines
9.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* AgentMail 鸿蒙客户端 — 设置页(账号管理)
* 多账号列表 / 添加新账号 / 删除 / 切换默认账号
*/
import { ApiClient, ApiError } from '../api/ApiClient';
import { Theme } from '../common/Theme';
import { AuthApi } from '../api/AuthApi';
import { AccountManager, AccountInfo } from '../api/AccountManager';
import { SseService } from '../api/SseService';
@Entry
@Component
struct SettingsPage {
@State accounts: AccountInfo[] = [];
@State activeId: string = '';
@State showAddDialog: boolean = false;
@State newDisplayName: string = '';
@State newServer: string = '';
@State newUsername: string = '';
@State newToken: string = '';
@State adding: boolean = false;
private client: ApiClient | null = null;
private acctMgr: AccountManager | null = null;
aboutToAppear(): void {
const ctx = this.getUIContext().getHostContext();
if (ctx !== undefined) {
this.client = ApiClient.getInstance(ctx);
this.acctMgr = AccountManager.getInstance(ctx);
this.acctMgr.load().then(() => {
this.refreshList();
});
}
}
refreshList(): void {
const manager: AccountManager | null = this.acctMgr;
if (manager === null) {
return;
}
this.accounts = manager.getAccounts();
this.activeId = manager.getActiveId();
}
normalizeServer(server: string): string {
let normalized: string = server.trim();
while (normalized.length > 0 && normalized.endsWith('/')) {
normalized = normalized.substring(0, normalized.length - 1);
}
return normalized;
}
async switchTo(accountId: string): Promise<void> {
const manager: AccountManager | null = this.acctMgr;
const client: ApiClient | null = this.client;
if (manager === null || client === null) {
return;
}
const switched: boolean = await manager.switchAccount(accountId);
if (!switched) {
return;
}
const account: AccountInfo | null = manager.getActiveAccount();
if (account !== null) {
client.setBase(account.server);
client.setToken(account.token);
this.getUIContext().getPromptAction().showToast({ message: '默认发信账号已设为 ' + account.displayName });
}
this.refreshList();
}
async removeAccount(accountId: string): Promise<void> {
const manager: AccountManager | null = this.acctMgr;
const client: ApiClient | null = this.client;
if (manager === null) {
return;
}
const removed: boolean = await manager.removeAccount(accountId);
if (!removed) {
return;
}
SseService.getInstance().disconnectAccount(accountId);
const active: AccountInfo | null = manager.getActiveAccount();
if (client !== null) {
if (active !== null) {
client.setBase(active.server);
client.setToken(active.token);
} else {
client.setToken('');
}
}
this.refreshList();
this.getUIContext().getPromptAction().showToast({ message: '账号已删除' });
}
async addNewAccount(): Promise<void> {
const manager: AccountManager | null = this.acctMgr;
const ctx = this.getUIContext().getHostContext();
if (manager === null || ctx === undefined || this.adding) {
return;
}
const displayName: string = this.newDisplayName.trim();
const server: string = this.normalizeServer(this.newServer);
const token: string = this.newToken.trim();
const optionalUsername: string = this.newUsername.trim();
if (displayName.length === 0 || server.length === 0 || token.length === 0) {
this.getUIContext().getPromptAction().showToast({ message: '请填写显示名称、Gateway 地址和 user_key' });
return;
}
this.adding = true;
try {
const validationClient: ApiClient = new ApiClient(ctx);
validationClient.setBase(server);
validationClient.setToken(token);
const user = await new AuthApi(validationClient).me();
const username: string = optionalUsername.length > 0 ? optionalUsername : user.username;
const account: AccountInfo = await manager.addAccount(server, username, token, displayName);
SseService.getInstance().connectForAccount(account.id, account.server, account.token);
this.getUIContext().getPromptAction().showToast({ message: '✅ 添加成功: ' + account.displayName });
this.showAddDialog = false;
this.newDisplayName = '';
this.newServer = '';
this.newUsername = '';
this.newToken = '';
this.refreshList();
} catch (e) {
const apiError = e as ApiError;
this.getUIContext().getPromptAction().showToast({ message: '验证失败: ' + apiError.message });
} finally {
this.adding = false;
}
}
build() {
Column() {
Row() {
Text('‹').fontSize(24).fontColor(Theme.accent).width(40).height(40)
.textAlign(TextAlign.Center)
.onClick(() => { this.getUIContext().getRouter().back(); })
Text('账号管理').fontSize(16).fontWeight(FontWeight.Bold).fontColor(Theme.textPrimary)
.layoutWeight(1)
Text('+').fontSize(24).fontColor(Theme.accent).width(40).height(40)
.textAlign(TextAlign.Center)
.onClick(() => { this.showAddDialog = true; })
}
.width('100%').height(56).padding({ left: 8, right: 8 })
.backgroundColor(Theme.surface)
Divider().color(Theme.border)
if (this.accounts.length === 0) {
Column() {
Text('📭 暂无账号').fontSize(16).fontColor(Theme.textMuted)
Button('添加第一个账号')
.margin({ top: 16 }).backgroundColor(Theme.accent)
.onClick(() => { this.showAddDialog = true; })
}
.width('100%').layoutWeight(1).justifyContent(FlexAlign.Center)
} else {
List({ space: 1 }) {
ForEach(this.accounts, (account: AccountInfo) => {
ListItem() {
this.AccountItem(account)
}
.height(72)
}, (account: AccountInfo) => account.id)
}
.width('100%').layoutWeight(1)
.divider({ strokeWidth: 1, color: Theme.border, startMargin: 16, endMargin: 16 })
}
if (this.showAddDialog) {
Column() {
Column()
.width('100%').layoutWeight(1)
.backgroundColor(Theme.overlay)
.onClick(() => { this.showAddDialog = false; })
Column() {
Text('添加新账号').fontSize(16).fontWeight(FontWeight.Bold).fontColor(Theme.textPrimary)
.margin({ bottom: 16 })
TextInput({ placeholder: '显示名称(必填)', text: this.newDisplayName })
.width('100%').height(44).margin({ bottom: 10 })
.onChange((value: string) => { this.newDisplayName = value; })
TextInput({ placeholder: 'Gateway 地址(必填)', text: this.newServer })
.width('100%').height(44).margin({ bottom: 10 })
.onChange((value: string) => { this.newServer = value; })
TextInput({ placeholder: '用户名(可选)', text: this.newUsername })
.width('100%').height(44).margin({ bottom: 10 })
.onChange((value: string) => { this.newUsername = value; })
TextInput({ placeholder: 'user_key(必填)', text: this.newToken })
.width('100%').height(44).margin({ bottom: 16 })
.type(InputType.Password)
.onChange((value: string) => { this.newToken = value; })
Row() {
Button('取消')
.width(80).height(36).backgroundColor(Theme.surfaceMuted).fontColor(Theme.textMuted)
.onClick(() => { this.showAddDialog = false; })
Blank()
Button(this.adding ? '验证中…' : '添加')
.width(80).height(36).backgroundColor(Theme.accent)
.enabled(!this.adding)
.onClick(() => { this.addNewAccount(); })
}
.width('100%')
}
.width('100%').height('68%')
.padding(16).backgroundColor(Theme.surface)
.borderRadius({ topLeft: 12, topRight: 12 })
}
.width('100%').height('100%')
.position({ x: 0, y: 0 })
}
}
.width('100%').height('100%')
.backgroundColor(Theme.pageBg)
}
@Builder
AccountItem(account: AccountInfo) {
Row() {
Column() {
Row() {
Text(account.displayName)
.fontSize(15).fontWeight(FontWeight.Bold)
.fontColor(account.id === this.activeId ? Theme.accent : Theme.textPrimary)
if (account.id === this.activeId) {
Text(' 默认')
.fontSize(11).fontColor(Theme.accent)
.backgroundColor(Theme.accentSoft).borderRadius(4)
.padding({ left: 4, right: 4, top: 1, bottom: 1 })
.margin({ left: 6 })
}
}
.width('100%')
Text((account.username.length > 0 ? account.username + ' · ' : '') + account.server)
.fontSize(12).fontColor(Theme.textMuted)
.margin({ top: 3 })
.maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis })
}
.layoutWeight(1).height('100%')
.alignItems(HorizontalAlign.Start)
.justifyContent(FlexAlign.Center)
if (account.id !== this.activeId) {
Text('设为默认')
.fontSize(12).fontColor(Theme.accent)
.margin({ right: 12 })
.onClick(() => { this.switchTo(account.id); })
}
Text('删除')
.fontSize(12).fontColor(Theme.danger)
.onClick(() => { this.removeAccount(account.id); })
}
.width('100%').height('100%')
.padding({ left: 16, right: 16 })
.alignItems(VerticalAlign.Center)
.backgroundColor(account.id === this.activeId ? Theme.accentSoft : Theme.surface)
}
}