v61:顶栏标题=模块名 / 抽屉瘦身 + 头像进个人设置 / 删除按钮红底 / 浮层动画 / 日程卡片与手势

用户这一批九条,逐条对应:

1)「页面上左上角的标题,不再是家书了,而是切换到那个模块,就显示哪个模块的标题。
   这样在页面内容部,就不再出现模块的名字标题了。」
   → TopBar 主标题改读 moduleName()(通知/设置/个人设置三个非模块路由也有名字);
     观影/纪念日/读书/笔记/通知五处页内大标题删掉。

2)「按钮,也需要和主题色保持一致,出现文字的时候,例如观影模块,
   在左上角出现的时候,颜色也需要和主题色保持一致。」
   → 标题色走 fbModuleColor(app.activeModule)(一处算,11 个页面不用各写)。

3)「弹框的外圈颜色,跟模块的主题色保持一致。」
   → 日程详情原来传 bookColor(日历本色)⇒ 改 accentColor();
     7 个模块设置浮层补传 accent: this.accent。

4)「删除按钮全部用红色背景。」
   → 日程编辑/人员编辑从红描边改红底白字;详情「删除联系人」从浅红底改红底白字;
     两处确认框统一 FbColors.red。

5)「做几个动画,例如,点击名册列表,应该有一个过渡动画出现弹框,
   点击详情,框变大了,也应该有一个过渡动画,点编辑,也有动画。」
   → 新建 common/FbAnim.ets(fbMaskTransition / fbSheetTransition /
     fbSheetGrowTransition / fbViewTransition),9 个页面共 17 遮罩 + 16 浮层挂上;
     简要卡→详情用 0.96→1 的"继续长大"(0.94 会先缩一下)。

6)「左侧抽屉,把通知消息、个人设置、修改密码、系统设置,都去掉,
   放在个人设置页,就是在点击右侧头像那里。消息通知不用放进去,
   直接在头像旁边那里就可以了。」
   → 抽屉底部那四行整块删除(抽屉只剩品牌区 + 模块列表);
     新建 pages/account/FbAccountPage.ets(整页,__account 分发),
     点头像 switchModule('__account');改密码真打服务端新接口。

7)「日程……日期下面:12本日历可见,本月124条,这句话去掉。
   点击日程弹出的框,编辑按钮也颜色也要修改。
   全天日程,例如农历,上面显示无标题,读不到这条日程,这个有问题。」
   → 删统计行;编辑按钮从写死名册青 #4A7C82 改模块主题色;
     真根因:衍生条目(农历/节气)的 detailFull **一直是 null**
     (它们没有 /events/<id> 可拉,原来直接 return)⇒ 垫 shellOf(),
     并把"整卡报错"改成"照常画内容 + 一行小字";
     空标题兜底从「(无标题)」改成日历本名。

8)「再做几个卡片,先做日程的,这个参考 synccalendar。」
   → FbDayEventPanel.eventRow 照 SyncCalendar:左侧 4vp 圆头色条 + 标题 +
     时间/全天 + 「↻ 重复」徽标 + 右端日历本名(限宽 30%、同色);
     一行一张独立圆角卡(12)+ 描边,卡间 space 8,不再用 Divider 连成一片。

9)「日程,有很多手势,你参考 synccalendar。」
   → 月历上滑→周视图、周条下划→月视图、周条左右滑→换周。
     真机实测两次踩空后定下写法:**竖向必须 parallelGesture(PanGesture)**
     (外层是 Scroll,SwipeGesture 的"快速划动"会被它的内置滚动先吃掉,
      gesture/priorityGesture 都不行);**横滑用 gesture(PanGesture)**
     (同一节点两条方向不同的 parallelGesture 会互相压制);
     方向按累计位移判、并要求 |dy| > |dx|。切视图走 animateTo + fbViewTransition。

