feat:优化练字贴
This commit is contained in:
@@ -42,13 +42,16 @@ page {
|
||||
.word-input-box {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
justify-content: flex-start;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.operation-box {
|
||||
.action-buttons-box {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
gap: 20rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,14 @@ Page({
|
||||
maxCol: 0 as number,
|
||||
|
||||
data: {
|
||||
// 选中的汉字列表
|
||||
// 最终的汉字列表(合并输入和选择的汉字)
|
||||
words: [] as string[],
|
||||
// 来自文本框输入的汉字(每次输入替换)
|
||||
inputWords: [] as string[],
|
||||
// 来自弹窗选择的汉字(追加)
|
||||
selectedWords: [] as string[],
|
||||
// 输入框的值(用于清空)
|
||||
inputValue: '',
|
||||
showSelectWordPopup: false,
|
||||
showColorPopup: false,
|
||||
currentKey: 0,
|
||||
@@ -33,9 +39,12 @@ Page({
|
||||
const hasShowPracticeDemo =
|
||||
wx.getStorageSync('hasShowPracticeDemo') || false;
|
||||
if (!hasShowPracticeDemo) {
|
||||
const demoWords = ['好', '好', '学', '习', '天', '天', '向', '上'];
|
||||
this.setData(
|
||||
{
|
||||
words: ['好', '好', '学', '习', '天', '天', '向', '上'],
|
||||
words: demoWords,
|
||||
inputWords: demoWords,
|
||||
selectedWords: [],
|
||||
},
|
||||
() => {
|
||||
wx.setStorageSync('hasShowPracticeDemo', true);
|
||||
@@ -86,47 +95,68 @@ Page({
|
||||
}
|
||||
},
|
||||
|
||||
// 输入组件回调
|
||||
// 输入组件回调(所见即所得:替换文本框输入的汉字)
|
||||
onConfirmInput(e: any) {
|
||||
const value: string = (e && e.detail && e.detail.value) || '';
|
||||
const text = (value || '').trim();
|
||||
if (!text) return;
|
||||
|
||||
// 如果文本框为空,清空输入汉字
|
||||
if (!text) {
|
||||
const { selectedWords } = this.data as any;
|
||||
const updatedWords = [...selectedWords];
|
||||
this.setData(
|
||||
{
|
||||
inputWords: [],
|
||||
words: updatedWords,
|
||||
},
|
||||
() => {
|
||||
this.renderPracticeContent().catch(console.error);
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.isChineseText(text)) {
|
||||
wx.showToast({ title: '请输入汉字', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
const { words } = this.data as any;
|
||||
|
||||
// 1. 解析新输入的汉字
|
||||
const newChars = this.splitToSingleChars(text);
|
||||
if (newChars.length === 0) {
|
||||
// 1. 解析输入的汉字
|
||||
const newInputChars = this.splitToSingleChars(text);
|
||||
if (newInputChars.length === 0) {
|
||||
wx.showToast({ title: '请输入有效汉字', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 检查是否超过限制
|
||||
if (words.length + newChars.length > 11) {
|
||||
const { selectedWords } = this.data as any;
|
||||
|
||||
// 2. 检查是否超过限制(输入汉字 + 已选择的汉字)
|
||||
if (newInputChars.length + selectedWords.length > 11) {
|
||||
wx.showToast({
|
||||
title: `最多只能添加 11 个字,当前已有 ${words.length} 个,输入了 ${newChars.length} 个`,
|
||||
title: `最多只能添加 11 个字,当前已选择 ${selectedWords.length} 个,输入了 ${newInputChars.length} 个`,
|
||||
icon: 'none',
|
||||
duration: 3000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 直接追加新汉字
|
||||
const updatedWords = [...words, ...newChars];
|
||||
// 3. 替换输入汉字(不是追加),合并已选择的汉字
|
||||
const updatedWords = [...newInputChars, ...selectedWords];
|
||||
|
||||
// 4. 更新数据并提示
|
||||
this.setData({ words: updatedWords }, () => {
|
||||
this.renderPracticeContent().catch(console.error);
|
||||
});
|
||||
this.setData(
|
||||
{
|
||||
inputWords: newInputChars,
|
||||
words: updatedWords,
|
||||
},
|
||||
() => {
|
||||
this.renderPracticeContent().catch(console.error);
|
||||
},
|
||||
);
|
||||
|
||||
// 5. 显示添加结果提示
|
||||
wx.showToast({
|
||||
title: `成功添加 ${newChars.length} 个汉字`,
|
||||
title: `已更新输入汉字(${newInputChars.length} 个)`,
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
});
|
||||
@@ -140,30 +170,90 @@ Page({
|
||||
this.setData({ showSelectWordPopup: false });
|
||||
},
|
||||
onChangeWord(e: any) {
|
||||
const selectedWords = e.detail.selectedWords as string[];
|
||||
const newWords = [...this.data.words, ...selectedWords];
|
||||
this.setData({ words: newWords, showSelectWordPopup: false }, () => {
|
||||
if (newWords && newWords.length > 0) {
|
||||
this.renderPracticeContent().catch(console.error);
|
||||
}
|
||||
});
|
||||
const newSelectedWords = e.detail.selectedWords as string[];
|
||||
const { inputWords } = this.data as any;
|
||||
|
||||
// 检查是否超过限制
|
||||
if (inputWords.length + newSelectedWords.length > 11) {
|
||||
wx.showToast({
|
||||
title: `最多只能添加 11 个字,当前输入 ${inputWords.length} 个,选择了 ${newSelectedWords.length} 个`,
|
||||
icon: 'none',
|
||||
duration: 3000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 合并输入汉字和选择的汉字(求并集)
|
||||
const updatedWords = [...inputWords, ...newSelectedWords];
|
||||
this.setData(
|
||||
{
|
||||
selectedWords: newSelectedWords,
|
||||
words: updatedWords,
|
||||
showSelectWordPopup: false,
|
||||
},
|
||||
() => {
|
||||
if (updatedWords && updatedWords.length > 0) {
|
||||
this.renderPracticeContent().catch(console.error);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
// 删除
|
||||
// 删除(需要判断删除的是输入汉字还是选择的汉字)
|
||||
deleteWordCard(e: any) {
|
||||
const { key } = e.detail;
|
||||
const { words } = this.data as any;
|
||||
const next = words.filter((_: string, index: number) => index !== key);
|
||||
this.setData({ words: next }, () =>
|
||||
this.renderPracticeContent().catch(console.error),
|
||||
);
|
||||
const { inputWords, selectedWords } = this.data as any;
|
||||
|
||||
// 判断删除的是输入汉字还是选择的汉字
|
||||
if (key < inputWords.length) {
|
||||
// 删除的是输入汉字
|
||||
const nextInputWords = inputWords.filter(
|
||||
(_: string, index: number) => index !== key,
|
||||
);
|
||||
const nextWords = [...nextInputWords, ...selectedWords];
|
||||
this.setData(
|
||||
{
|
||||
inputWords: nextInputWords,
|
||||
words: nextWords,
|
||||
},
|
||||
() => this.renderPracticeContent().catch(console.error),
|
||||
);
|
||||
} else {
|
||||
// 删除的是选择的汉字
|
||||
const selectedIndex = key - inputWords.length;
|
||||
const nextSelectedWords = selectedWords.filter(
|
||||
(_: string, index: number) => index !== selectedIndex,
|
||||
);
|
||||
const nextWords = [...inputWords, ...nextSelectedWords];
|
||||
this.setData(
|
||||
{
|
||||
selectedWords: nextSelectedWords,
|
||||
words: nextWords,
|
||||
},
|
||||
() => this.renderPracticeContent().catch(console.error),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// 清空
|
||||
// 清空(清空所有来源的汉字:文本框、预览、弹窗选择)
|
||||
clearWords() {
|
||||
this.setData({ words: [] }, () =>
|
||||
this.renderPracticeContent().catch(console.error),
|
||||
// 清空所有汉字数据
|
||||
this.setData(
|
||||
{
|
||||
words: [],
|
||||
inputWords: [],
|
||||
selectedWords: [],
|
||||
inputValue: '', // 清空输入框
|
||||
},
|
||||
() => {
|
||||
this.renderPracticeContent().catch(console.error);
|
||||
},
|
||||
);
|
||||
|
||||
// 关闭弹窗(如果打开)
|
||||
if (this.data.showSelectWordPopup) {
|
||||
this.setData({ showSelectWordPopup: false });
|
||||
}
|
||||
},
|
||||
|
||||
// 随机生成(取基础分类,过滤为可用SVG字,最多11个)
|
||||
|
||||
@@ -2,13 +2,29 @@
|
||||
<view class="wrapper">
|
||||
<text class="wrapper-title">自定义练字贴</text>
|
||||
<view class="word-input-box">
|
||||
<word-input bind:onConfirm="onConfirmInput" width="410rpx" />
|
||||
<word-input bind:onConfirm="onConfirmInput" style="width: 100%;"/>
|
||||
</view>
|
||||
|
||||
<view class="action-buttons-box">
|
||||
<toy-button
|
||||
type="green"
|
||||
bind:click="openSelectWordPopup"
|
||||
width="200rpx">
|
||||
height="80rpx"
|
||||
width="410rpx"
|
||||
icon="success"
|
||||
icon-class-prefix="van-icon">
|
||||
选择文字
|
||||
</toy-button>
|
||||
<toy-button
|
||||
disabled="{{words.length <= 0}}"
|
||||
type="white"
|
||||
bind:click="clearWords"
|
||||
width="220rpx"
|
||||
height="80rpx"
|
||||
icon="clear"
|
||||
icon-class-prefix="toy-icon">
|
||||
清空
|
||||
</toy-button>
|
||||
</view>
|
||||
|
||||
<view class="word-card-box">
|
||||
@@ -27,28 +43,9 @@
|
||||
<empty-state
|
||||
wx:if="{{!words.length}}"
|
||||
title="还没有添加文字"
|
||||
desc="请在上方输入文字或点击“选择文字”按钮,开始创建你的练字田字格吧!"
|
||||
desc='请在上方输入文字或点击"选择文字"按钮,开始创建你的练字田字格吧!'
|
||||
hint="提示:最多可以同时添加 11 个文字" />
|
||||
</view>
|
||||
<view class="operation-box">
|
||||
<toy-button
|
||||
type="primary"
|
||||
bind:click="refreshWords"
|
||||
width="410rpx"
|
||||
icon="refresh"
|
||||
icon-class-prefix="toy-icon">
|
||||
随机生成
|
||||
</toy-button>
|
||||
<toy-button
|
||||
disabled="{{words.length <= 0}}"
|
||||
type="white"
|
||||
bind:click="clearWords"
|
||||
width="200rpx"
|
||||
icon="clear"
|
||||
icon-class-prefix="toy-icon">
|
||||
清空
|
||||
</toy-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view id="previewWrapper" class="wrapper">
|
||||
@@ -88,7 +85,7 @@
|
||||
</view>
|
||||
<word-picker
|
||||
show="{{showSelectWordPopup}}"
|
||||
selectedWords="{{words}}"
|
||||
selectedWords="{{selectedWords}}"
|
||||
max="11"
|
||||
bind:onClose="closeSelectWordPopup"
|
||||
bind:onChange="onChangeWord" />
|
||||
|
||||
Reference in New Issue
Block a user