import PaperDrawService from './draw/paperDrawService'; import { PAPER_SHEET_WORKSHEET_ID, PAPER_TYPE_OPTIONS, PAPER_COLOR_OPTIONS, DEFAULT_PAPER_TYPE, DEFAULT_PAPER_COLOR, getModeInfo, getPublishMetaByMode, isValidPaperType, resolvePaperEntry, getWorksheetIdForPaperType, type PaperType, } from './paperSheet.config'; import { createPage, getPageCommonMethods, type CanvasDataState, } from '../../base/pageMixin'; import { getWorksheet } from '../../services/content-api'; import { defaultShareConfig } from '../../config/config'; import type { DebugPublishMeta } from '../../utils/debugPublish'; import { addFavorite, removeFavorite, batchCheckFavorited, } from '../../utils/favorites'; const pageInfoLookup = getModeInfo; const commonMethods = getPageCommonMethods({ pageInfoLookup, shareConfig: defaultShareConfig, }); type PageData = CanvasDataState & { worksheetId: string; paperTypeOptions: typeof PAPER_TYPE_OPTIONS; colorOptions: typeof PAPER_COLOR_OPTIONS; selectedPaperType: PaperType; selectedColor: string; isPreviewFavorite: boolean; isWorksheetReady: boolean; favoriteLoading: boolean; isDevEnv: boolean; debugPublishVisible: boolean; debugPublishLoading: boolean; debugPublishMeta: DebugPublishMeta | null; }; createPage( { canvas: null as Canvas | null, ctx: null as RenderingContext | null, boxHeight: 0, boxWidth: 0, drawService: null as PaperDrawService | null, _favoritedMap: {} as Record, _entryRequest: 0, _favoriteVersions: {} as Record, data: { pageTitle: '作业纸', functionId: PAPER_SHEET_WORKSHEET_ID, hasContent: false, showShareDialog: false, worksheetId: PAPER_SHEET_WORKSHEET_ID, paperTypeOptions: PAPER_TYPE_OPTIONS, colorOptions: PAPER_COLOR_OPTIONS, selectedPaperType: DEFAULT_PAPER_TYPE, selectedColor: DEFAULT_PAPER_COLOR, isPreviewFavorite: false, isWorksheetReady: false, favoriteLoading: false, isDevEnv: false, debugPublishVisible: false, debugPublishLoading: false, debugPublishMeta: null, } as unknown as PageData, async onLoad(options: { id?: string; type?: string; mode?: string }) { this.syncDebugPublishEnv(); await this.openEntry(options); this.loadFavoritedMap(); }, onUnload() { this._entryRequest++; }, /** 开发版直接预览已注册配置以制作封面;体验/正式版切换前校验公开状态。 */ async openEntry(options: { id?: string; type?: string; mode?: string; }) { const request = ++this._entryRequest; this.setData({ isWorksheetReady: false, hasContent: false, // 换纸张即丢弃旧发布表单,防止旧条目元数据配上新封面。 debugPublishVisible: false, debugPublishMeta: null, }); try { const { entry, paperType } = resolvePaperEntry(options); // 草稿在公开详情中固定为 404;开发版使用本地注册配置,不通过失败请求判断预览权限。 if (!this.data.isDevEnv) { const remote = await getWorksheet(entry.id); if ( entry.id !== PAPER_SHEET_WORKSHEET_ID && (remote.rendering?.rendererKey !== entry.rendererKey || remote.rendering?.paperType !== paperType) ) { throw new Error('作业纸配置暂不可用,请更新小程序'); } } if (request !== this._entryRequest) return; this.setData({ worksheetId: entry.id, selectedPaperType: paperType, // 综合入口分享保留所选纸张;独立条目由 ID 唯一确定纸张类型。 currentMode: entry.id === PAPER_SHEET_WORKSHEET_ID ? paperType : entry.id, isPreviewFavorite: this._favoritedMap[entry.id] === true, isWorksheetReady: true, }); this.initPageInfo(entry.id, entry.title); await this.drawCanvas(); } catch (error) { if (request !== this._entryRequest) return; wx.showToast({ title: error instanceof Error ? error.message : '作业纸加载失败', icon: 'none', }); } }, onCanvasReady(e: WechatMiniprogram.CustomEvent) { this.initCanvasFromComponent(e.detail, { createDrawService: ( canvas: Canvas, ctx: RenderingContext, opts?: Record, ) => new PaperDrawService(canvas, ctx, opts), drawServiceOptions: { title: this.data.pageTitle, }, onCanvasReady: () => { this.drawCanvas(); }, }); }, async drawCanvas() { if (!this.drawService || !this.data.isWorksheetReady) return; const request = this._entryRequest; try { await (this.drawService as PaperDrawService).draw( this.data.selectedPaperType, this.data.selectedColor, ); if ( request === this._entryRequest && this.data.isWorksheetReady ) this.setData({ hasContent: true }); } catch (err) { console.error('paperSheet draw failed', err); if (request === this._entryRequest) this.setData({ hasContent: false }); } }, onSelectPaperType(e: WechatMiniprogram.TouchEvent) { const id = e.currentTarget.dataset.id as string | undefined; if (!id || !isValidPaperType(id)) return; const worksheetId = getWorksheetIdForPaperType(id); if ( worksheetId === this.data.worksheetId && this.data.isWorksheetReady ) return; return this.openEntry({ id: worksheetId }); }, onSelectColor(e: WechatMiniprogram.TouchEvent) { const value = e.currentTarget.dataset.value as string | undefined; if (!value || value === this.data.selectedColor) return; this.setData({ selectedColor: value }, () => this.drawCanvas()); }, onPreviewRefresh() { this.drawCanvas(); }, onShare() {}, async exportToPrint() { if (!this.data.isWorksheetReady || !this.data.hasContent) return; return commonMethods.exportToPrint.call(this); }, async onShareSuccess() { if (!this.data.isWorksheetReady || !this.data.hasContent) { this.setData({ showShareDialog: false }); return; } return commonMethods.onShareSuccess.call(this); }, /** 请求失败不显示收藏成功,且响应只更新操作时的条目。 */ async onPreviewFavorite() { if (!this.data.isWorksheetReady || this.data.favoriteLoading) return; const id = this.data.worksheetId; const next = !this.data.isPreviewFavorite; this._favoriteVersions[id] = (this._favoriteVersions[id] || 0) + 1; this.setData({ favoriteLoading: true }); try { const ok = await (next ? addFavorite(id) : removeFavorite(id)); if (ok) { this._favoritedMap[id] = next; if (this.data.worksheetId === id) this.setData({ isPreviewFavorite: next }); } wx.showToast({ title: ok ? next ? '收藏成功' : '已取消收藏' : '收藏操作失败,请重试', icon: 'none', }); } finally { this.setData({ favoriteLoading: false }); } }, async loadFavoritedMap() { const ids = [ PAPER_SHEET_WORKSHEET_ID, ...PAPER_TYPE_OPTIONS.map((paper) => getWorksheetIdForPaperType(paper.id), ), ]; const versions = { ...this._favoriteVersions }; try { const map = await batchCheckFavorited(ids); // 慢速初次查询不能覆盖查询期间完成的收藏操作。 for (const id of ids) { if (versions[id] === this._favoriteVersions[id]) this._favoritedMap[id] = map[id] === true; } this.setData({ isPreviewFavorite: this._favoritedMap[this.data.worksheetId] === true, }); } catch { // 收藏加载失败不阻止预览;后续操作仍以服务端写入结果为准。 } }, getWorksheetStatsId(): string { return this.data.worksheetId; }, getPublishMeta(): DebugPublishMeta { if (!this.data.isWorksheetReady) throw new Error('请先加载作业纸'); const meta = getPublishMetaByMode(this.data.worksheetId); if (!meta) { throw new Error('当前题型配置不存在'); } return meta; }, }, { shareConfig: defaultShareConfig, pageInfoLookup, }, );