v67:读书模块补齐(书能点进去 / 加一本 / 读书笔记 / 统计)
用户 2026-10-20:「其他的功能也逐步完成……读书点不进去,也没法加书,
设置也没有任何的东西。」
## 先修三处「对着服务端抄错的口径」(都不报错,只是显示是错的)
1. 状态值:服务端 `Book::STATUS` 只有 wish/reading/done/paused,**没有 want**;
`Book::status()` 遇到不认识的值会静默改成 `wish`,而端上分组键写的 `want`
⇒ 书架里「想读」那一组**整组不显示**(页头还数着它,看着像书丢了)。
`paused`(搁置)同样没列 ⇒ 搁置的书也人间蒸发。
2. 评分:服务端 `rating` 是 0–10,端上当 0–5 用 ⇒ 8 分显示成 `8.0/5`。
现在解析时折半、写回时 ×2。
3. 进度:服务端 `progress` 是「读到第几章」,端上当百分比 ⇒ 读到第 30 章 = 30%。
现在按 `chapter_count` 换算,没解析过章节的书不画假进度。
## 补齐三个死掉的入口
- 书行整行可点 → `FbBookSheet`(状态 / 评分 / 章节进度 / 读书笔记 / 删除二次确认)
- 页头「+ 加一本」→ 同一浮层的新建态(书名 / 作者 / 状态)
- 设置「读书统计」→ 端上现算(藏书/在读/读完/想读/搁置/笔记条数);
另两条(导入笔记 / 微信读书)要文件选择与授权,仍标「网页端」,不摆假入口
## 服务端能力边界(照实做)
- `PATCH /books/<id>` 只认 status / rating ⇒ 详情里不给改书名/作者的输入框
- 章节进度只读(`progress` 由阅读器翻页写,接口没有回写入口)
- 读书笔记走真实接口 `GET/POST /books/<id>/notes`
## 验证
- `hvigorw assembleHap` → BUILD SUCCESSFUL
- `_fb_arkts_guard.js` → 797 / 0(新增 groupV67 28 条,含「端上分组键 ==
服务端枚举」的跨语言对照)
- `_fb_v59d_falsify.py` → 130 / 0(v67 新增 13 条注入全部变红)
- ⚠️ 设备仍断连(`hdc list targets` → `[Empty]`),真机未验收
This commit is contained in:
@@ -2,10 +2,17 @@
|
||||
* 家书 FamilyBook · 读书模块(鸿蒙端)
|
||||
*
|
||||
* 对应 Web 端 `templates/books/index.php`(书架 + 上传解析 + 在线读 + 笔记 + 统计)。
|
||||
* 端上先做**书架**这一层:按状态分组(在读 / 想读 / 读完),
|
||||
* 每本书显示作者、评分、笔记数、阅读进度。
|
||||
* 端上做**书架 + 一本书的详情**这两层:
|
||||
* · 书架按状态分组(在读 / 想读 / 搁置 / 读完),显示作者、评分、笔记数、进度;
|
||||
* · 点一本书 → `FbBookSheet`(状态 / 评分 / 章节进度 / 读书笔记 / 删除);
|
||||
* · 页头 + → 同一浮层的新建态(书名 / 作者 / 状态);
|
||||
* · 设置菜单 → 读书统计(端上现算)+ 两条网页端能力的入口说明。
|
||||
*
|
||||
* 「在线读」「上传 EPUB 解析」「笔记导入」这些属于交互+文件能力,留给第二轮。
|
||||
* 🔴 v67(用户 2026-10-20「其他的功能也逐步完成……读书点不进去」):
|
||||
* 原来这里**只有书架**:书行没有 `onClick`、页头"上传/统计"按钮没有 `onTap`、
|
||||
* 设置三项全是空 `action`。三处现在都接上了。
|
||||
*
|
||||
* 「在线读」「上传 EPUB 解析」「笔记导入」属于交互+文件能力,仍在网页端。
|
||||
*/
|
||||
|
||||
import { FbColors, FbMetric, fbTint, FbTint, FB_MASK } from '../../common/Theme';
|
||||
@@ -19,6 +26,7 @@ import { FB_DOCK_RESERVE } from '../../components/FloatDock';
|
||||
import { fbOnScroll, fbOnTouch } from '../../common/FbScroll';
|
||||
import { fbMaskTransition, fbSheetTransition } from '../../common/FbAnim';
|
||||
import { FbModuleSettingsSheet } from '../../components/FbModuleSettingsSheet';
|
||||
import { FbBookSheet, FbBookStatsSheet } from '../../components/FbBookSheet';
|
||||
import { FB_BACK } from '../../common/FbBack';
|
||||
import { FB_SET_BOOKS } from '../../model/FbSettingsMenus';
|
||||
|
||||
@@ -45,6 +53,20 @@ export struct FbBooksPage {
|
||||
|
||||
@Local all: FbBookItem[] = [];
|
||||
|
||||
// ---- 一本书的浮层(v67:原来点了没反应)----
|
||||
@Local bookOpen: boolean = false;
|
||||
/** 0 = 加一本;>0 = 这本书的详情 */
|
||||
@Local bookId: number = 0;
|
||||
@Local bookTitle: string = '';
|
||||
@Local bookAuthor: string = '';
|
||||
@Local bookStatus: string = 'wish';
|
||||
@Local bookRate: number = 0;
|
||||
@Local bookCur: number = 0;
|
||||
@Local bookChapters: number = 0;
|
||||
|
||||
/** 读书统计浮层 */
|
||||
@Local statsOpen: boolean = false;
|
||||
|
||||
/**
|
||||
* 页面出现:先读缓存、再拉接口(本地优先,见 FbModuleRepo 的说明)。
|
||||
*
|
||||
@@ -61,6 +83,14 @@ export struct FbBooksPage {
|
||||
}
|
||||
|
||||
private backOnce(): boolean {
|
||||
if (this.bookOpen) {
|
||||
this.bookOpen = false;
|
||||
return true;
|
||||
}
|
||||
if (this.statsOpen) {
|
||||
this.statsOpen = false;
|
||||
return true;
|
||||
}
|
||||
if (this.settingsOpen) {
|
||||
this.settingsOpen = false;
|
||||
return true;
|
||||
@@ -95,7 +125,13 @@ export struct FbBooksPage {
|
||||
*/
|
||||
@Monitor('settingsOpen')
|
||||
onSettingsChanged(): void {
|
||||
fbAppState().sheetCount = this.settingsOpen ? 1 : 0;
|
||||
fbAppState().sheetCount = (this.bookOpen || this.statsOpen || this.settingsOpen) ? 1 : 0;
|
||||
}
|
||||
|
||||
/** 三个浮层:任一个开着都要让底部悬浮栏让位(它们各自带全屏遮罩,会盖住悬浮栏) */
|
||||
@Monitor('bookOpen', 'statsOpen')
|
||||
onSheetsChanged(): void {
|
||||
fbAppState().sheetCount = (this.bookOpen || this.statsOpen || this.settingsOpen) ? 1 : 0;
|
||||
}
|
||||
|
||||
build() {
|
||||
@@ -120,8 +156,22 @@ export struct FbBooksPage {
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.layoutWeight(1)
|
||||
|
||||
// 上传 / 统计(Web 端在设置菜单里)
|
||||
FbIconButton({ icon: $r('app.media.fb_ic_chart'), tint: FbTint.muted })
|
||||
/* 🔴 v67:原来这颗是「统计」图标且**没有 `onTap`**(纯摆设,点了没反应)。
|
||||
现在拆成两颗:+ 加一本(主操作)、统计(设置里也有一条,这里给个快捷)。 */
|
||||
FbIconButton({
|
||||
icon: $r('app.media.fb_ic_plus'),
|
||||
tint: this.accent,
|
||||
onTap: (): void => {
|
||||
this.openNewBook();
|
||||
}
|
||||
})
|
||||
FbIconButton({
|
||||
icon: $r('app.media.fb_ic_chart'),
|
||||
tint: FbTint.muted,
|
||||
onTap: (): void => {
|
||||
this.statsOpen = true;
|
||||
}
|
||||
})
|
||||
// 🔴 设置按钮 = 网页版那种**三条横线**(☰)—— 用户 2026-10-16。
|
||||
// 点开是本模块的设置菜单(条目照网页版 `templates/<模块>/_settings_menu.php`)。
|
||||
FbIconButton({
|
||||
@@ -196,8 +246,51 @@ export struct FbBooksPage {
|
||||
this.settingsOpen = false;
|
||||
},
|
||||
onPick: (action: string): void => {
|
||||
// 条目里 `action === ''` 的是「暂未开放」(组件里已画灰、点了不响应)
|
||||
// ⇒ 这里只需处理已实现的;目前都还没有,保持浮层开着即可。
|
||||
/* 🔴 v67:三条原来是空 `action`(画灰、点了没反应 = 用户说的"设置没有任何东西")。
|
||||
现在 `bookstats` 真的能进去;另两条要文件选择/微信授权,
|
||||
网页端才有 ⇒ 在组件里仍是「暂未开放」,这里的 hint 也写清楚了。 */
|
||||
if (action === 'bookstats') {
|
||||
this.settingsOpen = false;
|
||||
this.statsOpen = true;
|
||||
}
|
||||
}
|
||||
})
|
||||
.transition(fbSheetTransition())
|
||||
}
|
||||
|
||||
// ---- 一本书(新建 / 详情)----
|
||||
if (this.bookOpen) {
|
||||
FbBookSheet({
|
||||
accent: this.accent,
|
||||
editingId: this.bookId,
|
||||
initTitle: this.bookTitle,
|
||||
initAuthor: this.bookAuthor,
|
||||
initStatus: this.bookStatus,
|
||||
initRate: this.bookRate,
|
||||
curChapter: this.bookCur,
|
||||
chapters: this.bookChapters,
|
||||
onClose: (): void => {
|
||||
this.bookOpen = false;
|
||||
},
|
||||
onSaved: (): void => {
|
||||
this.bookOpen = false;
|
||||
this.load();
|
||||
},
|
||||
onDeleted: (): void => {
|
||||
this.bookOpen = false;
|
||||
this.load();
|
||||
}
|
||||
})
|
||||
.transition(fbSheetTransition())
|
||||
}
|
||||
|
||||
// ---- 读书统计 ----
|
||||
if (this.statsOpen) {
|
||||
FbBookStatsSheet({
|
||||
accent: this.accent,
|
||||
items: this.all,
|
||||
onClose: (): void => {
|
||||
this.statsOpen = false;
|
||||
}
|
||||
})
|
||||
.transition(fbSheetTransition())
|
||||
@@ -207,6 +300,30 @@ export struct FbBooksPage {
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
/** 点一本书 → 详情 */
|
||||
private openBook(b: FbBookItem): void {
|
||||
this.bookId = b.id;
|
||||
this.bookTitle = b.title;
|
||||
this.bookAuthor = b.author;
|
||||
this.bookStatus = b.status;
|
||||
this.bookRate = b.rate;
|
||||
this.bookCur = b.curChapter;
|
||||
this.bookChapters = b.chapters;
|
||||
this.bookOpen = true;
|
||||
}
|
||||
|
||||
/** 页头 + → 走同一个浮层的新建态 */
|
||||
private openNewBook(): void {
|
||||
this.bookId = 0;
|
||||
this.bookTitle = '';
|
||||
this.bookAuthor = '';
|
||||
this.bookStatus = 'wish';
|
||||
this.bookRate = 0;
|
||||
this.bookCur = 0;
|
||||
this.bookChapters = 0;
|
||||
this.bookOpen = true;
|
||||
}
|
||||
|
||||
/** 一本书:书脊色块(代替封面)+ 书名/作者 + 评分/笔记/进度 */
|
||||
@Builder
|
||||
bookRow(b: FbBookItem) {
|
||||
@@ -285,6 +402,10 @@ export struct FbBooksPage {
|
||||
.borderRadius(FbMetric.radius)
|
||||
.margin({ bottom: 8 })
|
||||
.alignItems(VerticalAlign.Center)
|
||||
/* 🔴 v67:整行可点 → 打开这本书(原来**没有 `onClick`** ⇒ "点不进去") */
|
||||
.onClick((): void => {
|
||||
this.openBook(b);
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
|
||||
Reference in New Issue
Block a user