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:
@@ -3,19 +3,25 @@
|
||||
*
|
||||
* 对应服务端 `app/ApiHandler.php` 的 `ledger()`:
|
||||
* POST /api/v1/ledger 新建账本(name)
|
||||
* POST /api/v1/ledger/<id>/entries 记一笔(kind / amount / title / note / person_id)
|
||||
* PATCH /api/v1/ledger/<id> 账本改名(name) ← v68
|
||||
* DELETE /api/v1/ledger/<id> 删账本
|
||||
* POST /api/v1/ledger/<id>/entries 记一笔(kind/amount/title/note/person_id)
|
||||
* PATCH /api/v1/ledger/<id>/entries 改一笔(**id 在 body 里**) ← v68
|
||||
* DELETE /api/v1/ledger/<id>/entries 删一笔(**id 在 body/query**)← v68
|
||||
* GET /api/v1/ledger/<id>/shares 共享给了谁 ← v68
|
||||
* POST /api/v1/ledger/<id>/shares 共享给某人(person_id/perm)← v68
|
||||
* DELETE /api/v1/ledger/<id>/shares 取消共享(person_id) ← v68
|
||||
*
|
||||
* 🔴 用户 2026-10-20:「还有这个财务的显示也有问题。」
|
||||
* ⇒ 端上「记一笔」按钮**没有 `onTap`**、账本切换**不重拉明细**、
|
||||
* 资产/负债是**端上自己按正负号重新加**的(与净资产口径不一致)。见 `FbLedgerPage`。
|
||||
* 🔴 用户 2026-10-20:「还有这个财务的显示也有问题。」(v65 已修显示口径)
|
||||
* v68 补的是**动作**:设置里「共享给谁」「账本名字」原来是灰条,
|
||||
* 账目也没有"改一笔/删一笔" —— 模型里这些方法早就有,只差路由与端上入口。
|
||||
*
|
||||
* ⚠️ **金额传「元」的字符串**:服务端 `Ledger::toCents()` 负责转分
|
||||
* (App 与网页表单同一口径)。这里**不要**先转分再传 —— 会双重换算,差 100 倍。
|
||||
*
|
||||
* ⚠️ **没有"改一笔"和"删一笔"的接口**(`Api::` 路由只解析到第 3 段,
|
||||
* `/ledger/<id>/entries/<eid>` 的第 4 段会被丢掉)。所以端上只做"记一笔",
|
||||
* 改了金额请去网页端操作 —— 这一条要显式写在界面上,别让用户以为存不上。
|
||||
* 🔴 **被改/被删的那一笔,id 只能放 body 或 query,不能拼进路径**:
|
||||
* `Api::dispatch()` 只解析 `/<res>/<id>/<sub>` **三段**,
|
||||
* `/ledger/3/entries/17` 的第 4 段会被直接丢掉(会落到"整本账本"上)。
|
||||
*/
|
||||
|
||||
import { fbApi, FbApiResult, FbApiOptions } from './FbHttp';
|
||||
@@ -33,3 +39,65 @@ export async function addLedgerEntry(token: string, ledgerId: number, kind: stri
|
||||
const opts: FbApiOptions = { method: 'POST', token: token, body: body };
|
||||
return await fbApi('/api/v1/ledger/' + ledgerId.toString() + '/entries', opts);
|
||||
}
|
||||
|
||||
/** 改一笔(金额/名称/备注/收支/经手人)。`entryId` 必须在 body 里,见文件头说明。 */
|
||||
export async function updateLedgerEntry(token: string, ledgerId: number, entryId: number,
|
||||
kind: string, amountYuan: string, title: string, note: string): Promise<FbApiResult> {
|
||||
const body: Record<string, Object> = {};
|
||||
body['id'] = entryId;
|
||||
body['kind'] = kind;
|
||||
body['amount'] = amountYuan;
|
||||
body['title'] = title;
|
||||
body['note'] = note;
|
||||
const opts: FbApiOptions = { method: 'PATCH', token: token, body: body };
|
||||
return await fbApi('/api/v1/ledger/' + ledgerId.toString() + '/entries', opts);
|
||||
}
|
||||
|
||||
/** 删一笔 */
|
||||
export async function deleteLedgerEntry(token: string, ledgerId: number,
|
||||
entryId: number): Promise<FbApiResult> {
|
||||
/* ⚠️ DELETE 也带 body:服务端的 `Api::body()` 认 JSON body;
|
||||
同时也放进 query(`?id=`)—— 某些代理会丢 DELETE 的 body。 */
|
||||
const path: string = '/api/v1/ledger/' + ledgerId.toString() + '/entries?id=' +
|
||||
entryId.toString();
|
||||
const body: Record<string, Object> = {};
|
||||
body['id'] = entryId;
|
||||
const opts: FbApiOptions = { method: 'DELETE', token: token, body: body };
|
||||
return await fbApi(path, opts);
|
||||
}
|
||||
|
||||
/** 账本改名 */
|
||||
export async function renameLedger(token: string, ledgerId: number,
|
||||
name: string): Promise<FbApiResult> {
|
||||
const body: Record<string, Object> = {};
|
||||
body['name'] = name;
|
||||
const opts: FbApiOptions = { method: 'PATCH', token: token, body: body };
|
||||
return await fbApi('/api/v1/ledger/' + ledgerId.toString(), opts);
|
||||
}
|
||||
|
||||
/** 共享给了谁(服务端回 `{items:[…]}`,每项含 person_id / name / perm) */
|
||||
export async function fetchLedgerShares(token: string, ledgerId: number): Promise<FbApiResult> {
|
||||
const opts: FbApiOptions = { token: token, authProbe: true };
|
||||
return await fbApi('/api/v1/ledger/' + ledgerId.toString() + '/shares', opts);
|
||||
}
|
||||
|
||||
/** 共享给某人(perm = read / write) */
|
||||
export async function shareLedger(token: string, ledgerId: number, personId: number,
|
||||
perm: string): Promise<FbApiResult> {
|
||||
const body: Record<string, Object> = {};
|
||||
body['person_id'] = personId;
|
||||
body['perm'] = perm;
|
||||
const opts: FbApiOptions = { method: 'POST', token: token, body: body };
|
||||
return await fbApi('/api/v1/ledger/' + ledgerId.toString() + '/shares', opts);
|
||||
}
|
||||
|
||||
/** 取消某人的共享 */
|
||||
export async function unshareLedger(token: string, ledgerId: number,
|
||||
personId: number): Promise<FbApiResult> {
|
||||
const path: string = '/api/v1/ledger/' + ledgerId.toString() + '/shares?person_id=' +
|
||||
personId.toString();
|
||||
const body: Record<string, Object> = {};
|
||||
body['person_id'] = personId;
|
||||
const opts: FbApiOptions = { method: 'DELETE', token: token, body: body };
|
||||
return await fbApi(path, opts);
|
||||
}
|
||||
|
||||
@@ -174,6 +174,8 @@ interface RawTaskBoard {
|
||||
interface RawLedgerBook {
|
||||
id?: number; name?: string; my_perm?: string | null; entry_count?: number;
|
||||
share_perm?: string | null;
|
||||
/** v68:服务端补的"是不是我建的"(`my_perm` 只有 read/write,分不出主人) */
|
||||
is_owner?: boolean | number | null;
|
||||
}
|
||||
|
||||
interface RawLedgerEntry {
|
||||
@@ -390,6 +392,7 @@ export function parseLedger(json: string): FbLedgerBook[] {
|
||||
name: s(r.name),
|
||||
netCent: 0, // 概览接口不返回净资产,进详情页时再取 summary
|
||||
myPerm: s(r.my_perm) !== '' ? s(r.my_perm) : 'read',
|
||||
isOwner: b(r.is_owner),
|
||||
entryCount: n(r.entry_count),
|
||||
};
|
||||
out.push(bk);
|
||||
@@ -421,6 +424,7 @@ export function parseLedgerEntries(json: string): FbLedgerDetail {
|
||||
amountCent: n(r.amount_cents),
|
||||
// 「挂名的人」优先用昵称(我习惯叫他什么),没有就用本名
|
||||
ownerName: s(r.person_nick) !== '' ? s(r.person_nick) : s(r.person_name),
|
||||
note: s(r.note),
|
||||
updatedAt: datePart(s(r.updated_at)),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user