feat: 打印预览组件化
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -5,6 +5,13 @@
|
||||
"css_prefix_text": "icon-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "47422029",
|
||||
"name": "refresh",
|
||||
"font_class": "refresh",
|
||||
"unicode": "e62c",
|
||||
"unicode_decimal": 58924
|
||||
},
|
||||
{
|
||||
"icon_id": "47400915",
|
||||
"name": "keyboard-arrow-up",
|
||||
@@ -285,13 +292,6 @@
|
||||
"unicode": "e6ea",
|
||||
"unicode_decimal": 59114
|
||||
},
|
||||
{
|
||||
"icon_id": "12578929",
|
||||
"name": "refresh2",
|
||||
"font_class": "refresh2",
|
||||
"unicode": "e6e3",
|
||||
"unicode_decimal": 59107
|
||||
},
|
||||
{
|
||||
"icon_id": "18441414",
|
||||
"name": "sun",
|
||||
@@ -301,8 +301,8 @@
|
||||
},
|
||||
{
|
||||
"icon_id": "21937756",
|
||||
"name": "refresh",
|
||||
"font_class": "refresh",
|
||||
"name": "refresh-two",
|
||||
"font_class": "refresh-two",
|
||||
"unicode": "e6c2",
|
||||
"unicode_decimal": 59074
|
||||
},
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -168,6 +168,47 @@ export function getPageCommonMethods(config: PageCommonMethodsConfig = {}) {
|
||||
.exec();
|
||||
},
|
||||
|
||||
/**
|
||||
* 从 preview-card 组件的 canvas-ready 事件初始化 Canvas
|
||||
* 用于已将 canvas 节点下沉到 preview-card 组件的页面
|
||||
*/
|
||||
initCanvasFromComponent(
|
||||
this: PageCanvasInstance,
|
||||
detail: {
|
||||
canvas: Canvas;
|
||||
ctx: RenderingContext;
|
||||
width: number;
|
||||
height: number;
|
||||
},
|
||||
options: InitCanvasOptions,
|
||||
) {
|
||||
this.canvas = detail.canvas;
|
||||
this.ctx = detail.ctx;
|
||||
this.boxWidth = detail.width;
|
||||
this.boxHeight = detail.height;
|
||||
|
||||
this.setData({
|
||||
boxWidth: detail.width,
|
||||
boxHeight: detail.height,
|
||||
});
|
||||
|
||||
const drawServiceOptions = {
|
||||
title: this.data.pageTitle,
|
||||
subTitle: this.data.subTitle || '',
|
||||
...options.drawServiceOptions,
|
||||
};
|
||||
|
||||
this.drawService = options.createDrawService(
|
||||
detail.canvas,
|
||||
detail.ctx,
|
||||
drawServiceOptions,
|
||||
);
|
||||
|
||||
if (options.onCanvasReady) {
|
||||
options.onCanvasReady.call(this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 导出打印
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"toy-icon": "../../toy/icon/icon"
|
||||
},
|
||||
"styleIsolation": "apply-shared",
|
||||
"addGlobalClass": true
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
@import '../../style/theme.less';
|
||||
|
||||
.pc-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pc-card {
|
||||
position: relative;
|
||||
background: @bg-white;
|
||||
border-radius: @radius-xl;
|
||||
box-shadow: @shadow;
|
||||
padding: 40rpx;
|
||||
border: @border;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.pc-card--with-fab {
|
||||
padding-bottom: 56rpx;
|
||||
}
|
||||
|
||||
.pc-kicker {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: @fs-section-head-title;
|
||||
font-weight: bold;
|
||||
color: @text-secondary;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.pc-canvas-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 400rpx;
|
||||
background: @bg-gray;
|
||||
border-radius: @radius-sm;
|
||||
border: 2rpx dashed rgba(50, 46, 37, 0.12);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pc-canvas {
|
||||
max-width: 100%;
|
||||
border-radius: @radius-sm;
|
||||
box-shadow: @shadow;
|
||||
}
|
||||
|
||||
/* 底部角上的圆形操作按钮 */
|
||||
@pc-fab-size: 88rpx;
|
||||
|
||||
@keyframes pc-fab-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.pc-fab {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: @pc-fab-size;
|
||||
height: @pc-fab-size;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 6rpx 18rpx rgba(50, 46, 37, 0.12);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pc-fab--hover {
|
||||
opacity: 0.88;
|
||||
transform: scale(0.96);
|
||||
}
|
||||
|
||||
.pc-fab--refresh {
|
||||
left: 12rpx;
|
||||
bottom: 12rpx;
|
||||
background: #9add4c;
|
||||
}
|
||||
|
||||
.pc-fab--favorite {
|
||||
right: 12rpx;
|
||||
bottom: 12rpx;
|
||||
background: #f2eee4;
|
||||
}
|
||||
|
||||
.pc-fab__toy {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.pc-fab__icon-wrap--a .pc-fab__toy,
|
||||
.pc-fab__icon-wrap--b .pc-fab__toy {
|
||||
animation: pc-fab-spin 0.55s linear 1;
|
||||
}
|
||||
|
||||
.pc-fab__icon-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
import { PAPER_SIZE, A4_EXPORT_SIZE_150DPI } from '../../constants/colors';
|
||||
|
||||
Component({
|
||||
options: {
|
||||
styleIsolation: 'apply-shared',
|
||||
addGlobalClass: true,
|
||||
},
|
||||
|
||||
properties: {
|
||||
kicker: {
|
||||
type: String,
|
||||
value: '打印预览',
|
||||
},
|
||||
showRefresh: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
showFavorite: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
favorited: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
favoritedIconColor: {
|
||||
type: String,
|
||||
value: '#E53935',
|
||||
},
|
||||
favoriteIdleIconColor: {
|
||||
type: String,
|
||||
value: '#605b50',
|
||||
},
|
||||
},
|
||||
|
||||
data: {
|
||||
boxWidth: 0,
|
||||
boxHeight: 0,
|
||||
refreshIconAnimClass: '',
|
||||
withFab: false,
|
||||
},
|
||||
|
||||
observers: {
|
||||
'showRefresh, showFavorite'(
|
||||
showRefresh: boolean,
|
||||
showFavorite: boolean,
|
||||
) {
|
||||
this.setData({ withFab: !!showRefresh || !!showFavorite });
|
||||
},
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
ready() {
|
||||
this.initCanvas();
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
initCanvas() {
|
||||
const query = this.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.setData({ boxWidth, boxHeight });
|
||||
|
||||
this.createSelectorQuery()
|
||||
.select('#canvasContent')
|
||||
.fields({ node: true, size: true })
|
||||
.exec((res) => {
|
||||
if (!res[0]) 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);
|
||||
|
||||
this._canvas = canvas;
|
||||
|
||||
this.triggerEvent('canvas-ready', {
|
||||
canvas,
|
||||
ctx,
|
||||
width: boxWidth,
|
||||
height: boxHeight,
|
||||
});
|
||||
});
|
||||
})
|
||||
.exec();
|
||||
},
|
||||
|
||||
onRefreshTap() {
|
||||
this.triggerEvent('refresh', {});
|
||||
if ((this as any)._refreshSpinTimer) {
|
||||
clearTimeout((this as any)._refreshSpinTimer);
|
||||
}
|
||||
this.setData({ refreshIconAnimClass: '' });
|
||||
const n = ((this as any)._refreshTapCount || 0) + 1;
|
||||
(this as any)._refreshTapCount = n;
|
||||
const sub = n % 2 === 1 ? 'a' : 'b';
|
||||
(this as any)._refreshSpinTimer = setTimeout(() => {
|
||||
(this as any)._refreshSpinTimer = null;
|
||||
this.setData({
|
||||
refreshIconAnimClass: `pc-fab__icon-wrap--${sub}`,
|
||||
});
|
||||
}, 20);
|
||||
},
|
||||
|
||||
onFavoriteTap() {
|
||||
this.triggerEvent('favorite', {});
|
||||
},
|
||||
|
||||
getCanvas(): WechatMiniprogram.Canvas | null {
|
||||
return this._canvas || null;
|
||||
},
|
||||
|
||||
exportToTempFile(
|
||||
options?: { quality?: number; fileType?: 'png' | 'jpg' },
|
||||
): Promise<string> {
|
||||
const canvas = this._canvas;
|
||||
if (!canvas) {
|
||||
return Promise.reject(new Error('Canvas not initialized'));
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.canvasToTempFilePath({
|
||||
canvas,
|
||||
fileType: options?.fileType || 'png',
|
||||
quality: options?.quality ?? 1,
|
||||
destWidth: A4_EXPORT_SIZE_150DPI.width,
|
||||
destHeight: A4_EXPORT_SIZE_150DPI.height,
|
||||
success: (res) => resolve(res.tempFilePath),
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
<view class="pc-wrap">
|
||||
<view class="pc-card {{withFab ? 'pc-card--with-fab' : ''}}">
|
||||
<text class="pc-kicker">{{kicker}}</text>
|
||||
<view id="canvasWrapper" class="pc-canvas-wrap">
|
||||
<canvas
|
||||
type="2d"
|
||||
id="canvasContent"
|
||||
class="pc-canvas"
|
||||
style="width:{{boxWidth}}px;height:{{boxHeight}}px" />
|
||||
</view>
|
||||
|
||||
<view
|
||||
wx:if="{{showRefresh}}"
|
||||
class="pc-fab pc-fab--refresh"
|
||||
hover-class="pc-fab--hover"
|
||||
hover-start-time="0"
|
||||
hover-stay-time="70"
|
||||
catchtap="onRefreshTap">
|
||||
<view
|
||||
class="pc-fab__icon-wrap {{refreshIconAnimClass}}">
|
||||
<toy-icon
|
||||
name="refresh"
|
||||
size="40rpx"
|
||||
color="#2d5016"
|
||||
custom-class="pc-fab__toy" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
wx:if="{{showFavorite}}"
|
||||
class="pc-fab pc-fab--favorite"
|
||||
hover-class="pc-fab--hover"
|
||||
hover-start-time="0"
|
||||
hover-stay-time="70"
|
||||
catchtap="onFavoriteTap">
|
||||
<toy-icon
|
||||
name="{{favorited ? 'heart' : 'heart-o'}}"
|
||||
size="40rpx"
|
||||
color="{{favorited ? favoritedIconColor : favoriteIdleIconColor}}"
|
||||
custom-class="pc-fab__toy" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -10,6 +10,7 @@
|
||||
"share-guide-popup": "../../components/share-guide-popup/share-guide-popup",
|
||||
"draw-ad": "../../components/draw-ad/draw-ad",
|
||||
"preview-footer-actions": "../../components3.0/preview-footer-actions/preview-footer-actions",
|
||||
"toy-icon": "../../toy/icon/icon"
|
||||
"toy-icon": "../../toy/icon/icon",
|
||||
"preview-card": "../../components3.0/preview-card/preview-card"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,53 +19,6 @@ page {
|
||||
gap: 64rpx;
|
||||
}
|
||||
|
||||
/* ===== 预览卡 (rounded-xl shadow-sm p-8 border) ===== */
|
||||
.lt-preview-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.lt-preview-card {
|
||||
background: @bg-white;
|
||||
border-radius: @radius-xl;
|
||||
box-shadow: @shadow;
|
||||
padding: 40rpx;
|
||||
border: @border;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.lt-preview-kicker {
|
||||
display: block;
|
||||
text-align: center;
|
||||
/* text-xs = 12px → 24rpx */
|
||||
font-size: @fs-section-head-title;
|
||||
font-weight: bold;
|
||||
color: @text-secondary;
|
||||
// 设置字母间距,使文本字符之间有更宽的间隔,提升可读性和美观性
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.lt-canvas-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 400rpx;
|
||||
background: @bg-gray;
|
||||
border-radius: @radius-sm;
|
||||
border: 2rpx dashed rgba(50, 46, 37, 0.12);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.lt-canvas {
|
||||
max-width: 100%;
|
||||
border-radius: @radius-sm;
|
||||
box-shadow: @shadow;
|
||||
}
|
||||
|
||||
/* ===== 独立 Section 区块(参考 UI 稿 space-y-4) ===== */
|
||||
.lt-section {
|
||||
display: flex;
|
||||
|
||||
@@ -92,6 +92,7 @@ type PageData = CanvasDataState & {
|
||||
selectedTripleGroupIdx: number;
|
||||
letterGrid: string[];
|
||||
modeOptions: ReadonlyArray<{ id: string; label: string; desc: string }>;
|
||||
isPreviewFavorite: boolean;
|
||||
};
|
||||
|
||||
createPage(
|
||||
@@ -121,6 +122,7 @@ createPage(
|
||||
selectedTripleGroupIdx: 0,
|
||||
letterGrid: LETTERS_PAIRS,
|
||||
modeOptions: [...MODES],
|
||||
isPreviewFavorite: false,
|
||||
} as unknown as PageData,
|
||||
|
||||
/** 页面加载:从路由参数获取 worksheetId、letter、case、font 并应用,同时预加载字体 */
|
||||
@@ -170,9 +172,9 @@ createPage(
|
||||
});
|
||||
},
|
||||
|
||||
/** 页面就绪:初始化 Canvas → 首次绘制(标题行前缀使用系统 emoji,无需 loadFontFace) */
|
||||
onReady() {
|
||||
this.initCanvas({
|
||||
/** Canvas 组件就绪回调:创建 DrawService → 首次绘制 */
|
||||
onCanvasReady(e: WechatMiniprogram.CustomEvent) {
|
||||
this.initCanvasFromComponent(e.detail, {
|
||||
createDrawService: (
|
||||
canvas: Canvas,
|
||||
ctx: RenderingContext,
|
||||
@@ -274,6 +276,15 @@ createPage(
|
||||
this.drawCanvas();
|
||||
},
|
||||
|
||||
onPreviewFavorite() {
|
||||
const next = !this.data.isPreviewFavorite;
|
||||
this.setData({ isPreviewFavorite: next });
|
||||
wx.showToast({
|
||||
title: next ? '收藏成功' : '已取消收藏',
|
||||
icon: 'none',
|
||||
});
|
||||
},
|
||||
|
||||
/** 用户在三字母分组选择器中选择了一组 */
|
||||
onSelectTripleGroup(e: WechatMiniprogram.TouchEvent) {
|
||||
const idx = Number(e.currentTarget.dataset.idx);
|
||||
|
||||
@@ -2,18 +2,13 @@
|
||||
|
||||
<view class="lt-page">
|
||||
<view class="lt-main">
|
||||
<view class="lt-preview-wrap">
|
||||
<view class="lt-preview-card">
|
||||
<text class="lt-preview-kicker">打印预览</text>
|
||||
<view id="canvasWrapper" class="lt-canvas-wrap">
|
||||
<canvas
|
||||
type="2d"
|
||||
id="canvasContent"
|
||||
class="lt-canvas"
|
||||
style="width:{{boxWidth}}px;height:{{boxHeight}}px" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<preview-card
|
||||
id="previewCard"
|
||||
showRefresh="{{false}}"
|
||||
showFavorite="{{true}}"
|
||||
favorited="{{isPreviewFavorite}}"
|
||||
bind:canvas-ready="onCanvasReady"
|
||||
bind:favorite="onPreviewFavorite" />
|
||||
|
||||
<!-- 练习类型(2列卡片网格) -->
|
||||
<view class="lt-section">
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"share-guide-popup": "../../components/share-guide-popup/share-guide-popup",
|
||||
"draw-ad": "../../components/draw-ad/draw-ad",
|
||||
"preview-footer-actions": "../../components3.0/preview-footer-actions/preview-footer-actions",
|
||||
"toy-icon": "../../toy/icon/icon"
|
||||
"toy-icon": "../../toy/icon/icon",
|
||||
"preview-card": "../../components3.0/preview-card/preview-card"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,51 +18,6 @@ page {
|
||||
gap: 64rpx;
|
||||
}
|
||||
|
||||
/* ===== 预览卡 ===== */
|
||||
.fd-preview-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fd-preview-card {
|
||||
background: @bg-white;
|
||||
border-radius: @radius-xl;
|
||||
box-shadow: @shadow;
|
||||
padding: 40rpx;
|
||||
border: @border;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.fd-preview-kicker {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: @fs-section-head-title;
|
||||
font-weight: bold;
|
||||
color: @text-secondary;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.fd-canvas-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 400rpx;
|
||||
background: @bg-gray;
|
||||
border-radius: @radius-sm;
|
||||
border: 2rpx dashed rgba(50, 46, 37, 0.12);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fd-canvas {
|
||||
max-width: 100%;
|
||||
border-radius: @radius-sm;
|
||||
box-shadow: @shadow;
|
||||
}
|
||||
|
||||
/* ===== 区块 ===== */
|
||||
.fd-section {
|
||||
display: flex;
|
||||
|
||||
@@ -35,6 +35,7 @@ createFocusPage({
|
||||
actionsTitle: '选择模式',
|
||||
currentActions: [] as FocusTypeAction[],
|
||||
currentMode: '',
|
||||
isPreviewFavorite: false,
|
||||
},
|
||||
|
||||
onLoad(options: { id?: string; mode?: string }) {
|
||||
@@ -65,13 +66,13 @@ createFocusPage({
|
||||
this.initPageInfo(routeId, title);
|
||||
},
|
||||
|
||||
onReady() {
|
||||
onCanvasReady(e: WechatMiniprogram.CustomEvent) {
|
||||
if (!this.currentTypeConfig) return;
|
||||
|
||||
const typeConfig = this.currentTypeConfig;
|
||||
const mode = this.data.currentMode;
|
||||
|
||||
this.initCanvas({
|
||||
this.initCanvasFromComponent(e.detail, {
|
||||
createDrawService: (
|
||||
canvas: Canvas,
|
||||
ctx: RenderingContext,
|
||||
@@ -181,4 +182,18 @@ createFocusPage({
|
||||
);
|
||||
this.drawCanvas();
|
||||
},
|
||||
|
||||
/** 打印预览角标:换一批,与「随机生成」相同逻辑 */
|
||||
onPreviewRefresh() {
|
||||
this.onRandom();
|
||||
},
|
||||
|
||||
onPreviewFavorite() {
|
||||
const next = !this.data.isPreviewFavorite;
|
||||
this.setData({ isPreviewFavorite: next });
|
||||
wx.showToast({
|
||||
title: next ? '收藏成功' : '已取消收藏',
|
||||
icon: 'none',
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3,15 +3,29 @@
|
||||
<view class="fd-page">
|
||||
<view class="fd-main">
|
||||
<!-- 打印预览卡 -->
|
||||
<view class="fd-preview-wrap">
|
||||
<view class="fd-preview-card">
|
||||
<text class="fd-preview-kicker">打印预览</text>
|
||||
<view id="canvasWrapper" class="fd-canvas-wrap">
|
||||
<canvas
|
||||
type="2d"
|
||||
id="canvasContent"
|
||||
class="fd-canvas"
|
||||
style="width:{{boxWidth}}px;height:{{boxHeight}}px" />
|
||||
<preview-card
|
||||
id="previewCard"
|
||||
showRefresh="{{true}}"
|
||||
showFavorite="{{true}}"
|
||||
favorited="{{isPreviewFavorite}}"
|
||||
bind:canvas-ready="onCanvasReady"
|
||||
bind:refresh="onPreviewRefresh"
|
||||
bind:favorite="onPreviewFavorite" />
|
||||
|
||||
<!-- 子选项(当前类型有模式切换时显示) -->
|
||||
<view wx:if="{{showActions}}" class="fd-section">
|
||||
<text class="fd-section-title">{{actionsTitle}}</text>
|
||||
<view class="fd-chip-row">
|
||||
<view
|
||||
wx:for="{{currentActions}}"
|
||||
wx:key="value"
|
||||
class="fd-chip {{currentMode === item.value ? 'fd-chip--active' : ''}}"
|
||||
data-value="{{item.value}}"
|
||||
hover-class="fd-chip--pressed"
|
||||
hover-start-time="0"
|
||||
hover-stay-time="70"
|
||||
bindtap="onSelectMode">
|
||||
{{item.label}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -35,25 +49,7 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 子选项(当前类型有模式切换时显示) -->
|
||||
<view wx:if="{{showActions}}" class="fd-section">
|
||||
<text class="fd-section-title">{{actionsTitle}}</text>
|
||||
<view class="fd-chip-row">
|
||||
<view
|
||||
wx:for="{{currentActions}}"
|
||||
wx:key="value"
|
||||
class="fd-chip {{currentMode === item.value ? 'fd-chip--active' : ''}}"
|
||||
data-value="{{item.value}}"
|
||||
hover-class="fd-chip--pressed"
|
||||
hover-start-time="0"
|
||||
hover-stay-time="70"
|
||||
bindtap="onSelectMode">
|
||||
{{item.label}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 随机生成按钮 -->
|
||||
<!-- 随机生成按钮
|
||||
<view
|
||||
class="fd-shuffle-btn"
|
||||
hover-class="fd-shuffle-btn--hover"
|
||||
@@ -66,7 +62,7 @@
|
||||
color="#605b50"
|
||||
custom-class="fd-shuffle-btn__icon" />
|
||||
<text class="fd-shuffle-btn__text">随机生成</text>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 广告位 -->
|
||||
<draw-ad type="focusDraw"></draw-ad>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"share-guide-popup": "../../components/share-guide-popup/share-guide-popup",
|
||||
"draw-ad": "../../components/draw-ad/draw-ad",
|
||||
"preview-footer-actions": "../../components3.0/preview-footer-actions/preview-footer-actions",
|
||||
"toy-icon": "../../toy/icon/icon"
|
||||
"toy-icon": "../../toy/icon/icon",
|
||||
"preview-card": "../../components3.0/preview-card/preview-card"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,51 +18,6 @@ page {
|
||||
gap: 64rpx;
|
||||
}
|
||||
|
||||
/* ===== 预览卡 ===== */
|
||||
.md-preview-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.md-preview-card {
|
||||
background: @bg-white;
|
||||
border-radius: @radius-xl;
|
||||
box-shadow: @shadow;
|
||||
padding: 40rpx;
|
||||
border: @border;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.md-preview-kicker {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: @fs-section-head-title;
|
||||
font-weight: bold;
|
||||
color: @text-secondary;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.md-canvas-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 400rpx;
|
||||
background: @bg-gray;
|
||||
border-radius: @radius-sm;
|
||||
border: 2rpx dashed rgba(50, 46, 37, 0.12);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.md-canvas {
|
||||
max-width: 100%;
|
||||
border-radius: @radius-sm;
|
||||
box-shadow: @shadow;
|
||||
}
|
||||
|
||||
/* ===== 区块 ===== */
|
||||
.md-section {
|
||||
display: flex;
|
||||
|
||||
@@ -39,6 +39,7 @@ createMathPage({
|
||||
showNumberGrid: false,
|
||||
numberList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||
selectedNumber: 0,
|
||||
isPreviewFavorite: false,
|
||||
},
|
||||
|
||||
onLoad(options: { id?: string; mode?: string }) {
|
||||
@@ -74,13 +75,13 @@ createMathPage({
|
||||
this.initPageInfo(routeId, title);
|
||||
},
|
||||
|
||||
onReady() {
|
||||
onCanvasReady(e: WechatMiniprogram.CustomEvent) {
|
||||
if (!this.currentTypeConfig) return;
|
||||
|
||||
const typeConfig = this.currentTypeConfig;
|
||||
const mode = this.data.currentMode;
|
||||
|
||||
this.initCanvas({
|
||||
this.initCanvasFromComponent(e.detail, {
|
||||
createDrawService: (
|
||||
canvas: Canvas,
|
||||
ctx: RenderingContext,
|
||||
@@ -246,4 +247,17 @@ createMathPage({
|
||||
);
|
||||
this.drawCanvas();
|
||||
},
|
||||
|
||||
onPreviewRefresh() {
|
||||
this.onRandom();
|
||||
},
|
||||
|
||||
onPreviewFavorite() {
|
||||
const next = !this.data.isPreviewFavorite;
|
||||
this.setData({ isPreviewFavorite: next });
|
||||
wx.showToast({
|
||||
title: next ? '收藏成功' : '已取消收藏',
|
||||
icon: 'none',
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3,42 +3,20 @@
|
||||
<view class="md-page">
|
||||
<view class="md-main">
|
||||
<!-- 打印预览卡 -->
|
||||
<view class="md-preview-wrap">
|
||||
<view class="md-preview-card">
|
||||
<text class="md-preview-kicker">打印预览</text>
|
||||
<view id="canvasWrapper" class="md-canvas-wrap">
|
||||
<canvas
|
||||
type="2d"
|
||||
id="canvasContent"
|
||||
class="md-canvas"
|
||||
style="width:{{boxWidth}}px;height:{{boxHeight}}px" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 练习类型选择(2列卡片网格) -->
|
||||
<view class="md-section">
|
||||
<text class="md-section-title">练习类型</text>
|
||||
<view class="md-type-grid">
|
||||
<view
|
||||
wx:for="{{typeList}}"
|
||||
wx:key="id"
|
||||
class="md-type-card {{selectedTypeId === item.id ? 'md-type-card--active' : ''}}"
|
||||
data-id="{{item.id}}"
|
||||
hover-class="md-type-card--pressed"
|
||||
hover-start-time="0"
|
||||
hover-stay-time="70"
|
||||
bindtap="onSelectType">
|
||||
<text class="md-type-card__icon">{{item.icon}}</text>
|
||||
<text class="md-type-card__label">{{item.title}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<preview-card
|
||||
id="previewCard"
|
||||
showRefresh="{{true}}"
|
||||
showFavorite="{{true}}"
|
||||
favorited="{{isPreviewFavorite}}"
|
||||
bind:canvas-ready="onCanvasReady"
|
||||
bind:refresh="onPreviewRefresh"
|
||||
bind:favorite="onPreviewFavorite" />
|
||||
|
||||
<!-- 子选项(当前类型有模式切换时显示) -->
|
||||
<view wx:if="{{showActions}}" class="md-section">
|
||||
<text class="md-section-title">{{actionsTitle}}</text>
|
||||
<view class="md-chip-row {{currentActions.length > 3 ? 'md-chip-row--wrap' : ''}}">
|
||||
<view
|
||||
class="md-chip-row {{currentActions.length > 3 ? 'md-chip-row--wrap' : ''}}">
|
||||
<view
|
||||
wx:for="{{currentActions}}"
|
||||
wx:key="value"
|
||||
@@ -71,7 +49,26 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 随机生成按钮 -->
|
||||
<!-- 练习类型选择(2列卡片网格) -->
|
||||
<view class="md-section">
|
||||
<text class="md-section-title">练习类型</text>
|
||||
<view class="md-type-grid">
|
||||
<view
|
||||
wx:for="{{typeList}}"
|
||||
wx:key="id"
|
||||
class="md-type-card {{selectedTypeId === item.id ? 'md-type-card--active' : ''}}"
|
||||
data-id="{{item.id}}"
|
||||
hover-class="md-type-card--pressed"
|
||||
hover-start-time="0"
|
||||
hover-stay-time="70"
|
||||
bindtap="onSelectType">
|
||||
<text class="md-type-card__icon">{{item.icon}}</text>
|
||||
<text class="md-type-card__label">{{item.title}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 随机生成按钮
|
||||
<view
|
||||
class="md-shuffle-btn"
|
||||
hover-class="md-shuffle-btn--hover"
|
||||
@@ -84,7 +81,7 @@
|
||||
color="#605b50"
|
||||
custom-class="md-shuffle-btn__icon" />
|
||||
<text class="md-shuffle-btn__text">随机生成</text>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 广告位 -->
|
||||
<draw-ad type="mathDraw"></draw-ad>
|
||||
|
||||
Reference in New Issue
Block a user