/* * 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'; import { promptAction } from '@kit.ArkUI'; @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 { 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); promptAction.showToast({ message: '默认发信账号已设为 ' + account.displayName }); } this.refreshList(); } async removeAccount(accountId: string): Promise { 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(); promptAction.showToast({ message: '账号已删除' }); } async addNewAccount(): Promise { 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) { promptAction.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); promptAction.showToast({ message: '✅ 添加成功: ' + account.displayName }); this.showAddDialog = false; this.newDisplayName = ''; this.newServer = ''; this.newUsername = ''; this.newToken = ''; this.refreshList(); } catch (e) { const apiError = e as ApiError; promptAction.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) } }