任务共享:面板补「共享给谁」区块 laoyang/FamilyBook#26
用户原话(2026-10-28):「鸿蒙端对齐网页端」。任务面板原来没有共享入口,现在: 1) FbTaskShare 类型 + parseTaskDetail 解析 Task::find 已带的 shares 2) FbTaskRepo 补 fetchTaskShares/shareTask/unshareTask(删除走 query) 3) FbTaskPanel 加「共享给谁」区块:列表(可改/只看)+ 逐条取消 + 「+ 共享」复用选人组件(与资源/财务共享同一套) 编译 BUILD SUCCESSFUL;服务端冒烟 _i26_task_share_api.py 13/0 + 反证命中。
This commit is contained in:
@@ -31,17 +31,20 @@
|
||||
|
||||
import { FbColors, FbMetric, FB_MASK, fbAlpha, fbTint } from '../common/Theme';
|
||||
import {
|
||||
FbBoardOpt, FbTaskAttach, FbTaskComment, FbTaskDetail, FbTaskItem, FbTaskKid,
|
||||
FbBoardOpt, FbTaskAttach, FbTaskComment, FbTaskDetail, FbTaskItem, FbTaskKid, FbTaskShare,
|
||||
} from '../model/Types';
|
||||
import { FbSheetRing } from './FbSheetRing';
|
||||
import { FbSheetClose } from './FbSheetClose';
|
||||
import { FbCheckCircle } from './Widgets';
|
||||
import { FbPersonPickSheet } from './FbPersonPickSheet';
|
||||
import { FbPersonRepo, FbRosterPerson } from '../data/FbPersonRepo';
|
||||
import { FB_TOKEN_STORE } from '../data/FbTokenStore';
|
||||
import { FbApiResult } from '../data/FbHttp';
|
||||
import { fbImageSrc } from '../data/FbAttachQueue';
|
||||
import {
|
||||
addTaskComment, createTask, deleteTask, delTaskAttach, getTask, moveTask,
|
||||
setTaskStatus, uploadTaskAttach, FbTaskDraft,
|
||||
fetchTaskShares, shareTask, unshareTask,
|
||||
} from '../data/FbTaskRepo';
|
||||
import { parseTaskDetail } from '../data/FbParse';
|
||||
import { picker } from '@kit.CoreFileKit';
|
||||
@@ -104,6 +107,10 @@ export struct FbTaskPanel {
|
||||
/** 删除按钮点第一次 → 变成「确定删除?」 */
|
||||
@Local confirmDel: boolean = false;
|
||||
@Local uploading: boolean = false;
|
||||
// 共享(工单 #26)
|
||||
@Local roster: FbRosterPerson[] = [];
|
||||
@Local pickingShare: boolean = false;
|
||||
@Local shareBusy: boolean = false;
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.reload();
|
||||
@@ -231,6 +238,52 @@ export struct FbTaskPanel {
|
||||
return d !== null ? d.attachs : [];
|
||||
}
|
||||
|
||||
/** 共享给谁(工单 #26) */
|
||||
private shares(): FbTaskShare[] {
|
||||
const d: FbTaskDetail | null = this.detail;
|
||||
return d !== null ? d.shares : [];
|
||||
}
|
||||
|
||||
private async openSharePicker(): Promise<void> {
|
||||
if (this.roster.length === 0) {
|
||||
try {
|
||||
this.roster = await FbPersonRepo.inst().list();
|
||||
} catch (e) {
|
||||
this.roster = [];
|
||||
}
|
||||
}
|
||||
this.pickingShare = true;
|
||||
}
|
||||
|
||||
private async addShares(ids: number[]): Promise<void> {
|
||||
this.pickingShare = false;
|
||||
if (ids.length === 0) {
|
||||
return;
|
||||
}
|
||||
this.shareBusy = true;
|
||||
let bad: string = '';
|
||||
for (const pid of ids) {
|
||||
const res: FbApiResult = await shareTask(this.token(), this.taskId, pid, 'write');
|
||||
if (!res.ok && bad === '') {
|
||||
bad = res.error;
|
||||
}
|
||||
}
|
||||
this.shareBusy = false;
|
||||
this.note = bad !== '' ? bad : '';
|
||||
await this.reload();
|
||||
}
|
||||
|
||||
private async dropShare(personId: number): Promise<void> {
|
||||
this.shareBusy = true;
|
||||
const res: FbApiResult = await unshareTask(this.token(), this.taskId, personId);
|
||||
this.shareBusy = false;
|
||||
if (!res.ok) {
|
||||
this.note = res.error !== '' ? res.error : '没取消成。';
|
||||
return;
|
||||
}
|
||||
await this.reload();
|
||||
}
|
||||
|
||||
private categoryOf(): string {
|
||||
const d: FbTaskDetail | null = this.detail;
|
||||
return d !== null ? d.category : '';
|
||||
@@ -515,6 +568,7 @@ export struct FbTaskPanel {
|
||||
this.statusSeg()
|
||||
this.boardChips()
|
||||
this.infoRows()
|
||||
this.shareSection()
|
||||
this.kidSection()
|
||||
this.attachSection()
|
||||
this.commentSection()
|
||||
@@ -551,6 +605,22 @@ export struct FbTaskPanel {
|
||||
}
|
||||
}
|
||||
.width('94%')
|
||||
|
||||
/* 选人浮层:共享给谁(工单 #26) */
|
||||
if (this.pickingShare) {
|
||||
FbPersonPickSheet({
|
||||
people: this.roster,
|
||||
selected: [],
|
||||
title: '共享给谁',
|
||||
accent: this.accent,
|
||||
onConfirm: (ids: number[]): void => {
|
||||
this.addShares(ids);
|
||||
},
|
||||
onClose: (): void => {
|
||||
this.pickingShare = false;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
@@ -754,6 +824,70 @@ export struct FbTaskPanel {
|
||||
.alignItems(VerticalAlign.Top)
|
||||
}
|
||||
|
||||
/** 共享给谁(工单 #26):列表 + 共享入口 + 逐条取消 */
|
||||
@Builder
|
||||
shareSection() {
|
||||
Column({ space: 6 }) {
|
||||
Row({ space: 6 }) {
|
||||
Text('共享给谁')
|
||||
.fontSize(FbMetric.fontSmall)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor(FbColors.ink)
|
||||
if (this.shares().length > 0) {
|
||||
Text(this.shares().length.toString())
|
||||
.fontSize(FbMetric.fontTiny)
|
||||
.fontColor(FbColors.faint)
|
||||
}
|
||||
Blank()
|
||||
Text(this.shareBusy ? '处理中…' : '+ 共享')
|
||||
.fontSize(FbMetric.fontTiny)
|
||||
.fontColor(this.shareBusy ? FbColors.faint : this.accent)
|
||||
.padding({ left: 10, right: 10, top: 6, bottom: 6 })
|
||||
.backgroundColor(fbAlpha(this.accent, 0.1))
|
||||
.borderRadius(FbMetric.radiusPill)
|
||||
.onClick((): void => {
|
||||
this.openSharePicker();
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.padding({ top: 12 })
|
||||
.alignItems(VerticalAlign.Center)
|
||||
|
||||
if (this.shares().length === 0) {
|
||||
Text('还没共享给谁;共享后对方能在任务里看到它,权限分「可改 / 只看」')
|
||||
.fontSize(FbMetric.fontTiny)
|
||||
.fontColor(FbColors.faint)
|
||||
.width('100%')
|
||||
} else {
|
||||
ForEach(this.shares(), (s: FbTaskShare) => {
|
||||
Row({ space: 8 }) {
|
||||
Text(s.name)
|
||||
.fontSize(FbMetric.fontSmall)
|
||||
.fontColor(FbColors.ink)
|
||||
.layoutWeight(1)
|
||||
.maxLines(1)
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
Text(s.perm === 'read' ? '只看' : '可改')
|
||||
.fontSize(FbMetric.fontTiny)
|
||||
.fontColor(FbColors.faint)
|
||||
Text('取消')
|
||||
.fontSize(FbMetric.fontTiny)
|
||||
.fontColor(FbColors.red)
|
||||
.padding({ left: 6, right: 2, top: 2, bottom: 2 })
|
||||
.onClick((): void => {
|
||||
this.dropShare(s.personId);
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.padding({ top: 6, bottom: 6 })
|
||||
.alignItems(VerticalAlign.Center)
|
||||
}, (s: FbTaskShare): string => 'tsh_' + s.personId.toString())
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
}
|
||||
|
||||
/** 子任务:列表 + 加一条 */
|
||||
@Builder
|
||||
kidSection() {
|
||||
|
||||
Reference in New Issue
Block a user