底部「编辑」换成「保存」(#77)

用户 2026-11-05:「和网页版一样,没有保存按钮啊,这应该怎么保存呢?
在哪个地方点保存呢?」

之前是"失焦自动保存"——逻辑上能存,但**用户看不见这件事**,
没有按钮就没底,不知道到底存没存。补一颗显式按钮。

① footBar 的「编辑」→「保存」
   原来那颗「编辑」本身就是矛盾的:面板已经能改所有字段
   (标题/备注/截止/负责人/分类/协作人/子任务/附件/留言),
   再给一颗"编辑"反而跳到另一张表单。
   ⇒ 换成「保存」,保存后关窗(与网页端保存后关浮层一致)。

② saveAll():串行存标题 + 备注,然后 onChanged() + onClose()
   ⚠️ 必须**串行**不能并发:`saveField()` 内部会 `reload()`,
      两次并发会让后一次的 reload 覆盖前一次的结果,
      表现为"改完标题,备注却回到旧值"。
   ⚠️ 有 `saving` 忙碌态:避免连点两次发四组请求。

③ 其余字段保持"点了就生效",不按保存
   状态/看板/截止/负责人/分类/协作人/子任务/附件/留言 都是**动作**
   (选中即生效),多一步确认反而烦;只有"打字"类(标题、备注)
   才需要一次确认 —— 这也是网页端的口径。

编译通过,已装真机。
This commit is contained in:
2026-11-05 19:54:30 +08:00
parent cbeeb55a82
commit 980630644b
+43 -10
View File
@@ -132,6 +132,8 @@ export struct FbTaskPanel {
有焦点说明用户正在打字,这时覆盖会把刚打的字冲掉。 */ 有焦点说明用户正在打字,这时覆盖会把刚打的字冲掉。 */
@Local titleFocus: boolean = false; @Local titleFocus: boolean = false;
@Local noteFocus: boolean = false; @Local noteFocus: boolean = false;
/* 点「保存」时的忙碌态(标题 + 备注两次请求要串行,不能并发) */
@Local saving: boolean = false;
@Local inlineBusy: boolean = false; @Local inlineBusy: boolean = false;
/* #77c:附件预览浮层 —— 存当前要全屏看的那张图的地址,空 = 没开 */ /* #77c:附件预览浮层 —— 存当前要全屏看的那张图的地址,空 = 没开 */
@@ -397,7 +399,6 @@ export struct FbTaskPanel {
this.attPickOpen = true; this.attPickOpen = true;
} }
/** 保存备注(失焦/回车时触发) */
/** /**
* 保存任务标题。 * 保存任务标题。
* *
@@ -406,6 +407,33 @@ export struct FbTaskPanel {
* ⚠️ 空值必须**回填原值**:服务端会把空标题清洗成空串, * ⚠️ 空值必须**回填原值**:服务端会把空标题清洗成空串,
* 那等于把标题删了 —— 用户只是清空重打,不该丢标题。 * 那等于把标题删了 —— 用户只是清空重打,不该丢标题。
*/ */
/**
* 底部「保存」:把两个**手动编辑**的输入框(标题 / 备注)落库,然后关窗。
*
* 🔴 #77q(用户 2026-11-05):「和网页版一样,没有保存按钮啊,
* 这应该怎么保存呢?在哪个地方点保存呢?」
*
* 之前的设计是"失焦自动保存",但**用户看不见这件事** —— 没有按钮就没底,
* 不知道到底存没存。所以补一颗显式的保存按钮。
*
* ⚠️ 其它字段(状态/看板/截止/负责人/分类/协作人/子任务/附件/留言)
* **仍然是点一下就生效**,不用按保存 —— 那类操作是"动作",
* 做完就该立刻生效;只有"打字"类才需要一次确认。
* ⚠️ 串行两次请求而不是并发:`saveField()` 内部会 `reload()`,
* 并发会让两次 reload 互相覆盖 detail,出现"改完标题备注没了"。
*/
private async saveAll(): Promise<void> {
if (this.saving) {
return;
}
this.saving = true;
await this.saveTitle();
await this.saveNote();
this.saving = false;
this.onChanged();
this.onClose();
}
private async saveTitle(): Promise<void> { private async saveTitle(): Promise<void> {
const v: string = this.titleDraft.trim(); const v: string = this.titleDraft.trim();
if (v === '') { if (v === '') {
@@ -1976,24 +2004,29 @@ export struct FbTaskPanel {
@Builder @Builder
footBar() { footBar() {
Row({ space: 10 }) { Row({ space: 10 }) {
Text('编辑') /* 🔴🔴 #77q(用户 2026-11-05):「和网页版一样,没有保存按钮啊,
这应该怎么保存呢?在哪个地方点保存呢?」
原来这里是「编辑」—— 但面板本身已经能改所有字段(标题/备注/截止/
负责人/分类/协作人/子任务/附件/留言),再给一颗"编辑"是自相矛盾的
(点它反而跳到另一张表单)。
⇒ 换成**「保存」**:把"打字"类的两项(标题、备注)落库然后关窗。
与网页端保存后关浮层的行为一致。
⚠️ 状态/看板/截止/负责人这些**不用点保存**,选中即生效 ——
它们是"动作"不是"草稿",多一步确认反而烦。 */
Text(this.saving ? '保存中…' : '保存')
.fontSize(FbMetric.fontSmall) .fontSize(FbMetric.fontSmall)
.fontColor(Color.White) .fontColor(Color.White)
.textAlign(TextAlign.Center) .textAlign(TextAlign.Center)
.layoutWeight(1) .layoutWeight(1)
.height(42) .height(42)
.backgroundColor(this.busy ? '#C9CDD2' : this.accent) .backgroundColor(this.saving ? '#C9CDD2' : this.accent)
.borderRadius(FbMetric.radiusS) .borderRadius(FbMetric.radiusS)
.onClick((): void => { .onClick((): void => {
if (this.busy) { if (this.saving) {
return; return;
} }
const d: FbTaskDetail | null = this.detail; this.saveAll();
if (d === null) {
this.note = '还在载入,稍等一下再点编辑。';
return;
}
this.onEdit(d);
}) })
Text(this.confirmDel ? '确定删掉' : '删除') Text(this.confirmDel ? '确定删掉' : '删除')