v68:财务补齐(改一笔/删一笔/账本改名/共享给谁)

用户 2026-10-20:「还有这个财务的显示也有问题」——v65 修的是**显示口径**
(端上按正负号重加 vs 服务端负债取绝对值);这一批补的是**动作**:
设置里「共享给谁」「账本名字」一直是灰条,账目也改不了删不掉。

## 根因:不是端上没写,是服务端没有路由
`Ledger::rename / setShare / unshare / shares / updateEntry / removeEntry`
**一直都有**,`ApiHandler::ledger()` 却只开了「建账本 / 记一笔 / 删账本」
⇒ 端上只能把这两条画成"暂未开放"。

## 端上做了什么
- 点一行账目 → 同一个浮层进**编辑态**(类别 / 金额 / 名称 / 备注 +
  删除二次确认)。`aboutToAppear` 里把 @Param 拷进 @Local,
  点第二行才不会还是上一笔的内容。
- 设置「账本名字」→ 改名浮层;「共享给谁」→ 共享浮层(列表 + 选人 +
  逐个人取消)。列表解析走 `{items:[…]}`(`FbApiResult.data` 是原始 JSON)。
- 三个浮层共用 `recountSheets()` 让悬浮栏让位(原来只有"记一笔"有)。

## 顺手修的两处「对着服务端抄错」
1. `FbLedgerBook.myPerm` 的注释写 `owner / read / write`,
   而服务端**从来不给 `owner`**(主人也是 `write`)⇒ 端上"是不是我建的"永远 false。
   现在用服务端新补的 `isOwner` 布尔。
2. `FbLedgerEntry` 没有 `note` 字段 ⇒ 编辑时备注框永远是空的。补上类型与解析。

## 顺带
- 撤掉名册家谱那颗「补关系」按钮:从来没有 `onTap`,服务端 `relations`
  只有读接口、网页版也没这个功能 ⇒ 留个永远点不动的按钮只会被当成"坏了"。

