v0.7.0 接上真实服务器:登录 / 设备会话 / 全量同步与各模块真实数据
从「演示数据壳子」走到「真的能连家里的服务器用」。
登录(用户 2026-10-17「完整的登录功能」)
· 首次启动先填服务器地址 → /api/v1/ping 自报门户(认得出"这地址上真是家书")
· 手机号或用户名 + 密码 → 拿令牌;失败提示统一,不泄露账号是否存在
· FbDeviceStore:首次启动生成并持久化设备 UUID(三方应用拿不到 UDID),
设备名取机型(marketName),并上报 platform / app_version
设备会话(v57,用户 2026-10-17)
· 一把令牌 = 一台设备的一条会话;每次启动打一次 /me(有网就验)
· 两种锁分开:need_login(401/被踢 → 清令牌)与 offline_expired
(离线超 24h → 只锁界面、不清数据、联网自动恢复)——
混成一种就会违背用户要的"一直联网就不用每天输密码"
· 运行期任何请求 401 → 网络层全局回调立刻锁定跳登录页(FbHttp 的 authProbe
让登录/校验类请求跳过,避免"两个地方同时跳登录页")
· 退出登录:先清本地令牌(主防线),再尽力通知服务端
· 设置页显示版本号与「这台设备」
数据层
· FbDb / FbSchema / FbParse / 各 Repo(日程 / 名册 / 观影 / 模块)+ FbSyncAll
· 首页改为服务端 /home(农历/节气/纪念日/生日/天气/统计/往年的今天)
· 日程页用 FbDayEventPanel,与网页端显示方式/红线/并排三处一致
验证:ArkTS 静态守卫 231/0;hvigor 编译 BUILD SUCCESSFUL(entry-default-signed.hap)。
This commit is contained in:
@@ -176,7 +176,7 @@ export struct FbSectionTitle {
|
||||
*/
|
||||
@ComponentV2
|
||||
export struct FbAvatar {
|
||||
/** 显示名(取首字) */
|
||||
/** 显示名(取首字;也是**没有图片时**的回落) */
|
||||
@Param name: string = '';
|
||||
/** 底色(由业务侧算好传进来) */
|
||||
@Param color: string = '#A84A28';
|
||||
@@ -184,6 +184,17 @@ export struct FbAvatar {
|
||||
@Param dia: number = 36;
|
||||
/** 字号(vp);不传则按直径推算 */
|
||||
@Param fontSizeVp: number = 0;
|
||||
/**
|
||||
* 头像图 URL(**空 = 用色块字回落**)。
|
||||
*
|
||||
* 🔴 为什么要支持真图(用户 2026-10-13:"名册的头像怎么都没有?"):
|
||||
* 之前这里只有色块字,看起来像"没有头像"。
|
||||
* 实测名册 800 人里只有 19 人传过头像 ⇒ **两者都要有**:
|
||||
* 有图的显示图、没图的回落到色块字(这是绝大多数)。
|
||||
* ⚠️ URL 由调用方用 `fbImageUrl(key, token)` 拼好传进来 ——
|
||||
* `Image()` 不支持自定义请求头,令牌只能走查询串(见 `fbImageUrl` 的说明)。
|
||||
*/
|
||||
@Param imageUrl: string = '';
|
||||
|
||||
/** 取名字的第一个字(含中文名的姓) */
|
||||
private initial(): string {
|
||||
@@ -195,15 +206,29 @@ export struct FbAvatar {
|
||||
}
|
||||
|
||||
build() {
|
||||
Text(this.initial())
|
||||
.width(this.dia)
|
||||
.height(this.dia)
|
||||
.borderRadius(this.dia / 2)
|
||||
.backgroundColor(this.color)
|
||||
.fontColor(Color.White)
|
||||
.fontSize(this.fontSizeVp > 0 ? this.fontSizeVp : Math.round(this.dia * 0.42))
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.textAlign(TextAlign.Center)
|
||||
// ⚠️ 用 if/else 而不是"图层叠":两种形态的**尺寸来源**不同
|
||||
// (Image 有 intrinsic size,Text 靠 width/height)——
|
||||
// 叠起来容易出现"图把字盖住但字还在占位"的错位。
|
||||
if (this.imageUrl !== '') {
|
||||
Image(this.imageUrl)
|
||||
.width(this.dia)
|
||||
.height(this.dia)
|
||||
.borderRadius(this.dia / 2)
|
||||
// 加载失败/慢时先显示底色,避免"一片空白"
|
||||
.backgroundColor(this.color)
|
||||
.objectFit(ImageFit.Cover)
|
||||
.alt($r('app.media.fb_logo'))
|
||||
} else {
|
||||
Text(this.initial())
|
||||
.width(this.dia)
|
||||
.height(this.dia)
|
||||
.borderRadius(this.dia / 2)
|
||||
.backgroundColor(this.color)
|
||||
.fontColor(Color.White)
|
||||
.fontSize(this.fontSizeVp > 0 ? this.fontSizeVp : Math.round(this.dia * 0.42))
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.textAlign(TextAlign.Center)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,43 +428,26 @@ export struct FbDotLine {
|
||||
}
|
||||
}
|
||||
|
||||
/** 一条「三格数字」统计条(首页近七天:日程 / 待办 / 逾期) */
|
||||
@ComponentV2
|
||||
export struct FbStatTriple {
|
||||
@Param labelA: string = '';
|
||||
@Param valueA: string = '';
|
||||
@Param labelB: string = '';
|
||||
@Param valueB: string = '';
|
||||
@Param labelC: string = '';
|
||||
@Param valueC: string = '';
|
||||
/** C 项是否用警示红(逾期数) */
|
||||
@Param cAlarm: boolean = false;
|
||||
|
||||
@Builder
|
||||
cell(label: string, value: string, alarm: boolean) {
|
||||
Column({ space: 2 }) {
|
||||
Text(value)
|
||||
.fontSize(20)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor(alarm ? FbColors.red : FbColors.ink)
|
||||
Text(label)
|
||||
.fontSize(FbMetric.fontTiny)
|
||||
.fontColor(FbColors.muted)
|
||||
}
|
||||
.layoutWeight(1)
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
}
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
this.cell(this.labelA, this.valueA, false)
|
||||
this.cell(this.labelB, this.valueB, false)
|
||||
this.cell(this.labelC, this.valueC, this.cAlarm)
|
||||
}
|
||||
.width('100%')
|
||||
.padding({ top: 10, bottom: 10 })
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 一条「N 格数字」统计条 —— 🔴🔴 **已删除(v54b,2026-10-17)**。
|
||||
*
|
||||
* 原来这里有个 `FbStatTriple`(三格:日程 / 待办 / 逾期),内部用
|
||||
* `@Builder cell(label, value, alarm)` 画每一格。
|
||||
*
|
||||
* 用户 2026-10-17 报「概述卡……**日程、在做、待办的数量是错误的**」,
|
||||
* 真机实测:接口与端上缓存都是 `{1,3,2,0}`(正确),界面却是 `0/0/0`。
|
||||
* 根因:SDK 规则 `r/quick-rules/05-state.md` →
|
||||
* > **@Builder 参数传递**:「**两个及以上参数不触发刷新**」
|
||||
* ⇒ `cell()` 那份子树只按**初始值**渲染一次(那时还是默认的 0),
|
||||
* 数据回来、`build()` 重跑了,但**这个多值 @Builder 的子树不重建**。
|
||||
*
|
||||
* ⇒ **删除而不是修补**,理由:
|
||||
* ① 它当时**已无人引用**(首页改成四格 + `FbStatCell` 之后);
|
||||
* ② 留着它,以后有人"顺手用一下"就会原样复发(本项目已踩过 6 次这个坑);
|
||||
* ③ 它的三格形态也不再匹配需求(现在要四格)。
|
||||
* ⇒ 新的写法用 **`components/FbStatCell.ets`**(`@ComponentV2` + `@Param`,
|
||||
* **@Param 参与观察**),需要几格就摆几个。**不要再恢复 `@Builder` 版本。**
|
||||
*/
|
||||
|
||||
/**
|
||||
* 进度条(读书进度、旅程完成度…)。
|
||||
|
||||
Reference in New Issue
Block a user