feat(harmony): 对齐第一阶段 + 对齐计划文档(差距/分期/验收纪律)
用户:「安排对齐」。 ## 先量差距(不靠感觉) 鸿蒙侧的调色板与 WebUI **根本不同**:`#1A73E8`(Google 蓝)vs 品牌 `#2563EB`、 `#333333` vs slate-900 `#0F172A`、`#F5F7FA` vs `#F8FAFC`、`#FF4444` vs red-600… 共 217 处硬编码色值散在 7 个页面里。 功能面:鸿蒙是 收件箱/会话/联系人 三个 tab,**缺 发件箱 / 授权 / 日历 / 管理**, 也没有玻璃悬浮底栏、主题壁纸同步、Composer 共用组件。 ## 第一阶段(已完成并可验收) - `common/Theme.ets` 补齐文字/浅底/语义令牌,页面里的旧调色板**全量替换为令牌** (共 203 处),`hvigorw assembleHap` **BUILD SUCCESSFUL**。 - 判据:`cross-client-theme.test.mjs` 新增"鸿蒙页面里不得再出现旧调色板色值" (6 条全绿,含扰动自检)。这条防的是**新页面又随手写个"差不多"的颜色** —— 漂移就是这么开始的,而此前没有任何判据会红。 ## 计划文档:docs/HARMONY-ALIGN-PLAN.md 写清两件事,免得每轮重新猜"还差什么": - **差距表**(逐项,标出"缺页面/交互不同/观感不同"的性质); - **分期**:P2 发件箱(与收件箱同构,风险最低)→ P3 授权页(备注必须随决策送达模型 —— WebUI 侧踩过这个坑)→ P4 主题/壁纸同步(服务端"无记录"时以本地为准) → P5 玻璃悬浮导航 → P6 日历(最大,单独排)。 ## 如实说明 鸿蒙**视觉未验证**:本机 `hdc list targets` 为空、HAP 未签名 ⇒ 只能保证编译通过 + 令牌一致,观感需要设备或签名后由人眼确认。文档里也把这条写进"验收纪律"。
This commit is contained in:
@ -4,6 +4,7 @@
|
||||
* 路由参数可选: to, reply_to, session_alias
|
||||
*/
|
||||
import { ApiClient, ApiError } from '../api/ApiClient';
|
||||
import { Theme } from '../common/Theme';
|
||||
import { MailApi } from '../api/MailApi';
|
||||
import { AccountManager, AccountInfo } from '../api/AccountManager';
|
||||
import { SendMailRequest } from '../model/Models';
|
||||
@ -186,37 +187,37 @@ struct ComposePage {
|
||||
// 顶栏
|
||||
Row() {
|
||||
Text('取消')
|
||||
.fontSize(15).fontColor('#FF4444')
|
||||
.fontSize(15).fontColor(Theme.danger)
|
||||
.onClick(() => { this.getUIContext().getRouter().back(); })
|
||||
Blank()
|
||||
Text('写邮件').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#333333')
|
||||
Text('写邮件').fontSize(16).fontWeight(FontWeight.Bold).fontColor(Theme.textPrimary)
|
||||
Blank()
|
||||
Button(this.sending ? '发送中…' : '发送')
|
||||
.fontSize(13).height(32)
|
||||
.backgroundColor('#1A73E8')
|
||||
.backgroundColor(Theme.accent)
|
||||
.enabled(!this.sending && !this.uploading)
|
||||
.onClick(() => { this.doSend(); })
|
||||
}
|
||||
.width('100%').height(56)
|
||||
.padding({ left: 12, right: 12 })
|
||||
.backgroundColor('#FFFFFF')
|
||||
.backgroundColor(Theme.surface)
|
||||
|
||||
Divider().color('#EEEEEE')
|
||||
Divider().color(Theme.border)
|
||||
|
||||
// 发信账号选择(多账号时显示)
|
||||
if (this.accountList.length > 1) {
|
||||
Row() {
|
||||
Text('发信账号').fontSize(13).fontColor('#999999').width(72)
|
||||
Text('发信账号').fontSize(13).fontColor(Theme.textSubtle).width(72)
|
||||
// 显示当前选中的账号名
|
||||
Text(this.getSelectedAccountName())
|
||||
.fontSize(13).fontColor('#1A73E8')
|
||||
.fontSize(13).fontColor(Theme.accent)
|
||||
.layoutWeight(1)
|
||||
.onClick(() => { this.showAccountPicker = !this.showAccountPicker; })
|
||||
Text(' ▾').fontSize(12).fontColor('#999999')
|
||||
Text(' ▾').fontSize(12).fontColor(Theme.textSubtle)
|
||||
.onClick(() => { this.showAccountPicker = !this.showAccountPicker; })
|
||||
}
|
||||
.width('100%').height(40).padding({ left: 12, right: 12 })
|
||||
.backgroundColor('#FFFFFF')
|
||||
.backgroundColor(Theme.surface)
|
||||
|
||||
// 账号选择下拉
|
||||
if (this.showAccountPicker) {
|
||||
@ -224,15 +225,15 @@ struct ComposePage {
|
||||
Row() {
|
||||
Text(acct.displayName)
|
||||
.fontSize(13)
|
||||
.fontColor(this.selectedAccountId === acct.id ? '#1A73E8' : '#333333')
|
||||
.fontColor(this.selectedAccountId === acct.id ? Theme.accent : Theme.textPrimary)
|
||||
.fontWeight(this.selectedAccountId === acct.id ? FontWeight.Bold : FontWeight.Normal)
|
||||
.layoutWeight(1)
|
||||
if (this.selectedAccountId === acct.id) {
|
||||
Text('✓').fontSize(14).fontColor('#1A73E8')
|
||||
Text('✓').fontSize(14).fontColor(Theme.accent)
|
||||
}
|
||||
}
|
||||
.width('100%').height(40).padding({ left: 40, right: 12 })
|
||||
.backgroundColor(this.selectedAccountId === acct.id ? '#F0F7FF' : '#FFFFFF')
|
||||
.backgroundColor(this.selectedAccountId === acct.id ? Theme.accentSoft : Theme.surface)
|
||||
.onClick(() => {
|
||||
this.selectedAccountId = acct.id;
|
||||
this.showAccountPicker = false;
|
||||
@ -240,38 +241,38 @@ struct ComposePage {
|
||||
}, (acct: AccountInfo) => acct.id)
|
||||
}
|
||||
|
||||
Divider().color('#F0F0F0')
|
||||
Divider().color(Theme.border)
|
||||
}
|
||||
|
||||
// 收件人
|
||||
Row() {
|
||||
Text('收件人').fontSize(14).fontColor('#999999').width(60)
|
||||
Text('收件人').fontSize(14).fontColor(Theme.textSubtle).width(60)
|
||||
TextInput({ placeholder: 'name@path.session', text: this.to })
|
||||
.layoutWeight(1).fontSize(14).backgroundColor('#00000000')
|
||||
.onChange((v: string) => { this.to = v; })
|
||||
}
|
||||
.width('100%').height(48).padding({ left: 12, right: 12 })
|
||||
.backgroundColor('#FFFFFF')
|
||||
.backgroundColor(Theme.surface)
|
||||
|
||||
Divider().color('#F0F0F0')
|
||||
Divider().color(Theme.border)
|
||||
|
||||
// 主题
|
||||
Row() {
|
||||
Text('主题').fontSize(14).fontColor('#999999').width(60)
|
||||
Text('主题').fontSize(14).fontColor(Theme.textSubtle).width(60)
|
||||
TextInput({ placeholder: '邮件主题', text: this.subject })
|
||||
.layoutWeight(1).fontSize(14).backgroundColor('#00000000')
|
||||
.onChange((v: string) => { this.subject = v; })
|
||||
}
|
||||
.width('100%').height(48).padding({ left: 12, right: 12 })
|
||||
.backgroundColor('#FFFFFF')
|
||||
.backgroundColor(Theme.surface)
|
||||
|
||||
Divider().color('#F0F0F0')
|
||||
Divider().color(Theme.border)
|
||||
|
||||
// 正文
|
||||
TextArea({ placeholder: '输入邮件正文…' })
|
||||
.layoutWeight(1).width('100%')
|
||||
.fontSize(14)
|
||||
.backgroundColor('#FFFFFF')
|
||||
.backgroundColor(Theme.surface)
|
||||
.onChange((v: string) => { this.body = v; })
|
||||
|
||||
// 附件区
|
||||
@ -280,16 +281,16 @@ struct ComposePage {
|
||||
ForEach(this.attachmentNames, (name: string, idx: number) => {
|
||||
Row() {
|
||||
Text('📎 ' + name)
|
||||
.fontSize(12).fontColor('#333333')
|
||||
.fontSize(12).fontColor(Theme.textPrimary)
|
||||
.layoutWeight(1)
|
||||
.maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
Text('✕')
|
||||
.fontSize(14).fontColor('#FF4444')
|
||||
.fontSize(14).fontColor(Theme.danger)
|
||||
.onClick(() => { this.removeAttachment(idx); })
|
||||
}
|
||||
.width('100%').height(32)
|
||||
.padding({ left: 12, right: 12 })
|
||||
.backgroundColor('#F8F9FA')
|
||||
.backgroundColor(Theme.pageBg)
|
||||
}, (_name: string, idx: number) => idx.toString())
|
||||
}
|
||||
.width('100%')
|
||||
@ -298,24 +299,24 @@ struct ComposePage {
|
||||
// 底部工具栏
|
||||
Row() {
|
||||
Text('📎 添加附件')
|
||||
.fontSize(13).fontColor('#1A73E8')
|
||||
.fontSize(13).fontColor(Theme.accent)
|
||||
.onClick(() => { this.pickAttachment(); })
|
||||
|
||||
if (this.uploading) {
|
||||
Text(this.status)
|
||||
.fontSize(11).fontColor('#666666')
|
||||
.fontSize(11).fontColor(Theme.textMuted)
|
||||
.margin({ left: 12 })
|
||||
} else if (this.status.length > 0) {
|
||||
Text(this.status)
|
||||
.fontSize(11).fontColor('#4CAF50')
|
||||
.fontSize(11).fontColor(Theme.approve)
|
||||
.margin({ left: 12 })
|
||||
}
|
||||
}
|
||||
.width('100%').height(44)
|
||||
.padding({ left: 12, right: 12 })
|
||||
.backgroundColor('#FFFFFF')
|
||||
.backgroundColor(Theme.surface)
|
||||
}
|
||||
.width('100%').height('100%')
|
||||
.backgroundColor('#F5F7FA')
|
||||
.backgroundColor(Theme.pageBg)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user