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:
@@ -7,8 +7,16 @@
|
||||
*
|
||||
* 三条形态,同一个组件:
|
||||
* · **常驻侧栏**(宽屏:窗口短边 ≥ 600vp)—— 固定在左边,占 264vp;
|
||||
* · **左滑出层**(手机,从左边缘向右滑)—— 覆盖内容,点遮罩或选中项即收起;
|
||||
* · **右滑出层**(手机,从右边缘向左滑)—— 同上,只是贴右边(右手单手持机顺手)。
|
||||
* · **左滑出层**(手机)—— 覆盖内容,点遮罩或选中项即收起;
|
||||
* · **右滑出层**(手机)—— 同上,只是贴右边(右手单手持机顺手)。
|
||||
*
|
||||
* 🔴 抽屉**从哪边出**由「**握姿**」决定(用户 2026-10-16 第 4 条):
|
||||
* 左手握 → `app.drawerSide = 'left'`;右手握 → `'right'`。
|
||||
* 逻辑在 `common/FbGrip.ets`(用官方 `multimodalAwareness.motion` 的
|
||||
* `HoldingHandStatus`),不在本组件里。
|
||||
* 🔴 **打开方式只有一种:点顶栏左侧的家书图标**(`pages/Index.ets`)。
|
||||
* ⚠️ **横向滑动开抽屉的旧手势已删**(用户要求)—— 它与页面里的横滑、
|
||||
* 与"点人名拨号"在 `parallelGesture` 下**并行触发**,冲突无法根治。
|
||||
*
|
||||
* ⚠️ 这里**不用 SideBarContainer**:它的控制按钮与「滑出」是内建的一套,
|
||||
* 样式(图标、位置、宽度动画)很难与家书的视觉统一,且它只能有一层侧栏
|
||||
@@ -21,6 +29,16 @@ import { FbAppState, fbAppState } from '../common/Store';
|
||||
import { FbModuleDef, FB_MODULES, fbDefaultNavModules, fbThemeVars } from '../model/Modules';
|
||||
import { FbAvatar } from './Widgets';
|
||||
|
||||
/**
|
||||
* 底部手势条区域的留白(vp)。
|
||||
*
|
||||
* 🔴 应用已开 `setWindowLayoutFullScreen(true)`(见 EntryAbility):
|
||||
* 内容会铺到屏幕最下沿,而**系统手势条已隐藏**(用户要求"下面没有任何的条")
|
||||
* ⇒ 手势区**没有任何视觉提示**,贴着底边的元素很容易被"从下往上滑"误触。
|
||||
* 这里留一点缓冲,是给"手势区"而不是给"某个控件"。
|
||||
*/
|
||||
const FB_BOTTOM_GAP: number = 16;
|
||||
|
||||
@ComponentV2
|
||||
export struct FbDrawer {
|
||||
/** 全局状态(父组件传入,保证与页面同一份实例) */
|
||||
@@ -60,7 +78,7 @@ export struct FbDrawer {
|
||||
}
|
||||
.width('100%')
|
||||
// 顶部内边距 = 状态栏高度 + 一点呼吸,保证不压状态栏
|
||||
.padding({ left: 18, right: 12, top: 16, bottom: 10 })
|
||||
.padding({ left: 18, right: 12, top: 16 + this.app.statusBarH, bottom: 10 })
|
||||
}
|
||||
|
||||
/** 一个模块行 */
|
||||
@@ -112,29 +130,52 @@ export struct FbDrawer {
|
||||
.color(FbColors.line2)
|
||||
.margin({ bottom: 6 })
|
||||
|
||||
this.footerRow('fb_ic_bell', '通知消息', this.app.unread > 0 ? this.app.unread.toString() : '')
|
||||
this.footerRow('fb_ic_user', '个人设置', '')
|
||||
this.footerRow('fb_ic_lock', '修改密码', '')
|
||||
this.footerRow('fb_ic_bell', '通知消息',
|
||||
this.app.unread > 0 ? this.app.unread.toString() : '', '__notifications')
|
||||
this.footerRow('fb_ic_user', '个人设置', '', '__settings')
|
||||
// ⚠️ 下面两项端上**还没做页面**,传空 route ⇒ 灰显、不可点。
|
||||
// 别给它们绑 `__password` / `__system` —— Index.ets 没这两个分支,
|
||||
// 点下去是**空白页**,比"点不动"更让人困惑。
|
||||
this.footerRow('fb_ic_lock', '修改密码', '', '')
|
||||
if (this.app.session.me.role === 'admin') {
|
||||
this.footerRow('fb_ic_gear', '系统设置', '')
|
||||
this.footerRow('fb_ic_gear', '系统设置', '', '')
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.padding({ left: 12, right: 12, bottom: 10 })
|
||||
// 🔴 bottom 给底部**手势条区域**留一点(全屏布局下抽屉会铺到屏幕最下沿,
|
||||
// 底部这两行若贴着边,手指从下往上滑时容易误触到系统手势)。
|
||||
.padding({ left: 12, right: 12, bottom: 10 + FB_BOTTOM_GAP })
|
||||
}
|
||||
|
||||
/** 底部一行 */
|
||||
/**
|
||||
* 底部一行(通知消息 / 个人设置 / 修改密码 / 系统设置)。
|
||||
*
|
||||
* 🔴 必须带 `route` 并绑 onClick —— 之前这四行**根本没有点击处理**,
|
||||
* 界面上是个死按钮(点下去毫无反应)。
|
||||
* 排查记录:点「个人设置」后仍停在首页,看界面树发现该元素
|
||||
* `clickable=false` 且整行没有任何可点击祖先 —— 就是这个原因。
|
||||
* ⚠️ 与模块项(`moduleRow`)不同:这四项的路由 key 是 `__xxx` 形式,
|
||||
* 不是 `FB_MODULES` 里的模块,走同一个 `switchModule` 分发
|
||||
* (Index.ets 里用 `activeModule === '__settings'` 渲染对应页面)。
|
||||
*
|
||||
* ⚠️ `route` 传空串表示"**这个页面还没做**" ⇒ 不绑 onClick,且文字降为灰、
|
||||
* 保持不可点。为什么不给它绑个假跳转:那会跳到**空白页**
|
||||
* (Index.ets 里没有对应分支),比"点了没反应"更让人困惑。
|
||||
* 现状:`__notifications` / `__settings` 已有页面;
|
||||
* `修改密码` / `系统设置` **还没做**(Web 端有,端上待开发)。
|
||||
*/
|
||||
@Builder
|
||||
footerRow(iconName: string, label: string, badge: string) {
|
||||
footerRow(iconName: string, label: string, badge: string, route: string) {
|
||||
Row({ space: 12 }) {
|
||||
Image(FbIcon.ui(iconName))
|
||||
.width(17)
|
||||
.height(17)
|
||||
.renderMode(ImageRenderMode.Template)
|
||||
.fillColor(FbColors.muted)
|
||||
// 未实现的项图标也变灰,明示"暂不可用"
|
||||
.fillColor(route === '' ? FbColors.faint : FbColors.muted)
|
||||
Text(label)
|
||||
.fontSize(FbMetric.fontSmall)
|
||||
.fontColor(FbColors.ink)
|
||||
.fontColor(route === '' ? FbColors.faint : FbColors.ink)
|
||||
.layoutWeight(1)
|
||||
if (badge.length > 0) {
|
||||
Text(badge)
|
||||
@@ -148,6 +189,11 @@ export struct FbDrawer {
|
||||
.width('100%')
|
||||
.padding({ left: 10, right: 10, top: 9, bottom: 9 })
|
||||
.borderRadius(FbMetric.radiusS)
|
||||
.onClick(() => {
|
||||
if (route !== '') {
|
||||
this.app.switchModule(route); // switchModule 内部会收起抽屉
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 当前是否选中该模块 */
|
||||
@@ -263,41 +309,22 @@ export struct FbDrawerShell {
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.backgroundColor(FbColors.paper)
|
||||
// 🔴 横向滑动开抽屉(用户 2026-10-12 定的规则)。
|
||||
// 🔴🔴 **横向滑动开抽屉的手势已删除**(用户 2026-10-16 第 3、4 条)。
|
||||
//
|
||||
// ⚠️ **不要判断"起点是否贴屏幕边缘"** —— 用户实测反馈:屏幕边缘是
|
||||
// **系统手势区**(返回/侧边栏),从边缘往里滑的事件根本轮不到应用处理,
|
||||
// 我们无法控制。所以判据只能是"**在应用内部水平滑动**":
|
||||
// 向右滑 → 抽屉从左边出;向左滑 → 抽屉从右边出。
|
||||
// 这样左手持机时往右划、右手持机时往左划,单手都顺。
|
||||
// 用户原话:「这个列表上左滑、右滑和点击后打电话的事件冲突了……
|
||||
// 如果实在不行,就把左滑、右滑弹出抽屉这个功能去掉吧,
|
||||
// 只保留点击标题或图标后弹出抽屉的功能。」
|
||||
// 并再次强调:「**先这样做,把滑动出抽屉这个功能先去掉**,
|
||||
// 因为它现在在很多地方都跟别的功能有冲突。」
|
||||
//
|
||||
// ⚠️ `offsetX` 的单位是 **vp**(SDK 原文 "in vp"),不要再除以 density ——
|
||||
// 除一次会把位移缩到 1/3,导致阈值永远达不到、手势"看起来没生效"。
|
||||
// 历史:`parallelGesture(PanGesture)` + `fbHScrollBusy()` 的那套"让位"
|
||||
// 机制(见 git 历史)**治不了根本** —— 因为 `parallelGesture` 是**并行**识别,
|
||||
// 它和应用自己的横滑/点按/拨号**同时**成立,没有"谁先抢到"的机制。
|
||||
// 名册里"滑动既弹抽屉又跳拨号"就是这个并行识别的必然结果。
|
||||
// ⇒ 唯一可靠的办法是**不用横滑手势**。
|
||||
//
|
||||
// ⚠️ 用 `parallelGesture` 而不是 `gesture`:内容区自己还有竖向滚动
|
||||
// (以及纪念日/财务/任务的横向滚动条),用 gesture 会把它们抢掉。
|
||||
// 代价是横向滚动条扫得猛时也可能触发 —— 所以阈值给到 80vp,
|
||||
// 轻扫(浏览横向列表)不会误开。
|
||||
.parallelGesture(
|
||||
PanGesture({ direction: PanDirection.Horizontal, distance: 30 })
|
||||
.onActionEnd((e: GestureEvent) => {
|
||||
// 宽屏下抽屉常驻,不需要手势
|
||||
if (this.app.wideLayout) {
|
||||
return;
|
||||
}
|
||||
const dx: number = e.offsetX; // vp
|
||||
// 向右滑 ⇒ 抽屉在左
|
||||
if (dx > 80) {
|
||||
this.app.drawerSide = 'left';
|
||||
this.app.drawerOpen = true;
|
||||
return;
|
||||
}
|
||||
// 向左滑 ⇒ 抽屉在右
|
||||
if (dx < -80) {
|
||||
this.app.drawerSide = 'right';
|
||||
this.app.drawerOpen = true;
|
||||
}
|
||||
})
|
||||
)
|
||||
// 抽屉入口保留在:**顶栏左侧的家书图标**(`pages/Index.ets` 的 `topBarSlot`)。
|
||||
// 抽屉从哪边出,改由「**握姿**」决定(见 `FbGripWatcher` / `app.drawerSide`):
|
||||
// 左手握 → 从左边出;右手握 → 从右边出。
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user