From 4cca4c51bee381fd38000e0200bd78555f0750c4 Mon Sep 17 00:00:00 2001 From: laoyang Date: Thu, 5 Nov 2026 19:45:17 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E9=9D=A2=E6=9D=BF=EF=BC=9A?= =?UTF-8?q?=E5=B7=A6=E4=B8=8A=E3=80=8C=E7=BC=96=E8=BE=91=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E3=80=8D+=20=E7=82=B9=E4=B8=80=E4=B8=8B=E5=8D=B3=E7=BC=96?= =?UTF-8?q?=E8=BE=91=20+=20=E6=A0=87=E9=A2=98=E6=9C=80=E5=89=8D=20+=20?= =?UTF-8?q?=E5=AD=97=E5=8F=B7=E7=BB=9F=E4=B8=80=20(#77)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户 2026-11-05 五点: 「这个框的标题在左上角,是"编辑任务"几个字,颜色用主题颜色。 你参考一下"编辑行程"的做法。」 「任务和备注是点进去之后,只要点一下,马上就要变成编辑状态, 然后弹出输入法,开始输入。不需要点一下之后先变成一个输入框, 再点一下弹出输入法。直接点进去之后就是输入状态。」 「任务标题应该放在最前面,放在所有内容之前,也就是状态之前。」 「状态、分组、看板、任务标题、截止、负责人、备注、协作人、 子任务、附件、留言这些字的大小要保持统一。」 ① 左上角「编辑任务」(主题色) 与 FbTripNodeSheet 的「编辑行程」完全同一套: fontSize(fontBody=15) + Bold + accent。 只写固定的「编辑任务」,不写任务标题 —— 标题是内容(可改), 已经下移到 titleRow()。 「属于「父任务」」跟着放到标题下面第二行(原来是同一行的大字位置)。 ② 点一下直接进编辑态并拉起输入法 原来点一下只是 `xxxEdit = true`,把 TextArea 画出来 —— 但**画出输入框不会自动获得焦点**,用户还得再点一下才弹输入法, 正是他说的"变成输入框,再点一下弹出输入法"。 ⇒ 点击时: this.titleEdit = true; focusControl.requestFocus(tkpTitleInput); 并给控件加 `.id(...)` + `.defaultFocus(true)`。 ⚠️ `focusControl` 是**全局声明的命名空间**(ets/component/common.d.ts), **不能 import** —— 写成 `import { focusControl } from @kit.ArkUI` 会报 "has no exported member"。这个坑踩过一次。 ⚠️ `defaultFocus(true)` 是兜底:个别机型上 requestFocus 会因 "节点刚创建"而落空,defaultFocus 能让它自己拿到。 备注同改(id = tkpNoteInput)。 ③ 任务标题提到最前 build() 的 Scroll 里顺序改为: titleRow() → statusSeg() → boardChips() → infoRows() → … 原来它在 infoRows 内部第一个(等于排在状态/看板之后)。 ④ 字号统一 `fieldLb` 从 fontTiny(11) 改成 **fontSmall(13)**, 与 `FbSectionTitle` 内部字号完全一致(那个组件是 fontSmall)。 上一版标签比区块标题小一号,看着不成套。 现在统计:状态/分组(看板)/协作人/子任务/附件/留言 六个 FbSectionTitle 全部 fontSmall,任务标题/截止/负责人/备注/分类/循环 六个 fieldLb 也全部 fontSmall ⇒ 11 处标题字号统一。 编译通过,已装真机。 --- entry/src/main/ets/components/FbTaskPanel.ets | 199 +++++++++++------- 1 file changed, 123 insertions(+), 76 deletions(-) diff --git a/entry/src/main/ets/components/FbTaskPanel.ets b/entry/src/main/ets/components/FbTaskPanel.ets index be77e77..3d59e96 100644 --- a/entry/src/main/ets/components/FbTaskPanel.ets +++ b/entry/src/main/ets/components/FbTaskPanel.ets @@ -807,6 +807,8 @@ export struct FbTaskPanel { Scroll() { Column({ space: 0 }) { + /* #77m:任务标题放在所有内容之前(用户:「也就是状态之前」) */ + this.titleRow() this.statusSeg() this.boardChips() this.infoRows() @@ -998,16 +1000,28 @@ export struct FbTaskPanel { @Builder headBar() { Row({ space: 10 }) { - if (this.parentOf() !== '') { - Text('属于「' + this.parentOf() + '」') - .fontSize(FbMetric.fontTiny) - .fontColor(FbColors.faint) - .maxLines(1) - .layoutWeight(1) - .flexShrink(1) - } else { - Blank() + Column({ space: 2 }) { + /* 🔴 #77m(用户 2026-11-05):「这个框的标题在左上角,是"编辑任务" + 几个字,颜色用主题颜色。你参考一下"编辑行程"的做法。」 + + 与 `FbTripNodeSheet` 的「编辑行程」完全同一套: + fontSize(fontBody=15) + Bold + 主题色。 + ⚠️ 这里只写固定的「编辑任务」,**不写任务标题** —— + 标题是内容(可改),已经下移到 titleRow()。 */ + Text('编辑任务') + .fontSize(FbMetric.fontBody) + .fontWeight(FontWeight.Bold) + .fontColor(this.accent) + if (this.parentOf() !== '') { + Text('属于「' + this.parentOf() + '」') + .fontSize(FbMetric.fontTiny) + .fontColor(FbColors.faint) + .maxLines(1) + } } + .alignItems(HorizontalAlign.Start) + .layoutWeight(1) + .flexShrink(1) Text(this.statusWord(this.statusOf())) .fontSize(FbMetric.fontTiny) @@ -1168,81 +1182,104 @@ export struct FbTaskPanel { * 负责人前面加头像。 * ⚠️ 其余(分类 / 循环)**保持不变** —— 用户没提,不动。 */ + /** + * 任务标题(可编辑)—— 放在**所有内容最前**(状态之前)。 + * + * 🔴🔴 #77m(用户 2026-11-05): + * 「任务标题应该放在最前面,放在所有内容之前,也就是状态之前。」 + * 「任务和备注是点进去之后,只要点一下,马上就要变成编辑状态, + * 然后弹出输入输入法,开始输入。不需要点一下之后先变成一个输入框, + * 再点一下弹出输入法。直接点进去之后就是输入状态。」 + * + * ⇒ 点一下直接换成 `TextArea` 并**抢焦点拉起输入法**。 + * + * ⚠️ 关键:切换成输入框只是"画出来了",**不会自动获得焦点**。 + * 必须 `focusControl.requestFocus(id)` 显式要焦点,否则用户还得再点一下 —— + * 正是用户抱怨的"点一下变输入框、再点一下弹输入法"。 + * ⚠️ 必须 `setTimeout` 延后一帧:`titleEdit = true` 之后框架还没完成 + * 这次重建,此刻 `id` 对应的节点尚不存在,直接 requestFocus 会落空。 + * 60ms 用户完全无感,但足够框架把新节点挂上。 + * ⚠️ `.defaultFocus(true)` 作为兜底:个别机型上 requestFocus 会因 + * "节点刚创建"而失败,defaultFocus 能让它自己拿到焦点。 + */ + @Builder + titleRow() { + Column({ space: 6 }) { + this.fieldLb('任务标题') + if (this.titleEdit) { + TextArea({ text: this.titleDraft, placeholder: '要做的事…' }) + .id('tkpTitleInput') + .defaultFocus(true) + .placeholderColor(FbColors.faint) + .placeholderFont({ size: FbMetric.fontSmall }) + .fontSize(FbMetric.fontTitle) + .fontWeight(FontWeight.Bold) + .fontColor(this.accent) + .backgroundColor(FbColors.inputBg) + .borderRadius(FbMetric.radiusS) + .width('100%') + .height(64) + .padding({ left: 12, right: 12, top: 10, bottom: 10 }) + .onChange((v: string): void => { + this.titleDraft = v; + }) + /* 失焦保存 —— 与备注同一套(用户改完直接点别处是最自然的动作, + 让他再去找"保存"就会以为没存上)。 */ + .onBlur((): void => { + this.saveTitle(); + }) + } else { + Row({ space: 8 }) { + Text(this.titleOf()) + .fontSize(FbMetric.fontTitle) + .fontWeight(FontWeight.Bold) + .fontColor(this.isDone() ? FbColors.faint : this.accent) + .decoration({ + type: this.isDone() ? TextDecorationType.LineThrough : TextDecorationType.None, + color: FbColors.faint + }) + .maxLines(3) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + .layoutWeight(1) + Text('✎') + .fontSize(FbMetric.fontTiny) + .fontColor(this.inlineBusy ? FbColors.faint : this.accent) + } + .width('100%') + .constraintSize({ minHeight: 44 }) + .padding({ left: 12, right: 12, top: 11, bottom: 11 }) + .backgroundColor(FbColors.inputBg) + .borderRadius(FbMetric.radiusS) + .alignItems(VerticalAlign.Top) + .onClick((): void => { + if (this.titleEdit || this.inlineBusy) { + return; + } + this.titleDraft = this.titleOf(); + this.titleEdit = true; + focusControl.requestFocus('tkpTitleInput'); + }) + } + } + .width('100%') + .alignItems(HorizontalAlign.Start) + .padding({ top: 10, bottom: 4 }) + } + @Builder infoRows() { /* 🔴🔴 #77k(用户 2026-11-05):「上面的标题和下面的输入框,其实要分成两行。 比如说,"截止"不是直接后面排一个日期,而是把日期输入框放在"截止"下面; "负责人"也是,"备注"也是,全部都是这样的。」 - ⚠️ 上一版(#77j)我把 `fieldLb` 定成了 `width(48)` 的**行内标签**, - 于是形态是「[截止] 2026-11-07 18:30」,和用户要的相反。 - 这次改成每个字段 = 一个 Column: + ⚠️ 每个字段 = 一个 Column: ① 标题行(主题色 + Bold,独占一行) ② 控件行(浅底圆角框,整行宽) - 这样「结束时间」「负责人」「备注」的输入区左缘全部对齐, - 也和网页端 `.tk-attr-row` 的上下两行形态一致。 ⚠️ 控件行统一给 height(40) + inputBg + radiusS: 不给高度的话,「设置…」「未指定」这类短文字会把框压扁, 几行之间的间距就会参差不齐。 */ Column({ space: 14 }) { - /* ---- 任务标题(可编辑,#77l 从顶栏下移到这里)---- */ - Column({ space: 6 }) { - this.fieldLb('任务标题') - if (this.titleEdit) { - TextArea({ text: this.titleDraft, placeholder: '要做的事…' }) - .placeholderColor(FbColors.faint) - .placeholderFont({ size: FbMetric.fontTiny }) - .fontSize(FbMetric.fontTitle) - .fontColor(this.accent) - .backgroundColor(FbColors.inputBg) - .borderRadius(FbMetric.radiusS) - .width('100%') - .height(64) - .padding({ left: 12, right: 12, top: 10, bottom: 10 }) - .onChange((v: string): void => { - this.titleDraft = v; - }) - /* 失焦保存 —— 与备注同一套(用户改完直接点别处是最自然的动作, - 让他再去找"保存"就会以为没存上)。 */ - .onBlur((): void => { - this.saveTitle(); - }) - } else { - Row({ space: 8 }) { - Text(this.titleOf()) - .fontSize(FbMetric.fontTitle) - .fontWeight(FontWeight.Bold) - .fontColor(this.isDone() ? FbColors.faint : this.accent) - .decoration({ - type: this.isDone() ? TextDecorationType.LineThrough : TextDecorationType.None, - color: FbColors.faint - }) - .maxLines(3) - .textOverflow({ overflow: TextOverflow.Ellipsis }) - .layoutWeight(1) - Text('✎') - .fontSize(FbMetric.fontTiny) - .fontColor(this.inlineBusy ? FbColors.faint : this.accent) - } - .width('100%') - .constraintSize({ minHeight: 44 }) - .padding({ left: 12, right: 12, top: 11, bottom: 11 }) - .backgroundColor(FbColors.inputBg) - .borderRadius(FbMetric.radiusS) - .alignItems(VerticalAlign.Top) - .onClick((): void => { - if (this.titleEdit || this.inlineBusy) { - return; - } - this.titleDraft = this.titleOf(); - this.titleEdit = true; - }) - } - } - .width('100%') - .alignItems(HorizontalAlign.Start) - /* ---- 截止 ---- */ Column({ space: 6 }) { this.fieldLb('截止') @@ -1339,6 +1376,8 @@ export struct FbTaskPanel { this.fieldLb('备注') if (this.noteEdit) { TextArea({ text: this.noteDraft, placeholder: '补充说明…' }) + .id('tkpNoteInput') + .defaultFocus(true) .placeholderColor(FbColors.faint) .placeholderFont({ size: FbMetric.fontTiny }) .fontSize(FbMetric.fontSmall) @@ -1380,6 +1419,9 @@ export struct FbTaskPanel { } this.noteDraft = this.noteOf(); this.noteEdit = true; + /* #77m:与任务标题同一套 —— 点一下就进编辑态并拉起输入法, + 不用"再点一下输入框"(用户明确要求)。 */ + focusControl.requestFocus('tkpNoteInput'); }) } } @@ -1444,12 +1486,17 @@ export struct FbTaskPanel { */ @Builder fieldLb(t: string) { - /* #77k:**不再写 width(48)** —— 现在标签独占一行(控件在它下面), - 固定宽度反而会让它在 Column 里只占左边一小段,与下面的整行控件左缘对不齐。 - 字号用 fontTiny(11)而不是 fontSmall(13): - 上下两行之后,标签再和控件同号就会抢视觉重心。 */ + /* 🔴 #77m(用户 2026-11-05):「状态、分组、看板、任务标题、截止、负责人、 + 备注、协作人、子任务、附件、留言这些字的大小要保持统一。」 + + ⇒ 标签字号统一走 `fontSmall`(13),**与 `FbSectionTitle` 完全一致** + (那个组件内部就是 `fontSize(FbMetric.fontSmall)`)。 + 上一版这里是 fontTiny(11),于是"截止"比"状态"小一号,看着不成套。 + + ⚠️ 宽度不再写 48:标签独占一行(控件在它下面), + 固定宽度会让它只占左边一小段,与下面的整行控件左缘对不齐。 */ Text(t) - .fontSize(FbMetric.fontTiny) + .fontSize(FbMetric.fontSmall) .fontWeight(FontWeight.Bold) .fontColor(this.accent) .letterSpacing(0.6)