import { CATEGORY_LIST } from '../../core/data/categories'; type WorksheetItem = { _id: string; title: string; subtitle: string; category: string; previewImg: string; ageMin: number; ageMax: number; difficulty: 1 | 2 | 3 | 4; tags: string[]; tagsText: string; status: 'draft' | 'active' | 'hidden'; sortOrder: number; updatedAt: string; // display helpers ageBand: string; difficultyLabel: string; statusText: string; actionText: string; actionTarget: string; actionType: string; }; type Stats = { total: number; draft: number; active: number; hidden: number; }; type CloudFunctionResult = { success?: boolean; message?: string; data?: T; stats?: Stats; }; const DIFFICULTY_LABELS: Record = { 1: '入门', 2: '基础', 3: '进阶', 4: '挑战', }; const STATUS_CONFIG: Record< string, { text: string; action: string; target: string; actionType: string } > = { draft: { text: '草稿', action: '激活', target: 'active', actionType: 'green' }, active: { text: '线上', action: '下架', target: 'hidden', actionType: 'default' }, hidden: { text: '已隐藏', action: '恢复', target: 'draft', actionType: 'primary' }, }; function formatWorksheet(raw: Record): WorksheetItem { const status = String(raw.status || 'draft'); const cfg = STATUS_CONFIG[status] || STATUS_CONFIG.draft; const ageMin = Number(raw.ageMin) || 0; const ageMax = Number(raw.ageMax) || 0; const difficulty = (Number(raw.difficulty) || 2) as 1 | 2 | 3 | 4; return { _id: String(raw._id || ''), title: String(raw.title || ''), subtitle: String(raw.subtitle || ''), category: String(raw.category || ''), previewImg: String(raw.previewImg || ''), ageMin, ageMax, difficulty, tags: Array.isArray(raw.tags) ? raw.tags.map(String) : [], tagsText: Array.isArray(raw.tags) ? raw.tags.map(String).join('、') : '', status: status as WorksheetItem['status'], sortOrder: Number(raw.sortOrder) || 0, updatedAt: raw.updatedAt ? String(raw.updatedAt) : '', ageBand: `${ageMin}-${ageMax}岁`, difficultyLabel: DIFFICULTY_LABELS[difficulty] || '基础', statusText: cfg.text, actionText: cfg.action, actionTarget: cfg.target, actionType: cfg.actionType, }; } async function callCloudFunction( name: string, data?: Record, ): Promise> { const response = (await wx.cloud.callFunction({ name, data: data || {}, })) as { result?: CloudFunctionResult }; return response.result || {}; } Page({ data: { categories: CATEGORY_LIST, activeCategoryId: CATEGORY_LIST[0]?.id || 'math', worksheets: [] as WorksheetItem[], stats: { total: 0, draft: 0, active: 0, hidden: 0 } as Stats, loading: false, updatingId: '', building: false, }, onLoad() { void this.loadWorksheets(); }, async onPullDownRefresh() { await this.loadWorksheets(); wx.stopPullDownRefresh(); }, async loadWorksheets() { this.setData({ loading: true }); try { const result = await callCloudFunction( 'worksheetsQuery', { category: this.data.activeCategoryId }, ); if (!result.success) { throw new Error(result.message || '查询失败'); } const worksheets = (result.data || []).map((raw) => formatWorksheet(raw as unknown as Record), ); this.setData({ loading: false, worksheets, stats: result.stats || { total: 0, draft: 0, active: 0, hidden: 0, }, }); } catch (error) { this.setData({ loading: false }); wx.showToast({ title: error instanceof Error ? error.message : '查询失败', icon: 'none', }); } }, onCategoryTap(e: WechatMiniprogram.TouchEvent) { const id = e.currentTarget.dataset.id as string; if (!id || id === this.data.activeCategoryId) return; this.setData({ activeCategoryId: id }); void this.loadWorksheets(); }, async onStatusTap(e: WechatMiniprogram.TouchEvent) { const id = e.currentTarget.dataset.id as string; const target = e.currentTarget.dataset.target as string; if (!id || !target || this.data.updatingId) return; const ws = this.data.worksheets.find((w) => w._id === id); if (!ws) return; const confirmed = await new Promise((resolve) => { wx.showModal({ title: `${ws.actionText}`, content: `确认将「${ws.title}」${ws.actionText}吗?`, success: (res) => resolve(!!res.confirm), fail: () => resolve(false), }); }); if (!confirmed) return; this.setData({ updatingId: id }); try { const result = await callCloudFunction('worksheetsUpdateStatus', { id, status: target, }); if (!result.success) { throw new Error(result.message || '操作失败'); } wx.showToast({ title: `${ws.actionText}成功`, icon: 'success' }); await this.loadWorksheets(); } catch (error) { wx.showToast({ title: error instanceof Error ? error.message : '操作失败', icon: 'none', }); } finally { this.setData({ updatingId: '' }); } }, async onBuildTap() { if (this.data.building) return; const confirmed = await new Promise((resolve) => { wx.showModal({ title: '更新分类页数据', content: '将根据当前线上 worksheet 重新生成分类页数据,确认继续?', success: (res) => resolve(!!res.confirm), fail: () => resolve(false), }); }); if (!confirmed) return; this.setData({ building: true }); try { const result = await callCloudFunction<{ version: number; stats: Record; }>('pageContentBuild', { page: 'category' }); if (!result.success) { throw new Error(result.message || '生成失败'); } const version = result.data?.version || 0; wx.showToast({ title: `生成成功 v${version}`, icon: 'success', }); } catch (error) { wx.showToast({ title: error instanceof Error ? error.message : '生成失败', icon: 'none', }); } finally { this.setData({ building: false }); } }, });