在这里插入图片描述
在这里插入图片描述

一、设计目标

会议排期工具的 UI 目标:用户 3 秒内回答"这个会对我几点的"。设计围绕三个原则:

  1. 时间即主角:所有时间文本加粗、紫色高亮(#7C3AED),UTC 对照用小灰字;
  2. 城市即维度:每个时间都带城市旗标/名称,绝不出现"裸时间";
  3. 实时即信任:世界时钟秒级跳动,让用户相信"这是此刻"。

二、页面结构(组件树)

Scroll(整页滚动)
└─ Column(宽 100%)
   ├─ Row:标题「全球会议排期」+ 🗺️
   ├─ Flex:语言切换(5 语言,紫色选中)
   ├─ Text:会议列表(小标题)
   ├─ ForEach → 会议卡(Column)
   │  ├─ Row:主题(加粗)| 时长徽标(90m 紫底)
   │  ├─ Text:发起人
   │  ├─ Text:UTC 时刻(灰)
   │  └─ Text:本地时刻(紫、加粗)
   ├─ Text:世界时钟(小标题)
   ├─ Column 卡:6 城市当前时间(等宽字体 monospace 对齐秒位)
   ├─ Text:日期风格对比(小标题)
   ├─ Column 卡:full/long/medium/short 四行
   └─ Text:时区换算器(小标题)
      └─ Column 卡(浅紫底 #F5F3FF)
         ├─ Text:UTC 输入时刻
         ├─ Flex:城市选择
         └─ Text:→ 换算结果(大号紫色)

三、色彩与字号规范

主题色 #7C3AED(紫,象征"时间/宇宙"),区分于 01 的蓝(新闻)与 13 的青(钱):

元素 色值 字号 说明
页面标题 #1F2937 22 Bold
会议主题 #1F2937 15 Bold
本地时刻(重点) #7C3AED 14 Bold 用户最关心的
UTC 对照 #9CA3AF 12 辅助信息
时钟时间 #7C3AED 17 Bold + monospace 秒位对齐
换算结果 #7C3AED 18 Bold
发起人/时长 #6B7280 12

fontFamily('monospace') 让不同城市的时分秒逐位对齐,用户扫读快且专业。

四、语言切换栏的设计

语言切换放在标题正下方、内容之上,是页面的"第一操作"。与 01 的下拉面板不同,这里用5 个平铺胶囊按钮——因为会议排期场景语言数量少(简中/繁中/英/日/韩),平铺比折叠更直接:

Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.Start }) {
  ForEach(['zh_CN', 'zh_TW', 'en_US', 'ja_JP', 'ko_KR'] as string[], (code: string) => {
    Text(code === 'zh_CN' ? '🇨🇳 简中' : code === 'zh_TW' ? '🇭🇰 繁中' :
      code === 'en_US' ? '🇺🇸 EN' : code === 'ja_JP' ? '🇯🇵 日' : '🇰🇷 韩')
      .fontSize(12).padding({ left: 10, right: 10, top: 6, bottom: 6 }).borderRadius(16)
      .backgroundColor(this.currentLocale === code ? '#7C3AED' : '#E5E7EB')
      .fontColor(this.currentLocale === code ? Color.White : '#374151')
      .onClick(() => { this.currentLocale = code; })
  }, (code: string) => code)
}
.width('94%').margin({ top: 10 })

设计要点:

  • 选中态"紫底白字":与页面主题色一致,一眼看出当前语言;
  • 标签带国旗 emoji🇨🇳 简中 让语言辨识成本降到零——用户不读文字也能找到自己的语言;
  • 5 个按钮一行放不下自动换行FlexWrap.Wrap 保证小屏也不溢出。

五、会议卡片:UTC 与本地双行并列

会议卡片是本页 UI 的信息层级示范——同一时刻的两个投影(UTC 事实 + 本地体验)上下排列,但视觉权重刻意区分:

ForEach(MEETINGS, (m: Meeting) => {
  Column() {
    Row() {
      Text(m.topic).fontSize(15).fontWeight(FontWeight.Bold).fontColor('#1F2937').layoutWeight(1)
      Text(`${m.durationMin}m`).fontSize(11).fontColor('#7C3AED')
        .padding({ left: 8, right: 8, top: 3, bottom: 3 }).backgroundColor('#F3E8FF').borderRadius(8)
    }.width('100%')
    Row() {
      Text(`${this.T(K.host)}: ${m.host}`).fontSize(12).fontColor('#6B7280').layoutWeight(1)
    }.width('100%').margin({ top: 6 })
    Text(`${this.T(K.utcLabel)}: ${this.meetingUtc(m)}`)
      .fontSize(12).fontColor('#9CA3AF').width('100%').margin({ top: 4 })
    Text(`${this.T(K.local)}: ${this.meetingLocal(m)}`)
      .fontSize(14).fontWeight(FontWeight.Bold).fontColor('#7C3AED').width('100%').margin({ top: 2 })
  }
  .width('94%').padding(14).backgroundColor(Color.White).borderRadius(14).margin({ top: 8 })
}, (m: Meeting) => m.id)

层级设计:

  1. 主题 + 时长徽标(第一眼):主题加粗 15 号,时长 90m 用紫底圆角徽标——开会的人先看"什么会、多久";
  2. 发起人(第二眼):小灰字 12 号,回答"谁定的";
  3. UTC 对照(第三眼,最弱)#9CA3AF 最浅灰,是事实层但非用户主要关注点;
  4. 本地时刻(第四眼,最强):14 号加粗紫色——这是用户真正要的答案,放在最后是"答案在底"的阅读模式:扫完标题、发起人、UTC,最后落到自己的时间。