验证:
· 编译 BUILD SUCCESSFUL
· ArkTS 守卫 493/0;Schema 列守卫 12/0;反向验证 39/0(新增 22 条注入逐条确认能变红)
· 服务端接口 e2e 20/0(独立副本 + 真 MariaDB,5 种错误路径 + 原令牌仍有效)
· 真机 _fb_v61_verify.py 21/0(6 组全过);像素采样确认浮层主题色环实测存在
This commit is contained in:
2026-10-19 12:19:54 +08:00
parent 1a67247407
commit 853b0e0b20
22 changed files with 1252 additions and 362 deletions
+77 -6
View File
@@ -14,7 +14,8 @@
* ⇒ 三种态都要画:加载中 / 成功 / 失败。别只画成功态。
*/
import { FbColors, FbMetric } from '../common/Theme';
import { FbColors, FbMetric, FbTint } from '../common/Theme';
import { FbModuleDef, fbModuleOf, fbThemeVars } from '../model/Modules';
import { FbCalEventFull } from '../data/FbCalRepo';
import { FbCalBook } from '../model/Types';
import { FbDot } from './Widgets';
@@ -33,6 +34,13 @@ export struct FbEventSheet {
/** 这条日程属于哪本日历(列表里那份已知,用来显示本色/名字) */
@Param bookName: string = '';
@Param bookColor: string = '#9AA0A6';
/**
* 外圈环色 —— **模块主题色**(用户 2026-10-19:「弹框的外圈颜色,
* 跟模块的主题色保持一致」)。空 = 日程模块色。
* ⚠️ 与 `bookColor` 分工不同:环是"我在哪个模块里",
* 标题左侧那个点才是"这条日程属于哪本日历"(一本模块下可以有多本)。
*/
@Param accent: string = '';
/** 能不能编辑(不能写的日历本不给"编辑"按钮) */
@Param canEdit: boolean = false;
@Event onClose: () => void = (): void => {
@@ -40,6 +48,52 @@ export struct FbEventSheet {
@Event onEdit: () => void = (): void => {
};
/** 环色:显式给了就用给的,否则取日程模块色(与日程页其它浮层一致) */
private accentColor(): string {
if (this.accent !== '') {
return this.accent;
}
const m: FbModuleDef | undefined = fbModuleOf('calendar');
return m !== undefined ? fbThemeVars(m.color).brand : FbTint.brand;
}
/**
* 标题文字。
*
* 🔴 2026-10-19:原来为空时写死「(无标题)」—— 但那条文案在**农历/节气**
* 这些衍生条目上会误导(用户看到"农历显示无标题"以为数据错了,
* 实际是标题为空时的兜底文案不合适)。派生条目本来就该用**日历本名**
* 当兜底(「农历」「节假日」本身就是它是什么),自建日程才用「未命名日程」。
*/
private titleText(): string {
const e: FbCalEventFull | null = this.event;
if (e === null) {
return '';
}
if (e.title !== '') {
return e.title;
}
// 日历本名能说明"这是什么"(农历/节假日/节气…)
if (this.bookName !== '') {
return this.bookName;
}
return '未命名日程';
}
/**
* 详情加载失败的说明。
*
* 🔴 2026-10-19:原来加载失败会把**整张卡**换成一句错误文案 ——
* 而本地列表那份本来就能画标题/时间/地点 ⇒ 现在改成
* **照常画内容 + 底下加一行小字说明**(见 `openEvent` 的说明)。
*/
private errorNote(): string {
if (this.error === '') {
return '';
}
return '部分详情没读回来:' + this.error;
}
/** 时间显示:`10月15日 周三 09:00 - 10:30` / `全天 10月15日 周三` */
private timeText(): string {
const e: FbCalEventFull | null = this.event;
@@ -150,13 +204,16 @@ export struct FbEventSheet {
// (用户:「所有弹框都加线,保持一致」)。环色用**这本日历的颜色**,
// 一眼能看出这条日程属于哪个日历本。
Column() {
FbSheetRing({ radius: FbMetric.radius, ringColor: this.bookColor }) {
FbSheetRing({ radius: FbMetric.radius, ringColor: this.accentColor() }) {
Column({ space: 0 }) {
// ---- 标题区 ----
Row({ space: 10 }) {
FbDot({ dia: 12, fillC: this.bookColor })
Text(this.event !== null && this.event.title !== ''
? this.event.title : '(无标题)')
/* 🔴 2026-10-19:标题为空时要**说清这是什么**,而不是写「(无标题)」。
农历 / 节气这类衍生条目的标题服务端是给了的(如「九月初一」),
真为空的情况主要是「没填标题的自建日程」—— 那种回「未命名日程」
比「(无标题)」更像人话。 */
Text(this.titleText())
.fontSize(FbMetric.fontTitle)
.fontWeight(FontWeight.Medium)
.fontColor(FbColors.ink)
@@ -189,7 +246,10 @@ export struct FbEventSheet {
.padding({ top: 20, bottom: 20 })
.justifyContent(FlexAlign.Center)
} else if (this.event === null) {
Text(this.error !== '' ? ('读不到这条日程:' + this.error) : '读不到这条日程')
// 正常情况下不会走到这里(`openEvent` 一定会垫一份壳);
// 只有"打开浮层时状态被清掉"这种瞬时态才可能空着 ——
// 所以这里说的是"正在读取",不是"读不到"。
Text('正在读取…')
.fontSize(FbMetric.fontSmall)
.fontColor(FbColors.faint)
.width('100%')
@@ -215,6 +275,14 @@ export struct FbEventSheet {
if (this.event.note !== '') {
this.row('备注', this.event.note)
}
// 🔴 详情没拉全时给一行小字(而不是把整张卡变成"读不到")
if (this.errorNote() !== '') {
Text(this.errorNote())
.fontSize(FbMetric.fontTiny)
.fontColor(FbColors.faint)
.width('100%')
.padding({ top: 8 })
}
Row().height(8)
}
.width('100%')
@@ -247,13 +315,16 @@ export struct FbEventSheet {
this.onClose();
})
if (this.canEdit && this.event !== null) {
/* 🔴 用户 2026-10-19:「点击日程弹出的框,编辑按钮也颜色也要修改。」
⇒ 原来写死名册青 #4A7C82,在日程页里跟模块色(棕)不一致。
改成 `accentColor()`(= 日程模块主题色,与卡片外环同色)。 */
Text('编辑日程')
.fontSize(FbMetric.fontSmall)
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.layoutWeight(1)
.height(42)
.backgroundColor('#4A7C82')
.backgroundColor(this.accentColor())
.borderRadius(FbMetric.radiusS)
.onClick((): void => {
this.onEdit();