diff --git a/entry/src/main/ets/components/FbTaskPanel.ets b/entry/src/main/ets/components/FbTaskPanel.ets index c25147c..8299e8b 100644 --- a/entry/src/main/ets/components/FbTaskPanel.ets +++ b/entry/src/main/ets/components/FbTaskPanel.ets @@ -977,10 +977,14 @@ export struct FbTaskPanel { }) Column({ space: 2 }) { + /* 🔴 #77k(用户 2026-11-05):「上面"台式机采购计划"这样的标题, + 应该是主题的颜色。」 + ⚠️ 完成态仍用 faint + 删除线:那条是"这件事已经过去了"的信号, + 再上主题色会和"待办"的标题一样抢眼,反而分不出轻重。 */ Text(this.titleOf()) .fontSize(FbMetric.fontTitle) - .fontWeight(FontWeight.Medium) - .fontColor(this.isDone() ? FbColors.faint : FbColors.ink) + .fontWeight(FontWeight.Bold) + .fontColor(this.isDone() ? FbColors.faint : this.accent) .decoration({ type: this.isDone() ? TextDecorationType.LineThrough : TextDecorationType.None, color: FbColors.faint @@ -1160,76 +1164,106 @@ export struct FbTaskPanel { */ @Builder infoRows() { - Column({ space: 0 }) { - /* ---- 截止:可点,弹 FbDateTimePicker ---- */ - Row({ space: 8 }) { + /* 🔴🔴 #77k(用户 2026-11-05):「上面的标题和下面的输入框,其实要分成两行。 + 比如说,"截止"不是直接后面排一个日期,而是把日期输入框放在"截止"下面; + "负责人"也是,"备注"也是,全部都是这样的。」 + + ⚠️ 上一版(#77j)我把 `fieldLb` 定成了 `width(48)` 的**行内标签**, + 于是形态是「[截止] 2026-11-07 18:30」,和用户要的相反。 + 这次改成每个字段 = 一个 Column: + ① 标题行(主题色 + Bold,独占一行) + ② 控件行(浅底圆角框,整行宽) + 这样「结束时间」「负责人」「备注」的输入区左缘全部对齐, + 也和网页端 `.tk-attr-row` 的上下两行形态一致。 + + ⚠️ 控件行统一给 height(40) + inputBg + radiusS: + 不给高度的话,「设置…」「未指定」这类短文字会把框压扁, + 几行之间的间距就会参差不齐。 */ + Column({ space: 14 }) { + /* ---- 截止 ---- */ + Column({ space: 6 }) { this.fieldLb('截止') - Text(this.dueOf() !== '' ? this.dueOf() : '设置…') - .fontSize(FbMetric.fontSmall) - .fontColor(this.dueOf() === '' ? FbColors.faint - : (this.overdueOf() ? '#C0533F' : FbColors.ink)) - .layoutWeight(1) - if (this.overdueOf()) { - Text('已逾期') - .fontSize(10) - .fontColor('#C0533F') - .padding({ left: 6, right: 6, top: 2, bottom: 2 }) - .backgroundColor('#FDECEC') - .borderRadius(FbMetric.radiusPill) - } - /* 可编辑的视觉提示:一支小笔。没有它用户不知道这里能点 - (本项目反复踩过"纯文字看着不可点"的坑)。 */ - Text('✎') - .fontSize(FbMetric.fontTiny) - .fontColor(this.inlineBusy ? FbColors.faint : this.accent) - } - .width('100%') - .padding({ top: 7, bottom: 7 }) - .alignItems(VerticalAlign.Center) - .onClick((): void => { - this.openDuePicker(); - }) - - /* ---- 负责人:头像 + 可点选人 ---- */ - Row({ space: 8 }) { - this.fieldLb('负责人') - /* 头像(#77「负责人那个地方也需要有图标,就是人的头像」) - ⚠️ 端上不一定拿得到头像图(`assigneeAvatar` 可能是空 key)⇒ - 有图用图,没图用首字色块兜底(与留言区同一个手法)。 */ - if (this.assigneeAvatarSrc() !== '') { - Image(this.assigneeAvatarSrc()) - .width(22) - .height(22) - .borderRadius(11) - .objectFit(ImageFit.Cover) - .backgroundColor(FbColors.inputBg) - } else { - Row() { - Text(this.assigneeOf() !== '' ? this.assigneeOf().substring(0, 1) : '?') + Row({ space: 8 }) { + Text(this.dueOf() !== '' ? this.dueOf() : '设置截止时间…') + .fontSize(FbMetric.fontSmall) + .fontColor(this.dueOf() === '' ? FbColors.faint + : (this.overdueOf() ? '#C0533F' : FbColors.ink)) + .layoutWeight(1) + if (this.overdueOf()) { + Text('已逾期') .fontSize(10) - .fontColor(this.accent) + .fontColor('#C0533F') + .padding({ left: 6, right: 6, top: 2, bottom: 2 }) + .backgroundColor('#FDECEC') + .borderRadius(FbMetric.radiusPill) } - .width(22) - .height(22) - .borderRadius(11) - .backgroundColor(FbColors.inputBg) - .justifyContent(FlexAlign.Center) + /* 可编辑的视觉提示:一支小笔。没有它用户不知道这里能点 + (本项目反复踩过"纯文字看着不可点"的坑)。 */ + Text('✎') + .fontSize(FbMetric.fontTiny) + .fontColor(this.inlineBusy ? FbColors.faint : this.accent) } - Text(this.assigneeOf() !== '' ? this.assigneeOf() : '未指定') - .fontSize(FbMetric.fontSmall) - .fontColor(this.assigneeOf() === '' ? FbColors.faint : FbColors.ink) - .layoutWeight(1) - Text('✎') - .fontSize(FbMetric.fontTiny) - .fontColor(this.inlineBusy ? FbColors.faint : this.accent) + .width('100%') + .height(40) + .padding({ left: 12, right: 12 }) + .backgroundColor(FbColors.inputBg) + .borderRadius(FbMetric.radiusS) + .alignItems(VerticalAlign.Center) + .onClick((): void => { + this.openDuePicker(); + }) } .width('100%') - .padding({ top: 7, bottom: 7 }) - .alignItems(VerticalAlign.Center) - .onClick((): void => { - this.openAssigneePicker(); - }) + .alignItems(HorizontalAlign.Start) + /* ---- 负责人 ---- */ + Column({ space: 6 }) { + this.fieldLb('负责人') + Row({ space: 8 }) { + /* 头像(#77「负责人那个地方也需要有图标,就是人的头像」) + ⚠️ 端上不一定拿得到头像图(`assigneeAvatar` 可能是空 key)⇒ + 有图用图,没图用首字色块兜底(与留言区同一个手法)。 */ + if (this.assigneeAvatarSrc() !== '') { + Image(this.assigneeAvatarSrc()) + .width(24) + .height(24) + .borderRadius(12) + .objectFit(ImageFit.Cover) + .backgroundColor(FbColors.line2) + } else { + Row() { + Text(this.assigneeOf() !== '' ? this.assigneeOf().substring(0, 1) : '?') + .fontSize(11) + .fontColor(this.accent) + } + .width(24) + .height(24) + .borderRadius(12) + .backgroundColor(FbColors.line2) + .justifyContent(FlexAlign.Center) + } + Text(this.assigneeOf() !== '' ? this.assigneeOf() : '未指定') + .fontSize(FbMetric.fontSmall) + .fontColor(this.assigneeOf() === '' ? FbColors.faint : FbColors.ink) + .layoutWeight(1) + Text('✎') + .fontSize(FbMetric.fontTiny) + .fontColor(this.inlineBusy ? FbColors.faint : this.accent) + } + .width('100%') + .height(40) + .padding({ left: 12, right: 12 }) + .backgroundColor(FbColors.inputBg) + .borderRadius(FbMetric.radiusS) + .alignItems(VerticalAlign.Center) + .onClick((): void => { + this.openAssigneePicker(); + }) + } + .width('100%') + .alignItems(HorizontalAlign.Start) + + /* ---- 分类 / 循环(同样上下两行)---- */ if (this.categoryOf() !== '') { this.kvRow('分类', this.categoryOf()) } @@ -1237,56 +1271,60 @@ export struct FbTaskPanel { this.kvRow('循环', this.repeatOf()) } - /* ---- 备注:可编辑 ---- */ - Column({ space: 4 }) { - Row({ space: 8 }) { - this.fieldLb('备注') - if (this.noteEdit) { - TextInput({ text: this.noteDraft, placeholder: '补充说明…' }) - .placeholderColor(FbColors.faint) - .placeholderFont({ size: FbMetric.fontTiny }) - .fontSize(FbMetric.fontSmall) - .fontColor(FbColors.ink) - .backgroundColor(FbColors.inputBg) - .borderRadius(FbMetric.radiusS) - .height(38) - .layoutWeight(1) - .padding({ left: 10, right: 10 }) - .onChange((v: string): void => { - this.noteDraft = v; - }) - .onSubmit((): void => { - this.saveNote(); - }) - /* 失焦也保存 —— 用户改完直接点别处是很自然的动作, - 等他再去找"保存"就会以为没存上。 */ - .onBlur((): void => { - this.saveNote(); - }) - } else { + /* ---- 备注 ---- */ + Column({ space: 6 }) { + this.fieldLb('备注') + if (this.noteEdit) { + TextArea({ text: this.noteDraft, placeholder: '补充说明…' }) + .placeholderColor(FbColors.faint) + .placeholderFont({ size: FbMetric.fontTiny }) + .fontSize(FbMetric.fontSmall) + .fontColor(FbColors.ink) + .backgroundColor(FbColors.inputBg) + .borderRadius(FbMetric.radiusS) + .width('100%') + .height(76) + .padding({ left: 12, right: 12, top: 10, bottom: 10 }) + .onChange((v: string): void => { + this.noteDraft = v; + }) + /* 失焦保存 —— 用户改完直接点别处是很自然的动作, + 等他再去找"保存"就会以为没存上。 */ + .onBlur((): void => { + this.saveNote(); + }) + } else { + Row({ space: 8 }) { Text(this.noteOf() !== '' ? this.noteOf() : '点这里添加备注…') .fontSize(FbMetric.fontSmall) .fontColor(this.noteOf() === '' ? FbColors.faint : FbColors.ink) + .maxLines(3) + .textOverflow({ overflow: TextOverflow.Ellipsis }) .layoutWeight(1) Text('✎') .fontSize(FbMetric.fontTiny) - .fontColor(this.accent) + .fontColor(this.inlineBusy ? FbColors.faint : this.accent) } + .width('100%') + .constraintSize({ minHeight: 40 }) + .padding({ left: 12, right: 12, top: 11, bottom: 11 }) + .backgroundColor(FbColors.inputBg) + .borderRadius(FbMetric.radiusS) + .alignItems(VerticalAlign.Top) + .onClick((): void => { + if (this.noteEdit || this.inlineBusy) { + return; + } + this.noteDraft = this.noteOf(); + this.noteEdit = true; + }) } - .width('100%') - .padding({ top: 7, bottom: 7 }) - .alignItems(VerticalAlign.Center) - .onClick((): void => { - if (this.noteEdit || this.inlineBusy) { - return; - } - this.noteDraft = this.noteOf(); - this.noteEdit = true; - }) } .width('100%') + .alignItems(HorizontalAlign.Start) } .width('100%') + .alignItems(HorizontalAlign.Start) .padding({ top: 4 }) } @@ -1343,26 +1381,35 @@ export struct FbTaskPanel { */ @Builder fieldLb(t: string) { + /* #77k:**不再写 width(48)** —— 现在标签独占一行(控件在它下面), + 固定宽度反而会让它在 Column 里只占左边一小段,与下面的整行控件左缘对不齐。 + 字号用 fontTiny(11)而不是 fontSmall(13): + 上下两行之后,标签再和控件同号就会抢视觉重心。 */ Text(t) - .fontSize(FbMetric.fontSmall) + .fontSize(FbMetric.fontTiny) .fontWeight(FontWeight.Bold) .fontColor(this.accent) .letterSpacing(0.6) - .width(48) + .width('100%') + .textAlign(TextAlign.Start) } @Builder kvRow(label: string, value: string) { - Row({ space: 8 }) { + /* #77k:与截止/负责人/备注同形态(标签一行、值一行), + 否则「分类」「循环」还是左右排,夹在中间会显得错位。 */ + Column({ space: 6 }) { this.fieldLb(label) Text(value) .fontSize(FbMetric.fontSmall) .fontColor(FbColors.ink) - .layoutWeight(1) + .width('100%') + .padding({ left: 12, right: 12, top: 11, bottom: 11 }) + .backgroundColor(FbColors.inputBg) + .borderRadius(FbMetric.radiusS) } .width('100%') - .padding({ top: 7, bottom: 7 }) - .alignItems(VerticalAlign.Top) + .alignItems(HorizontalAlign.Start) } /** 共享给谁(工单 #26):列表 + 共享入口 + 逐条取消 */