feat: 涂色识字完善、找字涂色完成

This commit is contained in:
R524809
2026-05-09 09:56:16 +08:00
parent b85afde7c0
commit c21ac9e935
27 changed files with 328 additions and 1135 deletions
@@ -1,8 +0,0 @@
{
"component": true,
"styleIsolation": "isolated",
"usingComponents": {
"van-popup": "@vant/weapp/popup/index",
"toy-button": "/toy/button-v2/button"
}
}
@@ -1,103 +0,0 @@
.color-picker-popup {
border-radius: 20rpx;
.color-picker-container {
width: 642rpx;
background-color: #fff;
border-radius: 20rpx;
box-shadow: 0 3rpx 4rpx rgba(0, 0, 0, 0.15);
display: flex;
flex-direction: column;
padding: 36rpx 36rpx;
box-sizing: border-box;
align-items: center;
.color-picker-title {
font-size: 32rpx;
color: #141414;
font-weight: bold;
// margin-bottom: 30rpx;
}
.color-options-title {
width: 100%;
height: 1rpx;
position: relative;
padding: 30rpx 0;
.color-options-title-text {
position: absolute;
left: 50%;
transform: translate(-50%, -50%);
top: 50%;
font-size: 28rpx;
color: #666;
padding: 0 20rpx;
background-color: #fff;
}
.color-options-title-line {
margin: 0 14rpx;
height: 1rpx;
background-color: #999;
}
}
.color-options {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 20rpx 0;
.color-option {
width: 60rpx;
height: 60rpx;
border-radius: 10rpx;
margin: 14rpx;
display: inline-block;
cursor: pointer;
border: 1rpx solid #ccc;
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
transition: all 0.2s ease;
&.selected {
// border: 1px solid rgba(10, 111, 252, 1);
transform: scale(1.2);
// border: 1px solid #0A6FFC;
border: 1px solid #4096ff;
// box-shadow: 0px 0px 1px 2px rgba(0, 145, 255, 0.1);
box-shadow: 0 0 6rpx 6rpx rgba(5, 145, 255, 0.1);
}
}
}
}
}
.btn-area {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
margin: 10rpx 24rpx;
}
// .btn-yellow {
// display: flex;
// justify-content: center;
// align-items: center;
// height: 86rpx;
// width: 400rpx;
// border-radius: 18rpx;
// background: rgba(255, 215, 25, 1);
// box-shadow: 0px 10rpx 4rpx #DBB917;
// font-size: 32rpx;
// font-weight: bold;
// color: #fff;
// &.disabled {
// background: rgba(255, 215, 25, 0.5);
// box-shadow: 0px 10rpx 4rpx rgba(219, 185, 23, 0.5);
// }
// }
@@ -1,47 +0,0 @@
import { WATER_COLORS } from '../../constants/colors';
Component({
options: {},
/**
* 组件的属性列表
*/
properties: {
show: {
type: Boolean,
value: false,
},
currentColor: {
type: String,
value: '',
},
},
/**
* 组件的初始数据
*/
data: {
extended24Colors: WATER_COLORS.extended24,
},
lifetimes: {
attached() {},
},
/**
* 组件的方法列表
*/
methods: {
onClose() {
this.triggerEvent('onClose');
},
onSelectColor(e: WechatMiniprogram.TouchEvent) {
const { color } = e.currentTarget.dataset;
this.setData({
currentColor: color,
});
},
onChange(e: WechatMiniprogram.TouchEvent) {
const { currentColor } = this.data;
this.triggerEvent('onChange', { color: currentColor });
},
},
});
@@ -1,40 +0,0 @@
<van-popup
show="{{ show }}"
bind:close="onClose"
custom-class="color-picker-popup">
<view class="color-picker-container">
<text class="color-picker-title">选择颜色</text>
<!-- <view class="color-options-title">
<text class="color-options-title-text">基础12色</text>
<view class="color-options-title-line"></view>
</view>
<view class="color-options">
<block wx:for="{{WATER_COLORS.basic12}}" wx:key="index">
<view
class="color-option {{item.hex === currentColor ? 'selected' : ''}}"
style="background-color: {{item.hex}};"
bindtap="onSelectColor"
data-color="{{item.hex}}"></view>
</block>
</view>
<view class="color-options-title">
<text class="color-options-title-text">扩展24色</text>
<view class="color-options-title-line"></view>
</view> -->
<view class="color-options">
<block wx:for="{{extended24Colors}}" wx:key="index">
<view
class="color-option {{item.hex === currentColor ? 'selected' : ''}}"
style="background-color: {{item.hex}};"
bindtap="onSelectColor"
data-color="{{item.hex}}"></view>
</block>
</view>
<view class="btn-area">
<!-- <view class="btn-yellow">确认选择</view> -->
<toy-button type="primary" bind:click="onChange" width="400rpx">
确认选择
</toy-button>
</view>
</view>
</van-popup>
@@ -1,10 +0,0 @@
{
"component": true,
"styleIsolation": "isolated",
"usingComponents": {
"van-popup": "@vant/weapp/popup/index",
"toy-button": "/toy/button-v2/button",
"van-tab": "@vant/weapp/tab/index",
"van-tabs": "@vant/weapp/tabs/index"
}
}
@@ -1,93 +0,0 @@
.word-picker-content {
padding: 28rpx;
background-color: #ffffff;
overflow: hidden;
}
.word-picker-title {
font-size: 32rpx;
color: #141414;
font-weight: bold;
text-align: center;
margin-bottom: 28rpx;
}
.nav-class {
// background-color: red;
// width: 890rpx;
}
.tab-class {
// width: 220rpx;
// flex-basis: auto !important;
// display: inline-block;
}
.tab-active-class {
color: #93d333;
}
.wrap-class {
margin-bottom: 28rpx;
// background-color: blue;
}
.word-list-wrapper {
padding: 28rpx 0;
overflow-y: auto;
height: 500rpx;
.word-list {
display: grid;
grid-template-columns: repeat(6, 72rpx);
grid-template-rows: repeat(1, 72rpx);
gap: 40rpx;
justify-content: center;
// box-shadow: 0 0 -10rpx rgba(0, 0, 0, 0.2);
// align-items: flex-start;
.word-item {
width: 72rpx;
height: 72rpx;
border-radius: 16rpx;
background: rgba(240, 240, 240, 1);
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.15);
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
color: #141414;
&.selected {
background: rgb(147, 211, 51);
color: #ffffff;
box-shadow: 0px 2px 4px rgba(147, 211, 51, 0.15);
}
}
}
.word-item-empty {
height: 28rpx;
width: 100%;
}
}
.selected-words {
height: 66rpx;
padding: 28rpx;
font-size: 28rpx;
color: #141414;
.selected-words-text {
font-weight: bold;
color: #93d333;
}
}
.btn-area {
display: flex;
justify-content: space-between;
// margin-bottom: 96rpx;
padding: 0 28rpx;
}
@@ -1,100 +0,0 @@
import { WORDS } from '../../constants/words';
Component({
options: {},
/**
* 组件的属性列表
*/
properties: {
show: {
type: Boolean,
value: false,
},
cardList: {
type: Array,
value: [],
},
currentTab: {
type: Number,
value: 0,
},
selectedWords: {
type: Array,
value: []
},
max: {
type: Number,
value: 6
}
},
/**
* 组件的初始数据
*/
data: {
wordList: WORDS,
},
lifetimes: {
ready() {
// 初始化同步一次 selectedWords,避免首次传入时未触发 observers 的情况
const list = (this.data as any).cardList || [];
if (Array.isArray(list) && list.length > 0) {
const selectedWords = list.map((item: any) => item.word);
this.setData({ selectedWords });
}
},
},
observers: {
cardList(newVal: CardList) {
const selectedWords = newVal.map((item) => item.word);
this.setData({ selectedWords });
},
},
/**
* 组件的方法列表
*/
methods: {
onClose() {
this.triggerEvent('onClose');
},
onClear() {
this.setData({
selectedWords: [],
});
},
onChange() {
this.triggerEvent('onChange', { selectedWords: this.data.selectedWords });
},
onTabChange(e: WechatMiniprogram.CustomEvent) {
const index = typeof e.detail === 'object' ? e.detail.index : e.detail;
this.setData({ currentTab: index });
},
onWordClick(e: WechatMiniprogram.TouchEvent) {
const { word } = e.currentTarget.dataset;
const { selectedWords, max } = this.data;
let newSelectedWords = selectedWords as string[];
// 如果是已选中的文字,直接取消选中
if (newSelectedWords.includes(word)) {
newSelectedWords = newSelectedWords.filter((item) => item !== word);
} else {
// 如果是未选中的文字,先判断是否已选满6个
if (newSelectedWords.length >= max) {
wx.showToast({
title: `最多选择 ${max} 个字`,
icon: 'none',
});
return;
}
newSelectedWords = [...newSelectedWords, word];
}
this.setData({
selectedWords: newSelectedWords,
});
},
},
});
@@ -1,74 +0,0 @@
<wxs module="wxs" src="./word-picker.wxs"></wxs>
<van-popup
show="{{ show }}"
bind:close="onClose"
round
closeable="{{true}}"
close-on-click-overlay="{{true}}"
safe-area-inset-bottom="{{false}}"
position="bottom"
custom-style="height:78%"
custom-class="word-picker">
<view class="word-picker-content">
<view class="word-picker-title">请选择文字</view>
<van-tabs
wx:if="{{show}}"
id="tabs"
animated
color="#93d333"
ellipsis="{{false}}"
line-width="90rpx"
nav-class="nav-class"
tab-class="tab-class"
wrap-class="wrap-class"
tab-active-class="tab-active-class"
swipeable="{{true}}"
active="{{currentTab}}"
bind:change="onTabChange">
<van-tab
wx:for="{{wordList}}"
wx:for-index="categoryIndex"
wx:key="categoryIndex"
title="{{wordList[categoryIndex].icon}} {{wordList[categoryIndex].categoryName}}">
<view class="word-list-wrapper">
<view class="word-list">
<view
class="word-item {{wxs.isSelected(selectedWords, item) ? 'selected' : ''}}"
wx:for="{{wordList[categoryIndex].words}}"
wx:key="index"
data-word="{{item}}"
bind:tap="onWordClick">
<text class="word-item-text">{{item}}</text>
<!-- <text class="word-item-icon icon-success"></text> -->
</view>
</view>
<view class="word-item-empty"></view>
</view>
</van-tab>
</van-tabs>
<view class="selected-words">
已选文字:
<text
class="selected-word-text"
wx:for="{{selectedWords}}"
wx:key="index"
>{{item}}{{index !== selectedWords.length - 1 ? '、' :
''}}</text
>
</view>
<view class="btn-area">
<toy-button type="primary" bind:click="onChange" width="380rpx">
(已选{{selectedWords.length}}个) 确定
</toy-button>
<toy-button
type="white"
bind:click="onClear"
width="220rpx"
icon="clear"
icon-class-prefix="toy-icon">
清空
</toy-button>
</view>
</view>
</van-popup>
@@ -1,8 +0,0 @@
module.exports = {
isSelected: function (selectedWords, word) {
if (selectedWords && selectedWords.length > 0) {
return selectedWords.indexOf(word) !== -1;
}
return false;
},
};