import type { WorksheetCloudCategory, WorksheetStatus, } from '../core/models/worksheet'; /** * 调试发布时的裁剪模式。 * - header-footer: 同 node-tools 入口图脚本,默认裁掉页眉和页脚 * - header-only: 仅裁掉页眉,保留底部品牌区 * - none: 不裁剪,直接压缩整张 A4 预览图 */ export type DebugCropMode = 'header-footer' | 'header-only' | 'none'; /** * 发布到 worksheets 集合的核心元数据。 * 这里对齐《小程序云开发方案》中的题型字段设计,供页面侧生成 payload 使用。 */ export interface DebugPublishMeta { id: string; title: string; subtitle: string; category: WorksheetCloudCategory; subcategory?: string; path: string; ageMin: number; ageMax: number; grade: number; difficulty: 1 | 2 | 3 | 4; previewImg?: string; tags: string[]; isNew: boolean; isHot: boolean; sortOrder?: number; status: WorksheetStatus; } /** 发布弹窗里可调的图片处理参数。 */ export interface DebugPublishSettings { cropMode: DebugCropMode; quality: number; width: number; maxSizeKB: number; } /** 弹窗确认后回传给页面的表单结果。 */ export interface DebugPublishConfirmDetail { meta: Pick; settings: DebugPublishSettings; } /** 图片处理组件收到的输入参数。 */ export interface DebugProcessImageParams { sourcePath: string; settings: DebugPublishSettings; } /** 图片处理完成后返回给页面的信息。 */ export interface DebugProcessImageResult { tempFilePath: string; size: number; width: number; height: number; quality: number; } /** 默认压缩质量,与文档里的入口图建议值保持一致。 */ export const DEBUG_PUBLISH_DEFAULT_QUALITY = 90; /** 默认入口图宽度,沿用 node-tools 脚本的 600px。 */ export const DEBUG_PUBLISH_DEFAULT_WIDTH = 600; /** 默认体积上限,超过后会继续降质压缩。 */ export const DEBUG_PUBLISH_MAX_SIZE_KB = 200; /** 页眉裁剪比例:110 / 842,来源于现有入口图脚本。 */ export const DEBUG_CROP_TOP_RATIO = 110 / 842; /** 页脚裁剪比例:52 / 842,来源于现有入口图脚本。 */ export const DEBUG_CROP_BOTTOM_RATIO = 52 / 842; /** 仅开发版开放 Debug 发布能力。 */ export function isDebugPublishEnabled(): boolean { const accountInfo = wx.getAccountInfoSync(); return accountInfo.miniProgram.envVersion === 'develop'; } /** 限制压缩质量范围,避免过高或过低。 */ export function clampPublishQuality(value: number): number { return Math.min(95, Math.max(40, Math.round(value))); } /** 限制输出宽度范围,防止导出过小或过大。 */ export function clampPublishWidth(value: number): number { return Math.min(1000, Math.max(400, Math.round(value))); } /** 根据裁剪模式计算顶部 / 底部裁剪比例。 */ export function getCropRatios(mode: DebugCropMode): { topRatio: number; bottomRatio: number; } { if (mode === 'header-only') { return { topRatio: DEBUG_CROP_TOP_RATIO, bottomRatio: 0, }; } if (mode === 'none') { return { topRatio: 0, bottomRatio: 0, }; } return { topRatio: DEBUG_CROP_TOP_RATIO, bottomRatio: DEBUG_CROP_BOTTOM_RATIO, }; } /** 统一构造预览图在云存储中的路径。 */ export function buildWorksheetPreviewCloudPath( category: WorksheetCloudCategory, id: string, ): string { return `assets/previews/${category}/${id}.jpg`; } /** 将输入框中的标签文本拆成标签数组,兼容英文逗号、中文逗号、顿号和空白。 */ export function normalizeTagsInput(raw: string): string[] { return raw .split(/[,,、\s]+/) .map((item) => item.trim()) .filter(Boolean); } /** * 由年龄段推断年级值。 * 当前先用“年龄中心点 -> 年级”的简单映射,后续如有更细分规则可独立替换。 */ export function inferGradeFromAge(ageMin: number, ageMax: number): number { const centerAge = Math.round((ageMin + ageMax) / 2); const ageGradeMap: Record = { 2: -4, 3: -3, 4: -2, 5: -1, 6: 0, 7: 1, 8: 2, 9: 3, 10: 4, 11: 5, 12: 6, }; return ageGradeMap[centerAge] ?? 0; }