六、世界时钟:等宽字体逐位对齐

6 个城市的当前时间同屏对比,是"秒位对齐"的典型场景:

Column({ space: 6 }) {
  ForEach(CITIES, (c: City) => {
    Row() {
      Text(`${c.flag} ${c.name}`).fontSize(14).fontColor('#374151').layoutWeight(1)
      Text(clockTz(this.currentLocale, c.tz, this.now))
        .fontSize(16).fontWeight(FontWeight.Bold).fontColor('#7C3AED')
        .fontFamily('monospace')
    }.width('100%').padding({ left: 4, right: 4 })
  }, (c: City) => c.key)
}
.width('94%').padding(14).backgroundColor(Color.White).borderRadius(14).margin({ top: 8 })

fontFamily('monospace') 的价值:普通字体下 08:07:0323:59:58 的数字宽度不同,各行秒针位会左右漂移;等宽字体保证每一位数字占位相同,6 行时间秒位垂直对齐成一条线,扫读速度快一倍。

七、日期风格对比区

四种 dateStyle 竖排成表,前缀小灰字标 FULL/LONG/MEDIUM/SHORT

ForEach(['full', 'long', 'medium', 'short'] as string[], (s: string) => {
  Row() {
    Text(s.toUpperCase()).fontSize(12).fontColor('#6B7280')
      .width('62').textAlign(TextAlign.Start)
    Text(fmtStyle(this.currentLocale, s)).fontSize(13).fontColor('#1F2937')
  }.width('100%')
}, (s: string) => s)

这个区域不是功能,而是教学对比——让用户(和开发者)直观看到同一日期在 8/19/26(英文 short)与 26-8-19(中文 short)之间的写法差异。固定 width('62') 让左侧标签对齐,右侧结果长度不同也互不干扰。

八、时区换算器:视觉闭环

换算器用浅紫底 #F5F3FF 与卡片区分,形成"工具区"的视觉锚点:

Column() {
  Text(`${this.T(K.utcLabel)}: ${fmtInTz(this.currentLocale, 'UTC', Date.UTC(2026, 7, 19, 7, 0))}`)
    .fontSize(13).fontColor('#6B7280').width('100%')
  Text(`${this.T(K.pickTz)}:`).fontSize(13).fontColor('#6B7280').width('100%').margin({ top: 8 })
  Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.Start }) {
    ForEach(CITIES, (c: City, idx: number) => {
      Text(`${c.flag} ${c.name}`)
        .fontSize(12).padding({ left: 10, right: 10, top: 6, bottom: 6 }).borderRadius(14)
        .backgroundColor(this.convertIdx === idx ? '#7C3AED' : '#E5E7EB')
        .fontColor(this.convertIdx === idx ? Color.White : '#374151')
        .onClick(() => { this.convertIdx = idx; })
    }, (c: City) => c.key)
  }.width('100%').margin({ top: 6 })
  Text(`${fmtInTz(this.currentLocale, CITIES[this.convertIdx].tz, Date.UTC(2026, 7, 19, 7, 0))}`)
    .fontSize(18).fontWeight(FontWeight.Bold).fontColor('#7C3AED').width('100%').margin({ top: 10 })
}
.width('94%').padding(14).backgroundColor('#F5F3FF').borderRadius(14).margin({ top: 8, bottom: 16 })

设计闭环:选中的城市按钮是紫底白字,换算结果也是紫色加粗——“选谁,结果就是谁"的视觉闭环,用户不需要读文字也能理解操作与结果的对应关系。结果字号 18 是全页最大的时间,突出"答案”。

九、多语言排版验证清单

检查项 方法
12/24 小时制差异 统一 hour12: false,避免 AM/PM 造成对比错位
长城市名不溢出 城市名 layoutWeight(1) 自适应,时间固定右侧
星期名长度差异 德语星期名(Mittwoch)很长,dateStyle 输出由 intl 保证,UI 不拼
秒位对齐 monospace 字体 + 固定格式,任何语言下时分秒逐位对齐
时间文本方向 时区名/数字为中性内容,LTR 语言下自然显示
语言切换全重算 currentLocale 变化 → 会议/时钟/风格/换算全部刷新

十、设计取舍

  1. 为什么紫色:系列内每应用一个主题色(01 蓝/13 青/02 紫),既统一卡片风格又便于区分;
  2. 为什么 UTC 对照不省略:UTC 是"事实层",本地是"体验层",双行展示让用户既能信任又能看懂——这也是真实会议工具的常见做法(Google Calendar 的时区双行);
  3. 为什么换算器用固定时刻:真实产品应输入任意时刻,但固定演示时刻(春节/独立日等预设日期在应用 10 复用)降低了操作成本,聚焦"换算"本身;
  4. 为什么语言切换用平铺而非下拉:语言只有 5 种,平铺胶囊按钮点击一步到位,比展开面板更快;语言很多时才需要下拉/面板(见应用 01、08)。

十一、小结

时间类 UI 的成败在对比:多个城市的时刻必须逐位对齐(monospace)、同一事实的 UTC 与本地必须双行并列、切换语言必须即时重算。做到这三点,跨时区用户就能像看自己手机时钟一样信任这个工具。

本文的 4 个可复用模式(平铺语言胶囊、UTC/本地双行层级、等宽字体对齐、选中态-结果同色闭环)适用于一切"多时区对比"型界面。下一篇技术篇将深入 intl.DateTimeFormattimeZone 选项、夏令时自动处理与秒级刷新的生命周期管理。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