diff --git a/entry/src/main/ets/model/Types.ets b/entry/src/main/ets/model/Types.ets index 8aec361..8f2e71f 100644 --- a/entry/src/main/ets/model/Types.ets +++ b/entry/src/main/ets/model/Types.ets @@ -641,6 +641,36 @@ export function isEditableEvent(e: FbCalEvent): boolean { return e.kind === 'custom' && e.id > 0 && e.calId > 0; } +/** + * 这个日程**现在能不能真的改**(决定详情卡要不要给「编辑日程」入口)。 + * + * 🔴 2026-10-29 真机实测发现的问题(工单 laoyang/FamilyBook#31): + * 首页只判了 `isEditableEvent()`(kind/id/calId),**没判写权限**, + * 于是「工作学习」这种只读共享本里的日程照样显示「编辑日程」, + * 用户改完点保存才被服务端拒:「保存失败:这本日历你没有写权限。」 + * ⇒ 能做什么要在**入口处**就说清,不能让用户白改一遍。 + * + * 写权限口径与 `FbCalRepo.fetchBooks()` 一致(它按 `/calendar/books` 的 + * `kind` + `perm` 算出 `FbCalBook.canWrite`),这里直接复用那个布尔值, + * 不再自行推导,避免两处漂移。 + * + * @param e 要判定的日程 + * @param books 当前账号的日历本列表(拿不到时**判为不可编辑**, + * 宁可少给入口,也不让用户改完才报错) + */ +export function isEventWritable(e: FbCalEvent, books: FbCalBook[]): boolean { + if (!isEditableEvent(e)) { + return false; + } + for (const b of books) { + if (b.id === e.calId) { + return b.canWrite; + } + } + /* 找不到这本 ⇒ 不认(可能是权限被撤、本被删,或 books 还没加载完) */ + return false; +} + /** 日历本(calendar/calendars) */ export interface FbCalBook { id: number; diff --git a/entry/src/main/ets/pages/calendar/FbCalendarPage.ets b/entry/src/main/ets/pages/calendar/FbCalendarPage.ets index 0e781ba..96f0549 100644 --- a/entry/src/main/ets/pages/calendar/FbCalendarPage.ets +++ b/entry/src/main/ets/pages/calendar/FbCalendarPage.ets @@ -28,7 +28,7 @@ import { common } from '@kit.AbilityKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { FbAppState, fbAppState } from '../../common/Store'; -import { FbCalBook, FbCalEvent, isEditableEvent } from '../../model/Types'; +import { FbCalBook, FbCalEvent, isEditableEvent, isEventWritable } from '../../model/Types'; import { parseCalendar } from '../../data/FbParse'; import { loadModule } from '../../data/FbModuleLoad'; import { FbCalRepo, FbCalEventFull } from '../../data/FbCalRepo'; @@ -899,7 +899,11 @@ export struct FbCalendarPage { accent: this.accent, bookName: this.detailBase !== null ? this.detailBase.calName : '', bookColor: this.detailBase !== null ? this.detailBase.color : '#9AA0A6', - canEdit: this.detailBase !== null && isEditableEvent(this.detailBase), + /* 🔴 2026-10-29(工单 laoyang/FamilyBook#31):原来只判 `isEditableEvent` + (kind/id/calId),**没判写权限** ⇒ 只读共享本里的日程也给「编辑日程」, + 用户改完点保存才报「这本日历你没有写权限」。改为按本的可写性判定。 + 本页 `books` 在页面加载时就拉了(见 `loadBooks`),不会出现空数组误判。 */ + canEdit: this.detailBase !== null && isEventWritable(this.detailBase, this.books), onNavigate: (): void => { this.navigateDetail(); }, diff --git a/entry/src/main/ets/pages/home/FbHomePage.ets b/entry/src/main/ets/pages/home/FbHomePage.ets index faccdac..9aa697b 100644 --- a/entry/src/main/ets/pages/home/FbHomePage.ets +++ b/entry/src/main/ets/pages/home/FbHomePage.ets @@ -41,7 +41,7 @@ import { FbColors, FbMetric, FB_MASK } from '../../common/Theme'; import { FbAppState, fbAppState } from '../../common/Store'; import { FbCalEvent, FbCalBook, FbCatOpt, FbHomeData, FbMark, FbMemoryItem, FbRecentDay, FbTaskItem, FbBoardOpt, FbTaskDetail, FbTaskMeta, taskKey, - FbWeather, isEditableEvent } from '../../model/Types'; + FbWeather, isEditableEvent, isEventWritable } from '../../model/Types'; import { common } from '@kit.AbilityKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; @@ -413,6 +413,16 @@ export struct FbHomePage { this.evtBase = e; this.evtFull = null; this.evtError = ''; + /* 🔴 2026-10-29(工单 #31):详情卡的「编辑日程」按 `calBooks[calId].canWrite` 判定, + 而 `calBooks` 原本是懒加载(只在新建/编辑时才拉)⇒ 刚进详情时它还是空数组, + 会把**本来能编辑**的日程也误判成只读。 + 这里顺手拉一次(拉过就复用,`ensureCalBooks` 内部有缓存判断), + 不 await —— 详情内容先出来,按钮随 books 到位再显示,不拖慢打开速度。 */ + if (this.calBooks.length === 0) { + this.ensureCalBooks().catch((): void => { + /* 拉不到就维持"不给编辑入口",比让用户白改一遍好 */ + }); + } if (!isEditableEvent(e)) { this.evtLoading = false; this.evtFull = this.shellOf(e); @@ -1498,7 +1508,13 @@ export struct FbHomePage { 那个理由成立,但**结论错了** —— 正确解法不是"不给编辑", 而是"编辑也不许跳"(与 v79 任务面板的处理完全一致)。 现在点「编辑」只在本页叠一张表单,卡片不动、模块不动。 */ - canEdit: true, + /* 🔴 2026-10-29 真机实测修(工单 laoyang/FamilyBook#31): + 原来这里写死 `true`,于是**只读共享本**(如「工作学习」)里的日程 + 也显示「编辑日程」,用户改完点保存才被服务端拒 + 「保存失败:这本日历你没有写权限。」 + v86 开编辑入口的决定本身没错(编辑就地改、不跳页), + 错在没把"没有写权限的本"排除掉 ⇒ 改为按 calWrite 判定。 */ + canEdit: this.evtBase !== null && isEventWritable(this.evtBase, this.calBooks), onNavigate: (): void => { this.navigateEvent(); },