chore: directory migration - gateway→server, web→client/electron
This commit is contained in:
269
client/harmony/entry/src/main/ets/pages/SettingsPage.ets
Normal file
269
client/harmony/entry/src/main/ets/pages/SettingsPage.ets
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* AgentMail 鸿蒙客户端 — 设置页(账号管理)
|
||||
* 多账号列表 / 添加新账号 / 删除 / 切换默认账号
|
||||
*/
|
||||
import { ApiClient, ApiError } from '../api/ApiClient';
|
||||
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<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);
|
||||
promptAction.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();
|
||||
promptAction.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) {
|
||||
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('#1A73E8').width(40).height(40)
|
||||
.textAlign(TextAlign.Center)
|
||||
.onClick(() => { this.getUIContext().getRouter().back(); })
|
||||
Text('账号管理').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#333333')
|
||||
.layoutWeight(1)
|
||||
Text('+').fontSize(24).fontColor('#1A73E8').width(40).height(40)
|
||||
.textAlign(TextAlign.Center)
|
||||
.onClick(() => { this.showAddDialog = true; })
|
||||
}
|
||||
.width('100%').height(56).padding({ left: 8, right: 8 })
|
||||
.backgroundColor('#FFFFFF')
|
||||
|
||||
Divider().color('#EEEEEE')
|
||||
|
||||
if (this.accounts.length === 0) {
|
||||
Column() {
|
||||
Text('📭 暂无账号').fontSize(16).fontColor('#777777')
|
||||
Button('添加第一个账号')
|
||||
.margin({ top: 16 }).backgroundColor('#1A73E8')
|
||||
.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: '#EEEEEE', startMargin: 16, endMargin: 16 })
|
||||
}
|
||||
|
||||
if (this.showAddDialog) {
|
||||
Column() {
|
||||
Column()
|
||||
.width('100%').layoutWeight(1)
|
||||
.backgroundColor('#80000000')
|
||||
.onClick(() => { this.showAddDialog = false; })
|
||||
|
||||
Column() {
|
||||
Text('添加新账号').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#333333')
|
||||
.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('#F5F5F5').fontColor('#555555')
|
||||
.onClick(() => { this.showAddDialog = false; })
|
||||
Blank()
|
||||
Button(this.adding ? '验证中…' : '添加')
|
||||
.width(80).height(36).backgroundColor('#1A73E8')
|
||||
.enabled(!this.adding)
|
||||
.onClick(() => { this.addNewAccount(); })
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.width('100%').height('68%')
|
||||
.padding(16).backgroundColor('#FFFFFF')
|
||||
.borderRadius({ topLeft: 12, topRight: 12 })
|
||||
}
|
||||
.width('100%').height('100%')
|
||||
.position({ x: 0, y: 0 })
|
||||
}
|
||||
}
|
||||
.width('100%').height('100%')
|
||||
.backgroundColor('#F5F7FA')
|
||||
}
|
||||
|
||||
@Builder
|
||||
AccountItem(account: AccountInfo) {
|
||||
Row() {
|
||||
Column() {
|
||||
Row() {
|
||||
Text(account.displayName)
|
||||
.fontSize(15).fontWeight(FontWeight.Bold)
|
||||
.fontColor(account.id === this.activeId ? '#1A73E8' : '#333333')
|
||||
if (account.id === this.activeId) {
|
||||
Text(' 默认')
|
||||
.fontSize(11).fontColor('#1A73E8')
|
||||
.backgroundColor('#E3F2FD').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('#777777')
|
||||
.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('#1A73E8')
|
||||
.margin({ right: 12 })
|
||||
.onClick(() => { this.switchTo(account.id); })
|
||||
}
|
||||
|
||||
Text('删除')
|
||||
.fontSize(12).fontColor('#D93025')
|
||||
.onClick(() => { this.removeAccount(account.id); })
|
||||
}
|
||||
.width('100%').height('100%')
|
||||
.padding({ left: 16, right: 16 })
|
||||
.alignItems(VerticalAlign.Center)
|
||||
.backgroundColor(account.id === this.activeId ? '#F0F7FF' : '#FFFFFF')
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user