feat:生产初版页面

This commit is contained in:
R524809
2026-03-26 17:33:04 +08:00
parent 3aaf340781
commit dc5e057cb3
63 changed files with 2940 additions and 543 deletions
+92
View File
@@ -0,0 +1,92 @@
/**
* Canvas 平台适配器
* 封装微信小程序 Canvas API,为未来 Web 平台迁移做准备
*/
export interface CanvasInitResult {
canvas: WechatMiniprogram.Canvas;
ctx: CanvasRenderingContext2D;
width: number;
height: number;
}
/**
* 初始化 Canvas 节点
* @param selector Canvas 选择器 (如 '#canvasContent')
* @param wrapperSelector 容器选择器 (如 '#canvasWrapper')
* @param aspectRatio 宽高比 (width / height)
*/
export function initCanvas(
selector: string,
wrapperSelector: string,
aspectRatio: number,
): Promise<CanvasInitResult> {
return new Promise((resolve, reject) => {
const query = wx.createSelectorQuery();
query
.select(wrapperSelector)
.boundingClientRect((rect) => {
if (!rect) {
reject(new Error('Canvas wrapper not found'));
return;
}
const boxWidth = rect.width;
const boxHeight = boxWidth / aspectRatio;
wx.createSelectorQuery()
.select(selector)
.fields({ node: true, size: true })
.exec((res) => {
if (!res[0]) {
reject(new Error('Canvas node not found'));
return;
}
const canvas = res[0].node;
const ctx = canvas.getContext('2d');
const dpr = wx.getSystemInfoSync().pixelRatio;
canvas.width = boxWidth * dpr;
canvas.height = boxHeight * dpr;
ctx.scale(dpr, dpr);
resolve({ canvas, ctx, width: boxWidth, height: boxHeight });
});
})
.exec();
});
}
/**
* Canvas 导出为临时文件路径
*/
export function canvasToTempFilePath(
canvas: WechatMiniprogram.Canvas,
options?: { quality?: number; fileType?: 'png' | 'jpg' },
): Promise<string> {
return new Promise((resolve, reject) => {
wx.canvasToTempFilePath({
canvas,
fileType: options?.fileType || 'png',
quality: options?.quality || 1,
success: (res) => resolve(res.tempFilePath),
fail: reject,
});
});
}
/**
* 加载图片到 Canvas
*/
export function loadImage(
canvas: WechatMiniprogram.Canvas,
src: string,
): Promise<WechatMiniprogram.Image> {
return new Promise((resolve, reject) => {
const img = canvas.createImage();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = src;
});
}
+70
View File
@@ -0,0 +1,70 @@
/**
* 云服务平台适配器
* 封装微信云开发 API
*/
export interface CloudResult {
code?: string | number;
message?: string;
info?: string;
data?: any;
[key: string]: any;
}
/**
* 调用云函数
*/
export async function callCloud(
action: string,
options?: Record<string, any>,
): Promise<CloudResult> {
try {
const name = 'doodle';
const { errMsg, result } = await wx.cloud.callFunction({
name,
data: {
action,
...options,
},
});
if (!/ok/.test(errMsg)) {
wx.showToast({
title: '服务器错误',
icon: 'none',
duration: 2000,
});
return {
code: '500',
info: '服务器繁忙',
message: errMsg,
};
}
return result as CloudResult;
} catch (e: any) {
return { code: '500', info: e.message || '服务器繁忙' };
}
}
/**
* 查询云数据库集合
*/
export async function queryCollection(
collection: string,
where?: Record<string, any>,
limit: number = 20,
orderBy?: { field: string; order: 'asc' | 'desc' },
): Promise<any[]> {
try {
const db = wx.cloud.database();
let query = db.collection(collection).where(where || {}).limit(limit);
if (orderBy) {
query = query.orderBy(orderBy.field, orderBy.order);
}
const { data } = await query.get();
return data;
} catch (e) {
console.error('queryCollection failed:', collection, e);
return [];
}
}
+49
View File
@@ -0,0 +1,49 @@
/**
* 图片平台适配器
* 封装微信小程序图片加载和保存 API
*/
/**
* 保存图片到相册
*/
export function saveImageToAlbum(filePath: string): Promise<void> {
return new Promise((resolve, reject) => {
wx.saveImageToPhotosAlbum({
filePath,
success: () => resolve(),
fail: (err) => {
if (
err.errMsg.includes('auth deny') ||
err.errMsg.includes('authorize')
) {
wx.showModal({
title: '提示',
content: '需要授权保存图片到相册',
confirmText: '去设置',
success: (res) => {
if (res.confirm) {
wx.openSetting();
}
},
});
}
reject(err);
},
});
});
}
/**
* 获取图片信息
*/
export function getImageInfo(
src: string,
): Promise<WechatMiniprogram.GetImageInfoSuccessCallbackResult> {
return new Promise((resolve, reject) => {
wx.getImageInfo({
src,
success: resolve,
fail: reject,
});
});
}
+29
View File
@@ -0,0 +1,29 @@
/**
* 存储平台适配器
* 封装微信小程序 Storage API
*/
export function getStorage<T>(key: string, defaultValue?: T): T | undefined {
try {
const value = wx.getStorageSync(key);
return value !== '' ? value : defaultValue;
} catch {
return defaultValue;
}
}
export function setStorage(key: string, value: any): void {
try {
wx.setStorageSync(key, value);
} catch (e) {
console.error('setStorage failed:', key, e);
}
}
export function removeStorage(key: string): void {
try {
wx.removeStorageSync(key);
} catch (e) {
console.error('removeStorage failed:', key, e);
}
}