feat: worksheet发布功能开发
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
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<DebugPublishMeta, 'title' | 'subtitle' | 'tags' | 'status'>;
|
||||
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<number, number> = {
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user