diff --git a/miniprogram/api/JournalApi.ts b/miniprogram/api/JournalApi.ts index 4bc43c3..0c01222 100644 --- a/miniprogram/api/JournalApi.ts +++ b/miniprogram/api/JournalApi.ts @@ -86,4 +86,9 @@ export class JournalApi { static getListByIds(ids: number[]): Promise { return Network.post("/journal/list/ids", ids); } + + /** 是否有上传权限 */ + static canUpload(): Promise { + return Network.post("/journal/can-upload"); + } } diff --git a/miniprogram/app.ts b/miniprogram/app.ts index db4f490..9b8e28e 100644 --- a/miniprogram/app.ts +++ b/miniprogram/app.ts @@ -1,7 +1,24 @@ // app.ts +import Permission from "./utils/Permission"; + +const originPage = Page; + +(globalThis as any).Page = function (options: WechatMiniprogram.Page.Options) { + const originalOnShow = options.onShow; + return originPage({ + ...options, + async onShow(...args: any[]) { + await Permission.checkAndCacheUploadPermission(); + if (originalOnShow) { + return await originalOnShow.apply(this, args); + } + } + }); +}; + App({ globalData: { }, onLaunch() { }, -}) \ No newline at end of file +}) diff --git a/miniprogram/pages/main/tabs/journal/index.ts b/miniprogram/pages/main/tabs/journal/index.ts index c3a3e1c..fcf18f0 100644 --- a/miniprogram/pages/main/tabs/journal/index.ts +++ b/miniprogram/pages/main/tabs/journal/index.ts @@ -9,6 +9,7 @@ import { OrderType } from "../../../../types/Model"; import { PreviewImageMetadata } from "../../../../types/Attachment"; import { MediaItem, MediaItemType } from "../../../../types/UI"; import { JournalApi } from "../../../../api/JournalApi"; +import Permission from "../../../../utils/Permission"; interface JournalData { page: JournalPage; @@ -23,6 +24,7 @@ interface JournalData { isShowMoreMenu: boolean; menuTop: number; menuLeft: number; + canUpload: boolean; } Page({ @@ -52,7 +54,17 @@ Page({ stickyOffset: 0, isShowMoreMenu: false, menuTop: 0, - menuLeft: 0 + menuLeft: 0, + canUpload: false + }, + async onShow() { + const cached = Permission.getCachedUploadPermission(); + if (cached !== null) { + this.setData({ canUpload: cached }); + return; + } + const canUpload = await Permission.checkAndCacheUploadPermission(); + this.setData({ canUpload }); }, onLoad() { Events.reset("JOURNAL_REFRESH", () => { diff --git a/miniprogram/pages/main/tabs/journal/index.wxml b/miniprogram/pages/main/tabs/journal/index.wxml index 4b9134e..3729016 100644 --- a/miniprogram/pages/main/tabs/journal/index.wxml +++ b/miniprogram/pages/main/tabs/journal/index.wxml @@ -12,8 +12,8 @@ style="top: {{menuTop}}px; left: {{menuLeft}}px;" catchtap="stopPropagation" > - - + + @@ -53,4 +53,4 @@ 已回到最初的起点 - \ No newline at end of file + diff --git a/miniprogram/pages/main/tabs/moment/index.ts b/miniprogram/pages/main/tabs/moment/index.ts index 38b1b0a..aae15f1 100644 --- a/miniprogram/pages/main/tabs/moment/index.ts +++ b/miniprogram/pages/main/tabs/moment/index.ts @@ -9,6 +9,7 @@ import { PreviewImageMetadata } from "../../../../types/Attachment"; import { MomentApi } from "../../../../api/MomentApi"; import { JournalApi } from "../../../../api/JournalApi"; import { Network } from "../../../../utils/Network"; +import Permission from "../../../../utils/Permission"; type Item = { id: number; @@ -44,6 +45,7 @@ interface MomentData { isVisibleArchivePopup: boolean; archiveStep: ArchiveStep; selectedJournalId: number | null; + canUpload: boolean; } Page({ @@ -64,10 +66,11 @@ Page({ isAuthLocation: false, isVisibleArchivePopup: false, archiveStep: "select-type", - selectedJournalId: null + selectedJournalId: null, + canUpload: false }, async onLoad() { - this.fetch(); + await this.fetch(); // 授权定位 const setting = await wx.getSetting(); @@ -116,6 +119,15 @@ Page({ }); }); }, + async onShow() { + const cached = Permission.getCachedUploadPermission(); + if (cached !== null) { + this.setData({ canUpload: cached }); + } else { + const canUpload = await Permission.checkAndCacheUploadPermission(); + this.setData({ canUpload }); + } + }, async chooseLocation() { const location = await wx.chooseLocation({}); this.setData({ diff --git a/miniprogram/pages/main/tabs/moment/index.wxml b/miniprogram/pages/main/tabs/moment/index.wxml index a7c5f6f..857a699 100644 --- a/miniprogram/pages/main/tabs/moment/index.wxml +++ b/miniprogram/pages/main/tabs/moment/index.wxml @@ -3,12 +3,12 @@ - + 由于微信限制,一次只能上传 20 张照片或视频,可以先在此页面分批次将所有照片或视频上传, 记得勾选原图 。无需担心重复选择,已上传的文件不会再次上传。上传后有空再挑选归档,归档后此页面不再显示该照片或视频。 - + 删除已选 - + - \ No newline at end of file + diff --git a/miniprogram/pages/main/tabs/other/index.ts b/miniprogram/pages/main/tabs/other/index.ts index 779e01f..091ec89 100644 --- a/miniprogram/pages/main/tabs/other/index.ts +++ b/miniprogram/pages/main/tabs/other/index.ts @@ -1,27 +1,54 @@ +import Permission from "../../../../utils/Permission"; + type NavItem = { title: string; icon: string; url: string; + requiredUploadPermission: boolean; }; interface OtherData { navList: NavItem[]; + canUpload: boolean; +} + +const baseNavList: NavItem[] = [ + { + title: "备忘录", + icon: "task-checked", + url: "/pages/main/other/memo/index", + requiredUploadPermission: true + }, + { + title: "专拍", + icon: "face-retouching", + url: "/pages/main/other/portfolio/index", + requiredUploadPermission: false + } +]; + +function buildNavList(canUpload: boolean): NavItem[] { + if (canUpload) { + return [...baseNavList]; + } + return baseNavList.filter((item) => !item.requiredUploadPermission); } Page({ data: { - navList: [ - { - title: "备忘录", - icon: "task-checked", - url: "/pages/main/other/memo/index" - }, - { - title: "专拍", - icon: "face-retouching", - url: "/pages/main/other/portfolio/index" - } - ], + navList: buildNavList(false), + canUpload: false + }, + async onShow() { + const cached = Permission.getCachedUploadPermission(); + let canUpload = cached; + if (cached === null) { + canUpload = await Permission.checkAndCacheUploadPermission(); + } + this.setData({ + canUpload: !!canUpload, + navList: buildNavList(!!canUpload) + }); }, onNavTap(e: WechatMiniprogram.BaseEvent) { const { url } = e.currentTarget.dataset as { url?: string }; diff --git a/miniprogram/pages/main/tabs/travel/index.ts b/miniprogram/pages/main/tabs/travel/index.ts index 26de7a3..afbea93 100644 --- a/miniprogram/pages/main/tabs/travel/index.ts +++ b/miniprogram/pages/main/tabs/travel/index.ts @@ -3,6 +3,7 @@ import Time from "../../../../utils/Time"; import { TravelApi } from "../../../../api/TravelApi"; import { Travel, TravelPage, TravelStatus, TravelStatusLabel, TravelStatusIcon, TransportationTypeLabel, TransportationTypeIcon } from "../../../../types/Travel"; +import Permission from "../../../../utils/Permission"; interface TravelData { /** 分页参数 */ @@ -28,6 +29,8 @@ interface TravelData { transportLabels: typeof TransportationTypeLabel; /** 交通类型图标映射 */ transportIcons: typeof TransportationTypeIcon; + /** 是否允许上传 */ + canUpload: boolean; } Page({ @@ -46,12 +49,20 @@ Page({ statusLabels: TravelStatusLabel, statusIcons: TravelStatusIcon, transportLabels: TransportationTypeLabel, - transportIcons: TransportationTypeIcon + transportIcons: TransportationTypeIcon, + canUpload: false }, onLoad() { this.resetAndFetch(); }, - onShow() { + async onShow() { + const cached = Permission.getCachedUploadPermission(); + if (cached !== null) { + this.setData({ canUpload: cached }); + } else { + const canUpload = await Permission.checkAndCacheUploadPermission(); + this.setData({ canUpload }); + } // 页面显示时刷新数据(从编辑页返回时) if (0 < this.data.list.length) { this.resetAndFetch(); diff --git a/miniprogram/pages/main/tabs/travel/index.wxml b/miniprogram/pages/main/tabs/travel/index.wxml index 2ace7d4..dc56431 100644 --- a/miniprogram/pages/main/tabs/travel/index.wxml +++ b/miniprogram/pages/main/tabs/travel/index.wxml @@ -96,6 +96,6 @@ 没有更多了 - + diff --git a/miniprogram/pages/main/travel/detail/index.ts b/miniprogram/pages/main/travel/detail/index.ts index 71178fb..0817f0f 100644 --- a/miniprogram/pages/main/travel/detail/index.ts +++ b/miniprogram/pages/main/travel/detail/index.ts @@ -5,6 +5,7 @@ import { TravelApi } from "../../../../api/TravelApi"; import { TravelLocationApi } from "../../../../api/TravelLocationApi"; import config from "../../../../config/index"; import { Travel, TravelStatusLabel, TravelStatusIcon, TransportationTypeLabel, TravelLocation, TravelLocationTypeLabel, TravelLocationTypeIcon, TransportationTypeIcon, TravelLocationType } from "../../../../types/Travel"; +import Permission from "../../../../utils/Permission"; interface TravelLocationView extends TravelLocation { /** 预览图 */ @@ -42,6 +43,8 @@ interface TravelDetailData { deleteDialogVisible: boolean; /** 删除确认文本 */ deleteConfirmText: string; + /** 是否允许上传 */ + canUpload: boolean; } Page({ @@ -60,7 +63,8 @@ Page({ locationTypes: ["全部", ...Object.values(TravelLocationTypeLabel)], selectedLocationTypeIndex: 0, deleteDialogVisible: false, - deleteConfirmText: "" + deleteConfirmText: "", + canUpload: false }, onLoad(options: any) { @@ -79,10 +83,17 @@ Page({ } }, - onShow() { + async onShow() { + const cached = Permission.getCachedUploadPermission(); + if (cached !== null) { + this.setData({ canUpload: cached }); + } else { + const canUpload = await Permission.checkAndCacheUploadPermission(); + this.setData({ canUpload }); + } // 页面显示时刷新地点列表(从编辑页返回时) if (this.data.travelId && !this.data.isLoading) { - this.fetchLocations(this.data.travelId); + await this.fetchLocations(this.data.travelId); } }, diff --git a/miniprogram/pages/main/travel/detail/index.wxml b/miniprogram/pages/main/travel/detail/index.wxml index 04265c3..67e30fa 100644 --- a/miniprogram/pages/main/travel/detail/index.wxml +++ b/miniprogram/pages/main/travel/detail/index.wxml @@ -1,7 +1,7 @@ - + @@ -61,7 +61,14 @@ - + @@ -117,6 +124,7 @@ - + @@ -120,7 +120,7 @@ - + | null = null; + +function parseCachedValue(value: unknown): boolean | null { + if (value === true || value === false) { + return value; + } + if (value === "true") { + return true; + } + if (value === "false") { + return false; + } + return null; +} + +export default class Permission { + /** 获取缓存的上传权限(不存在则返回 null) */ + static getCachedUploadPermission(): boolean | null { + if (cachedCanUpload !== null) { + return cachedCanUpload; + } + try { + const value = wx.getStorageSync(UPLOAD_PERMISSION_KEY); + const parsed = parseCachedValue(value); + if (parsed !== null) { + cachedCanUpload = parsed; + return parsed; + } + } catch (error) { + console.warn("读取上传权限缓存失败", error); + } + return null; + } + + /** 检查并缓存上传权限 */ + static async checkAndCacheUploadPermission(): Promise { + if (pendingCheck) { + return await pendingCheck; + } + pendingCheck = (async () => { + try { + const canUpload = await JournalApi.canUpload(); + cachedCanUpload = !!canUpload; + wx.setStorageSync(UPLOAD_PERMISSION_KEY, cachedCanUpload); + return cachedCanUpload; + } catch (error) { + console.error("检查上传权限失败", error); + const cached = this.getCachedUploadPermission(); + const fallback = cached !== null ? cached : false; + return fallback; + } finally { + pendingCheck = null; + } + })(); + return await pendingCheck; + } +}