## 验证
- `hvigorw assembleHap` → BUILD SUCCESSFUL
- `_fb_arkts_guard.js` → 827 / 0(新增 groupV68 29 条)
- `_fb_v59d_falsify.py` → 139 / 0(v68 新增 9 条注入全部变红)
- ⚠️ 设备仍断连(`hdc list targets` → `[Empty]`),真机未验收
This commit is contained in:
2026-10-20 20:18:38 +08:00
parent ec2cb14c4c
commit 2ff90519fa
9 changed files with 703 additions and 44 deletions
@@ -17,7 +17,7 @@ import { FbColors, FbMetric, FB_MASK, fbAlpha } from '../common/Theme';
import { FbSheetClose } from './FbSheetClose';
import { FbSheetRing } from './FbSheetRing';
import { FB_TOKEN_STORE } from '../data/FbTokenStore';
import { addLedgerEntry } from '../data/FbLedgerRepo';
import { addLedgerEntry, updateLedgerEntry, deleteLedgerEntry } from '../data/FbLedgerRepo';
import { FbApiResult } from '../data/FbHttp';
/** 类别键(顺序与 `Ledger::KINDS` 一致) */
@@ -35,6 +35,19 @@ export struct FbLedgerEntrySheet {
/** 记到哪本账 */
@Param ledgerId: number = 0;
@Param ledgerName: string = '';
/**
* 编辑模式:> 0 = 改这一条(`0` = 新记一笔)。
*
* 🔴 v68(用户 2026-10-20「财务的显示也有问题」的后续):
* 原来这里只有「记一笔」,底部还写着"改/删去网页端"——因为服务端没有路由。
* v68 服务端补了 `PATCH/DELETE /ledger/<id>/entries`(id 走 body),
* 端上就地把**改一笔 / 删一笔**做完。
*/
@Param editId: number = 0;
@Param editKind: string = 'deposit';
@Param editAmount: string = '';
@Param editTitle: string = '';
@Param editNote: string = '';
@Event onClose: () => void = (): void => {};
@Event onSaved: () => void = (): void => {};
@@ -45,6 +58,28 @@ export struct FbLedgerEntrySheet {
@Local note: string = '';
@Local saving: boolean = false;
@Local err: string = '';
/** 删除的二次确认(删账目不可逆,必须先问一句) */
@Local confirmingDelete: boolean = false;
/**
* 编辑态要**把 @Param 拷进 @Local**。
*
* ⚠️ 不能在字段初始化里写 `@Local amount: string = this.editAmount`:
* V2 的成员初始化顺序不保证,`@Param` 那时可能还没赋值(拿到空串)。
* 浮层每次打开都是新实例 ⇒ 在 `aboutToAppear` 拷一次就够。
*/
aboutToAppear(): void {
if (this.editId > 0) {
if (this.editKind !== '') { this.kind = this.editKind; }
this.amount = this.editAmount;
this.title = this.editTitle;
this.note = this.editNote;
}
}
private isEdit(): boolean {
return this.editId > 0;
}
private kindNameOf(k: string): string {
const i: number = KIND_KEYS.indexOf(k);
@@ -77,7 +112,7 @@ export struct FbLedgerEntrySheet {
Column({ space: 12 }) {
Row({ space: 8 }) {
Column({ space: 2 }) {
Text('记一笔')
Text(this.isEdit() ? '改这一笔' : '记一笔')
.fontSize(FbMetric.fontTitle)
.fontWeight(FontWeight.Medium)
.fontColor(FbColors.ink)
@@ -213,11 +248,30 @@ export struct FbLedgerEntrySheet {
.width('100%')
.alignItems(VerticalAlign.Top)
Text('已有账目的金额修改 / 删除还在网页端 —— 接口只开放了"记一笔"。')
.fontSize(FbMetric.fontTiny)
.fontColor(FbColors.faint)
.width('100%')
.maxLines(3)
if (this.isEdit()) {
if (!this.confirmingDelete) {
Text('删掉这一笔')
.fontSize(FbMetric.fontTiny)
.fontColor(FbColors.red)
.width('100%')
.textAlign(TextAlign.Center)
.onClick((): void => {
this.confirmingDelete = true;
})
} else {
Text('再点一次就删掉了(不可恢复)')
.fontSize(FbMetric.fontTiny)
.fontColor('#FFFFFF')
.textAlign(TextAlign.Center)
.width('100%')
.height(38)
.borderRadius(FbMetric.radiusS)
.backgroundColor('#C0533F')
.onClick((): void => {
this.remove();
})
}
}
}
.width('100%')
.alignItems(HorizontalAlign.Start)
@@ -235,7 +289,8 @@ export struct FbLedgerEntrySheet {
.maxLines(3)
}
Text(this.saving ? '记入中…' : '记下来')
Text(this.saving ? (this.isEdit() ? '保存中…' : '记入中…')
: (this.isEdit() ? '保存改动' : '记下来'))
.fontSize(FbMetric.fontBody)
.fontWeight(FontWeight.Medium)
.fontColor(this.saving ? FbColors.faint : '#FFFFFF')
@@ -271,8 +326,11 @@ export struct FbLedgerEntrySheet {
}
this.saving = true;
this.err = '';
const res: FbApiResult = await addLedgerEntry(FB_TOKEN_STORE.get(), this.ledgerId,
this.kind, amt, this.title.trim(), this.note.trim());
const res: FbApiResult = this.isEdit()
? await updateLedgerEntry(FB_TOKEN_STORE.get(), this.ledgerId, this.editId,
this.kind, amt, this.title.trim(), this.note.trim())
: await addLedgerEntry(FB_TOKEN_STORE.get(), this.ledgerId,
this.kind, amt, this.title.trim(), this.note.trim());
this.saving = false;
if (!res.ok) {
this.err = res.error !== '' ? res.error : '没记上,请稍后再试。';
@@ -280,4 +338,21 @@ export struct FbLedgerEntrySheet {
}
this.onSaved();
}
/** 删掉这一笔(服务端 `DELETE /ledger/<id>/entries`,id 走 body + query) */
private async remove(): Promise<void> {
if (this.saving) {
return;
}
this.saving = true;
const res: FbApiResult = await deleteLedgerEntry(FB_TOKEN_STORE.get(), this.ledgerId,
this.editId);
this.saving = false;
if (!res.ok) {
this.err = res.error !== '' ? res.error : '没删掉,请稍后再试。';
this.confirmingDelete = false;
return;
}
this.onSaved();
}
}