feat: 完成文字涂色卡功能

This commit is contained in:
2025-07-01 11:27:50 +08:00
parent 654afced6f
commit 6d38a17652
21 changed files with 267 additions and 103 deletions
+5 -2
View File
@@ -10,7 +10,6 @@ cloud.init({
exports.main = async (event, context) => { exports.main = async (event, context) => {
try { try {
console.log('main event.action:', event.action);
switch (event.action) { switch (event.action) {
case 'getOpenId': { case 'getOpenId': {
const res = await getOpenId(event, context); const res = await getOpenId(event, context);
@@ -26,7 +25,11 @@ exports.main = async (event, context) => {
return await createPDF(); return await createPDF();
} }
default: default:
return { code: 1, message: '请检查云函数名是否正确!', data: {} }; return {
code: 1,
message: '请检查云函数名是否正确!',
data: {},
};
} }
} catch (error) { } catch (error) {
console.error('Error in user cloud Function:', error); console.error('Error in user cloud Function:', error);
-19
View File
@@ -2,25 +2,6 @@
App<IAppOption>({ App<IAppOption>({
globalData: {}, globalData: {},
onLaunch() { onLaunch() {
// 展示本地存储能力
const logs = wx.getStorageSync('logs') || [];
logs.unshift(Date.now());
wx.setStorageSync('logs', logs);
wx.cloud.init({
// env 参数说明:
// env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源
// 此处请填入环境 ID, 环境 ID 可打开云控制台查看
// 如不填则使用默认环境(第一个创建的环境)
env: '',
traceUser: true,
});
// 登录
wx.login({
success: (res) => {
console.log(res.code);
// 发送 res.code 到后台换取 openId, sessionKey, unionId
},
});
}, },
}); });
@@ -147,8 +147,6 @@ class TextDrawService {
canvas.width = width; canvas.width = width;
canvas.height = height; canvas.height = height;
console.log('width---:', width);
console.log('height---:', height);
this.clear(); this.clear();
ctx.fillStyle = '#fff'; // 设置背景色为白色 ctx.fillStyle = '#fff'; // 设置背景色为白色
ctx.fillRect(0, 0, width, height); ctx.fillRect(0, 0, width, height);
@@ -210,8 +210,6 @@ class TextDrawService {
canvas.width = width; canvas.width = width;
canvas.height = height; canvas.height = height;
console.log('width---:', width);
console.log('height---:', height);
this.clear(); this.clear();
ctx.fillStyle = '#fff'; // 设置背景色为白色 ctx.fillStyle = '#fff'; // 设置背景色为白色
ctx.fillRect(0, 0, width, height); ctx.fillRect(0, 0, width, height);
@@ -13,7 +13,7 @@
height: 60rpx; height: 60rpx;
border-radius: 50%; border-radius: 50%;
background-color: #ff0000; background-color: #ff0000;
margin-left: 20rpx; margin-left: 24rpx;
border: 1rpx solid #141414; border: 1rpx solid #141414;
position: relative; position: relative;
@@ -34,7 +34,7 @@
} }
.word-box { .word-box {
margin: 0 4rpx 0 24rpx; margin: 0 16rpx 0 36rpx;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@@ -2,6 +2,7 @@
"component": true, "component": true,
"styleIsolation": "apply-shared", "styleIsolation": "apply-shared",
"usingComponents": { "usingComponents": {
"van-icon": "@vant/weapp/icon/index" "van-icon": "@vant/weapp/icon/index",
"toy-button": "/ui/button/button"
} }
} }
@@ -19,4 +19,22 @@
font-size: 28rpx; font-size: 28rpx;
line-height: 92rpx; line-height: 92rpx;
} }
.btn-word-add {
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
height: 72rpx;
padding: 0 24rpx;
background: rgba(255, 215, 25, 1);
border-radius: 20rpx;
font-size: 28rpx;
color: #fff;
margin-right: 10rpx;
&.active {
background-color: rgba(255, 215, 25, 0.8);
}
}
} }
@@ -18,20 +18,28 @@ Component({
/** /**
* 组件的初始数据 * 组件的初始数据
*/ */
data: {}, data: {
},
lifetimes: { lifetimes: {
attached() { attached() {
(this as any).words = ''; (this as any).value = '';
}, },
}, },
/** /**
* 组件的方法列表 * 组件的方法列表
*/ */
methods: { methods: {
onConfirm(e: WechatMiniprogram.Input) { onInput(e: WechatMiniprogram.Input) {
let { value } = e.detail; let { value } = e.detail;
// (this as any).words = value; value = value.replace(/\s/g, '');
value = value.replace(' ', ''); if (value.length > 0) {
(this as any).value = value;
}
},
onConfirm() {
const value = (this as any).value;
if (value.length > 0) { if (value.length > 0) {
this.triggerEvent('onConfirm', { value }); this.triggerEvent('onConfirm', { value });
} }
@@ -1,3 +1,5 @@
<wxs module="wxs" src="./word-input.wxs"></wxs>
<view <view
class="word-input-container" class="word-input-container"
style="{{width ? 'width:' + width + ';' : ''}}"> style="{{width ? 'width:' + width + ';' : ''}}">
@@ -10,5 +12,13 @@
class="word-input" class="word-input"
type="text" type="text"
placeholder="{{placeholder}}" placeholder="{{placeholder}}"
bindinput="onInput"
bindconfirm="onConfirm" /> bindconfirm="onConfirm" />
<view
class="btn-word-add"
bind:tap="onConfirm"
bind:touchstart="{{wxs.touchStart}}"
bind:touchend="{{wxs.touchEnd}}">
添加
</view>
</view> </view>
@@ -0,0 +1,23 @@
module.exports = {
touchStart: function (event, ownerInstance) {
var instance = event.instance;
var dataSet = instance.getDataset();
var disabled = dataSet.disabled;
var loading = dataSet.loading;
if (instance && !disabled && !loading) {
instance.addClass('active');
}
},
touchEnd: function (event, ownerInstance) {
var instance = event.instance;
var dataSet = instance.getDataset();
var disabled = dataSet.disabled;
var loading = dataSet.loading;
if (instance && !disabled && !loading) {
instance.removeClass('active');
}
},
};
@@ -86,6 +86,7 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin-bottom: 96rpx; margin-bottom: 96rpx;
padding: 0 28rpx;
} }
} }
@@ -27,7 +27,6 @@ Component({
}, },
lifetimes: { lifetimes: {
ready() { ready() {
console.log('selectedWords', this.data.selectedWords);
}, },
}, },
/** /**
@@ -38,6 +37,12 @@ Component({
this.triggerEvent('onClose'); this.triggerEvent('onClose');
}, },
onClear() {
this.setData({
selectedWords: [],
});
},
onChange() { onChange() {
this.triggerEvent('onChange', { selectedWords: this.data.selectedWords }); this.triggerEvent('onChange', { selectedWords: this.data.selectedWords });
}, },
@@ -4,13 +4,15 @@
show="{{ show }}" show="{{ show }}"
bind:close="onClose" bind:close="onClose"
round round
close-on-click-overlay="{{false}}" closeable="{{true}}"
close-on-click-overlay="{{true}}"
safe-area-inset-bottom="{{true}}" safe-area-inset-bottom="{{true}}"
position="bottom" position="bottom"
custom-style="height: 70%" custom-style="height: 70%"
custom-class="word-picker"> custom-class="word-picker">
<view class="word-picker-title">请选择文字</view> <view class="word-picker-title">请选择文字</view>
<van-tabs <van-tabs
wx:if="{{show}}"
id="tabs" id="tabs"
animated animated
color="#93d333" color="#93d333"
@@ -54,15 +56,16 @@
> >
</view> </view>
<view class="btn-area"> <view class="btn-area">
<toy-button <toy-button type="primary" bind:click="onChange" width="400rpx">
type="primary"
bind:click="onChange"
width="420rpx"
disabled="{{selectedWords.length <= 0}}">
(已选{{selectedWords.length}}个) 确定 (已选{{selectedWords.length}}个) 确定
</toy-button> </toy-button>
<toy-button type="white" bind:click="onClose" width="220rpx"> <toy-button
取消 type="white"
bind:click="onClear"
width="210rpx"
icon="clear"
icon-class-prefix="toy-icon">
清空
</toy-button> </toy-button>
</view> </view>
</van-popup> </van-popup>
+126 -22
View File
@@ -172,9 +172,16 @@ export const WORDS = [
}, },
{ {
categoryId: 3, categoryId: 3,
icon: '🎨',
categoryName: '颜色',
words: ['红', '蓝', '绿', '黄', '黑', '白', '紫', '橙', '粉', '棕', '灰'],
},
{
categoryId: 4,
icon: '', icon: '',
categoryName: '数字与颜色', categoryName: '数字',
words: [ words: [
'零',
'一', '一',
'二', '二',
'三', '三',
@@ -185,75 +192,172 @@ export const WORDS = [
'八', '八',
'九', '九',
'十', '十',
'', '0',
'', '1',
'绿', '2',
'', '3',
'', '4',
'', '5',
'', '6',
'', '7',
'', '8',
'', '9',
'', '10',
'11',
'12',
'13',
'14',
'15',
'16',
'17',
'18',
'19',
'20',
'21',
'22',
'23',
'24',
'25',
'26',
'27',
'28',
'29',
'30',
'31',
'32',
'33',
'34',
'35',
'36',
'37',
'38',
'39',
'40',
'41',
'42',
'43',
'44',
'45',
'46',
'47',
'48',
'49',
'50',
'51',
'52',
'53',
'54',
'55',
'56',
'57',
'58',
'59',
'60',
'61',
'62',
'63',
'64',
'65',
'66',
'67',
'68',
'69',
'70',
'71',
'72',
'73',
'74',
'75',
'76',
'77',
'78',
'79',
'80',
'81',
'82',
'83',
'84',
'85',
'86',
'87',
'88',
'89',
'90',
'91',
'92',
'93',
'94',
'95',
'96',
'97',
'98',
'99',
'100'
], ],
}, },
{ {
categoryId: 4, categoryId: 5,
icon: '🎨',
categoryName: '字母',
words: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
},
{
categoryId: 6,
icon: '☀️', icon: '☀️',
categoryName: '日字旁', categoryName: '日字旁',
words: ['日', '明', '早', '时', '晴', '春', '星', '晨'], words: ['日', '明', '早', '时', '晴', '春', '星', '晨'],
}, },
{ {
categoryId: 5, categoryId: 7,
icon: '💧', icon: '💧',
categoryName: '三点水', categoryName: '三点水',
words: ['水', '江', '河', '流', '沙', '洗', '海', '汗'], words: ['水', '江', '河', '流', '沙', '洗', '海', '汗'],
}, },
{ {
categoryId: 6, categoryId: 8,
icon: '🐦', icon: '🐦',
categoryName: '鸟字边', categoryName: '鸟字边',
words: ['鸟', '鸡', '鸭', '鹅', '鸣', '鸽', '鸦'], words: ['鸟', '鸡', '鸭', '鹅', '鸣', '鸽', '鸦'],
}, },
{ {
categoryId: 7, categoryId: 9,
icon: '🐾', icon: '🐾',
categoryName: '反犬旁', categoryName: '反犬旁',
words: ['狗', '猫', '猴', '狮', '狼', '猪'], words: ['狗', '猫', '猴', '狮', '狼', '猪'],
}, },
{ {
categoryId: 8, categoryId: 10,
icon: '🪱', icon: '🪱',
categoryName: '虫字旁', categoryName: '虫字旁',
words: ['虫', '蚁', '蝶', '蜻', '蛙', '蛇', '蜘', '蜂'], words: ['虫', '蚁', '蝶', '蜻', '蛙', '蛇', '蜘', '蜂'],
}, },
{ {
categoryId: 9, categoryId: 11,
icon: '🌧️', icon: '🌧️',
categoryName: '雨字头', categoryName: '雨字头',
words: ['雨', '雪', '雷', '露', '雾', '雹', '霜'], words: ['雨', '雪', '雷', '露', '雾', '雹', '霜'],
}, },
{ {
categoryId: 10, categoryId: 12,
icon: '🌲', icon: '🌲',
categoryName: '木字旁', categoryName: '木字旁',
words: ['木', '林', '树', '桃', '森', '松', '桥', '枝'], words: ['木', '林', '树', '桃', '森', '松', '桥', '枝'],
}, },
{ {
categoryId: 11, categoryId: 13,
icon: '👄', icon: '👄',
categoryName: '口字旁', categoryName: '口字旁',
words: ['口', '吃', '叫', '唱', '听', '吹', '叶', '和'], words: ['口', '吃', '叫', '唱', '听', '吹', '叶', '和'],
}, },
{ {
categoryId: 12, categoryId: 14,
icon: '🧍', icon: '🧍',
categoryName: '单人旁', categoryName: '单人旁',
words: ['你', '他', '们', '作', '休', '住', '伙', '伴'], words: ['你', '他', '们', '作', '休', '住', '伙', '伴'],
}, },
{ {
categoryId: 13, categoryId: 15,
icon: '❤️', icon: '❤️',
categoryName: '竖心旁', categoryName: '竖心旁',
words: ['心', '情', '快', '怕', '惊', '忙', '怀'], words: ['心', '情', '快', '怕', '惊', '忙', '怀'],
+12 -4
View File
@@ -24,7 +24,7 @@ page {
.wrapper-title { .wrapper-title {
font-size: 32rpx; font-size: 32rpx;
color: #141414; color: #141414;
margin-bottom: 30rpx; margin-bottom: 24rpx;
font-weight: bold; font-weight: bold;
text-align: center; text-align: center;
} }
@@ -34,13 +34,23 @@ page {
} }
.word-card-box { .word-card-box {
margin-top: 30rpx; padding: 34rpx 0;
.word-list-empty {
text-align: center;
font-size: 28rpx;
color: #999;
}
.word-card-list { .word-card-list {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
margin-bottom: 24rpx; margin-bottom: 24rpx;
&:last-child {
margin-bottom: 0;
}
} }
} }
@@ -66,9 +76,7 @@ page {
.canvas-wrapper { .canvas-wrapper {
margin-top: 20rpx;
width: 100%; width: 100%;
// border: 1rpx solid #141414;
background-color: #fff; background-color: #fff;
box-sizing: border-box; box-sizing: border-box;
} }
+3 -4
View File
@@ -49,7 +49,9 @@ Page({
this.boxHeight = boxHeight; this.boxHeight = boxHeight;
this.boxWidth = boxWidth; this.boxWidth = boxWidth;
setTimeout(() => {
this.initCanvas(boxWidth, boxHeight); this.initCanvas(boxWidth, boxHeight);
}, 500);
} }
}) })
.exec(); .exec();
@@ -176,7 +178,6 @@ Page({
/** 下载打印 */ /** 下载打印 */
exportToPrint() { exportToPrint() {
console.log('this.canvas:', this.canvas);
if (this.canvas && this.data.cardList.length > 0) { if (this.canvas && this.data.cardList.length > 0) {
wx.canvasToTempFilePath({ wx.canvasToTempFilePath({
canvas: this.canvas, canvas: this.canvas,
@@ -259,7 +260,7 @@ Page({
// 随机生成 // 随机生成
refreshCardList() { refreshCardList() {
// 获取前4个分类的所有文字 // 获取前4个分类的所有文字
const allWords = WORDS.slice(0, 4).reduce((acc, category) => { const allWords = WORDS.slice(0, 2).reduce((acc, category) => {
return acc.concat(category.words); return acc.concat(category.words);
}, [] as string[]); }, [] as string[]);
@@ -286,7 +287,6 @@ Page({
color: selectedColors[index], color: selectedColors[index],
word word
})); }));
console.log('cardList:', cardList);
this.drawCanvas(cardList); this.drawCanvas(cardList);
}, },
openSelectWordPopup() { openSelectWordPopup() {
@@ -303,7 +303,6 @@ Page({
onChangeWord(e: WechatMiniprogram.CustomEvent) { onChangeWord(e: WechatMiniprogram.CustomEvent) {
const selectedWords = e.detail.selectedWords as string[]; const selectedWords = e.detail.selectedWords as string[];
console.log('selectedWords:', selectedWords);
const colors = [...WATER_COLORS.basic12]; const colors = [...WATER_COLORS.basic12];
const cardList = selectedWords.map((word, index) => ({ const cardList = selectedWords.map((word, index) => ({
+10 -5
View File
@@ -12,6 +12,7 @@
</view> </view>
<view class="word-card-box"> <view class="word-card-box">
<block wx:if="{{cardList.length > 0}}">
<block <block
wx:for="{{cardList}}" wx:for="{{cardList}}"
wx:for-item="item" wx:for-item="item"
@@ -32,6 +33,12 @@
bind:onColorTap="onColorTap" /> bind:onColorTap="onColorTap" />
</view> </view>
</block> </block>
</block>
<block wx:if="{{!cardList.length}}">
<view class="word-list-empty">
请选择或输入文字,生成涂鸦卡
</view>
</block>
</view> </view>
<view class="operation-box"> <view class="operation-box">
<toy-button <toy-button
@@ -53,16 +60,14 @@
</toy-button> </toy-button>
</view> </view>
</view> </view>
<view <view id="previewWrapper" class="wrapper">
id="previewWrapper"
class="wrapper {{cardList.length > 0 ? '' : 'hidden'}}">
<text class="wrapper-title">预览打印效果</text> <text class="wrapper-title">预览打印效果</text>
<view id="canvasWrapper" class="canvas-wrapper"> <view id="canvasWrapper" class="canvas-wrapper">
<!-- <canvas <canvas
type="2d" type="2d"
id="canvasContent" id="canvasContent"
class="canvas-content" class="canvas-content"
style="width:{{boxWidth}}px;height:{{boxHeight}}px" /> --> style="width:{{boxWidth}}px;height:{{boxHeight}}px" />
</view> </view>
</view> </view>
<view class="empty"></view> <view class="empty"></view>
+2 -2
View File
@@ -70,10 +70,10 @@ class TextDrawService {
this.ctx = ctx; this.ctx = ctx;
this.paperSize = 'A4'; this.paperSize = 'A4';
this.options = { this.options = {
appName: '涂鸦丫', appName: '涂鸦丫小程序',
appHint: '涂色|识字|画画|打印', appHint: '涂色|识字|画画|打印',
title: '找一找 涂 色', title: '找一找 涂 色',
subTitle: '把相同的文字涂上相同的颜色', subTitle: '文字涂上相同的颜色',
...options, ...options,
}; };
this.currentX = 0; this.currentX = 0;
+2 -3
View File
@@ -15,7 +15,6 @@ wx-button:not([size=mini]) {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: @button-default-height; height: @button-default-height;
line-height: @button-default-height;
border-radius: @button-border-radius; border-radius: @button-border-radius;
font-size: @button-default-font-size; font-size: @button-default-font-size;
color: @button-default-color; color: @button-default-color;
@@ -64,8 +63,8 @@ wx-button:not([size=mini]) {
border: 2rpx solid rgba(223, 220, 220, 1); border: 2rpx solid rgba(223, 220, 220, 1);
&.disabled { &.disabled {
color: rgba(34, 36, 37, 0.7); color: rgba(34, 36, 37, 0.5);
background: rgba(255, 255, 255, 0.8); background: rgba(255, 255, 255, 0.7);
box-shadow: 0px 8rpx 0rpx rgba(223, 220, 220, 0.9); box-shadow: 0px 8rpx 0rpx rgba(223, 220, 220, 0.9);
} }
+1 -1
View File
@@ -85,7 +85,7 @@ Component({
attached() { attached() {
const { type, plain, disabled } = this.data; const { type, plain, disabled } = this.data;
if (type === 'white' && !plain) { if (type === 'white' && !plain) {
const iconColor = disabled ? 'rgba(34, 36, 37, 0.7)' : 'rgba(34, 36, 37, 0.9)'; const iconColor = disabled ? 'rgba(34, 36, 37, 0.5)' : 'rgba(34, 36, 37, 0.9)';
this.setData({ this.setData({
iconColor, iconColor,
}); });
+1 -1
View File
@@ -23,7 +23,7 @@ module.exports = {
getIconColor: function (iconColor, type, plain, disabled) { getIconColor: function (iconColor, type, plain, disabled) {
if (type === 'white' && !plain) { if (type === 'white' && !plain) {
return disabled ? 'rgba(34, 36, 37, 0.7)' : 'rgba(34, 36, 37, 0.9)'; return disabled ? 'rgba(34, 36, 37, 0.5)' : 'rgba(34, 36, 37, 0.9)';
} }
return iconColor; return iconColor;
}, },