feat:架构代码优化

This commit is contained in:
R524809
2025-12-11 13:02:44 +08:00
parent 2c32235568
commit 3c0e2af10d
89 changed files with 2774 additions and 2816 deletions
+338
View File
@@ -0,0 +1,338 @@
import { PAPER_SIZE } from '../constants/colors';
import { checkAndSaveImage } from '../utils/saveImage';
import { shouldShowShareGuide } from '../utils/shareGuide';
import { BaseDrawService } from '../service/baseDraw';
import tracker from '../utils/tracker';
/**
* Canvas 相关的页面实例属性
*/
export interface PageCanvasInstance {
data: CanvasDataState;
canvas: Canvas | null;
ctx: RenderingContext | null;
boxHeight: number;
boxWidth: number;
drawService: BaseDrawService | null;
setData(data: any, callback?: () => void): void;
route: string;
getShareOptions(): ShareOptions;
}
/**
* Canvas 数据状态接口
*/
export interface CanvasDataState {
hasContent: boolean;
showShareDialog: boolean;
boxWidth: number;
boxHeight: number;
functionId: string;
currentMode?: string;
pageTitle: string;
subTitle?: string;
data: any;
setData(data: any, callback?: () => void): void;
route: string;
}
/**
* Canvas 初始化选项
*/
export interface InitCanvasOptions {
/**
* 创建绘制服务的工厂函数
*/
createDrawService: (
canvas: Canvas,
ctx: RenderingContext,
options?: Record<string, any>,
) => BaseDrawService;
/**
* 绘制服务的选项
*/
drawServiceOptions?: Record<string, any>;
/**
* Canvas 初始化完成后回调
*/
onCanvasReady?: () => void;
}
/**
* 分享配置选项
*/
export interface ShareOptions {
/**
* 页面路径(相对于 mathPages 目录,例如:'missingNumber/missingNumber'
*/
path: string;
title: string;
imageUrl: string;
}
/**
* 页面信息接口
*/
export interface PageInfo {
title: string;
desc?: string;
}
/**
* 页面信息查找函数类型
*/
export type PageInfoLookup = (functionId: string) => PageInfo | undefined;
/**
* 页面公共方法配置
*/
export interface PageCommonMethodsConfig {
/**
* 分享配置
*/
shareConfig?: {
title: string;
imageUrl: string;
};
/**
* 页面信息查找函数(可选)
* 如果提供,initPageInfo 方法会使用它来查找页面信息
*/
pageInfoLookup?: PageInfoLookup;
}
const defaultShareConfig = {
title: '涂鸦丫',
imageUrl: 'https://cdn.joeyone.cn/doodle/share-img/index-share-v2.png',
};
/**
* 获取页面公共方法
* 这些方法可以在所有Canvas绘制页面中复用
* @param config 配置选项
*/
export function getPageCommonMethods(config: PageCommonMethodsConfig = {}) {
const { shareConfig = defaultShareConfig, pageInfoLookup } = config;
return {
/**
* 初始化 Canvas
*/
initCanvas(this: PageCanvasInstance, options: InitCanvasOptions) {
const query = wx.createSelectorQuery();
query
.select('#canvasWrapper')
.boundingClientRect((rect) => {
if (!rect) return;
const { width, height } = PAPER_SIZE['A4'];
const boxWidth = rect.width;
const boxHeight = boxWidth / (width / height);
this.boxHeight = boxHeight;
this.boxWidth = boxWidth;
this.setData({ boxWidth, boxHeight });
const canvas = wx
.createSelectorQuery()
.select('#canvasContent');
canvas.fields({ node: true, size: true }).exec((res) => {
if (res[0]) {
const canvasNode = res[0].node;
const ctx = canvasNode.getContext('2d');
const dpr = wx.getSystemInfoSync().pixelRatio;
canvasNode.width = boxWidth * dpr;
canvasNode.height = boxHeight * dpr;
ctx.scale(dpr, dpr);
this.canvas = canvasNode;
this.ctx = ctx;
// 创建绘制服务
const drawServiceOptions = {
title: this.data.pageTitle,
subTitle: this.data.subTitle || '',
...options.drawServiceOptions,
};
this.drawService = options.createDrawService(
canvasNode,
ctx,
drawServiceOptions,
);
// 执行初始化完成回调
if (options.onCanvasReady) {
options.onCanvasReady.call(this);
}
}
});
})
.exec();
},
/**
* 导出打印
*/
exportToPrint(this: PageCanvasInstance) {
if (!this.canvas || !this.data.hasContent) {
return;
}
if (shouldShowShareGuide()) {
this.setData({ showShareDialog: true });
return;
}
// 上报下载埋点
tracker.reportDownload(this.data.pageTitle, this.data.currentMode);
checkAndSaveImage(this.canvas);
},
getShareOptions(this: PageCanvasInstance): ShareOptions {
const route = this.route || '';
const { functionId, currentMode } = this.data;
const currentModeQuery = currentMode ? `&mode=${currentMode}` : '';
const path = `${route}?id=${functionId}${currentModeQuery}`;
console.log('getShareOptions path', path);
return {
...shareConfig,
path,
};
},
/**
* 分享小程序
*/
onShareAppMessage(this: PageCanvasInstance) {
// 上报分享埋点
tracker.reportShare(this.data.pageTitle);
return this.getShareOptions();
},
/**
* 分享到朋友圈
*/
onShareTimeline(this: PageCanvasInstance) {
console.log('onShareTimeline');
// 上报分享埋点
tracker.reportShare(this.data.pageTitle);
return this.getShareOptions();
},
/**
* 关闭分享引导弹窗
*/
onCloseShareDialog(this: PageCanvasInstance) {
this.setData({ showShareDialog: false });
},
/**
* 分享成功回调
*/
onShareSuccess(this: PageCanvasInstance) {
this.setData({ showShareDialog: false });
if (this.canvas) {
// 上报下载埋点(分享成功后下载)
tracker.reportDownload(this.data.pageTitle);
checkAndSaveImage(this.canvas);
}
},
/**
* 初始化页面信息
*
* 支持两种调用方式:
* 1. initPageInfo(functionId, defaultTitle) - 如果有 pageInfoLookup,会尝试查找;否则使用 defaultTitle
* 2. initPageInfo({ title, desc, functionId }) - 直接提供页面信息
*/
initPageInfo(
this: PageCanvasInstance,
functionIdOrOptions:
| string
| { title: string; desc?: string; functionId: string },
defaultTitle?: string,
) {
let functionId: string;
let title: string;
let desc: string = '';
// 判断调用方式
if (typeof functionIdOrOptions === 'string') {
// 方式1: initPageInfo(functionId, defaultTitle)
functionId = functionIdOrOptions;
title = defaultTitle || '';
// 如果有 pageInfoLookup,尝试查找
if (pageInfoLookup) {
const pageInfo = pageInfoLookup(functionId);
if (pageInfo) {
title = pageInfo.title;
desc = pageInfo.desc || '';
}
}
} else {
// 方式2: initPageInfo({ title, desc, functionId })
functionId = functionIdOrOptions.functionId;
title = functionIdOrOptions.title;
desc = functionIdOrOptions.desc || '';
}
this.setData({
pageTitle: title,
subTitle: desc,
functionId,
});
wx.setNavigationBarTitle({ title });
},
};
}
/**
* 应用页面公共方法的辅助函数
* 自动混入公共方法,简化页面代码
* @param pageOptions 页面选项
* @param config 公共方法配置
* @returns 合并后的页面选项
*/
export function applyPageMixin(
pageOptions: any,
config: PageCommonMethodsConfig = {},
) {
const commonMethods = getPageCommonMethods(config);
// 提取 pageOptions 中的 data(如果有)
const pageData = pageOptions.data || {};
// 合并页面选项和公共方法
// 注意:pageOptions 放在后面,这样页面可以覆盖公共方法
const mergedOptions: any = {
...commonMethods,
...pageOptions,
// 处理 data 的合并(需要特殊处理,避免覆盖)
data: {
...pageData,
},
};
return mergedOptions;
}
/**
* 创建页面的便捷函数
* 自动应用公共方法并注册为页面
* @param pageOptions 页面选项
* @param config 公共方法配置
*/
export function createPage(
pageOptions: any,
config: PageCommonMethodsConfig = {},
) {
Page(applyPageMixin(pageOptions, config));
}