feat:完成颜色选择器和button组件

This commit is contained in:
2025-06-10 17:32:08 +08:00
parent 13a0afe97e
commit efa213bfe1
14 changed files with 515 additions and 17 deletions
@@ -0,0 +1,8 @@
{
"component": true,
"styleIsolation": "isolated",
"usingComponents": {
"van-popup": "@vant/weapp/popup/index",
"toy-button": "/ui/button/button"
}
}
@@ -0,0 +1,103 @@
.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: 20rpx 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);
// }
// }
@@ -0,0 +1,44 @@
import { WATER_COLORS } from '../../constants/index';
Component({
options: {},
/**
* 组件的属性列表
*/
properties: {
show: {
type: Boolean,
value: false,
},
currentColor: {
type: String,
value: '',
},
},
/**
* 组件的初始数据
*/
data: {
WATER_COLORS: WATER_COLORS,
},
lifetimes: {
attached() {},
},
/**
* 组件的方法列表
*/
methods: {
onClose() {
this.triggerEvent('onClose');
},
onSelectColor(e: WechatMiniprogram.TouchEvent) {
const { color } = e.currentTarget.dataset;
console.log('Selected color:', color);
this.setData({
currentColor: color,
});
this.triggerEvent('onSelectColor', { color });
},
},
});
@@ -0,0 +1,40 @@
<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="{{WATER_COLORS.extended24}}" 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="" width="400rpx">
确认选择
</toy-button>
</view>
</view>
</van-popup>
@@ -37,5 +37,10 @@ Component({
const { key, word } = this.data;
this.triggerEvent('onDelete', { key, word });
},
onColorTap() {
const { color, key, word } = this.data;
this.triggerEvent('onColorTap', { key, word, color });
},
},
});
@@ -1,5 +1,8 @@
<view class="word-card">
<view class="color-box" style="background-color: {{color}};"></view>
<view
class="color-box"
style="background-color: {{color}};"
bindtap="onColorTap"></view>
<view class="word-box border-1px">
<text class="word-content">{{word}}</text>
</view>
+4 -1
View File
@@ -6,7 +6,10 @@
"enablePullDownRefresh": false,
"usingComponents": {
"van-icon": "@vant/weapp/icon/index",
"van-popup": "@vant/weapp/popup/index",
"word-input": "../../components/word-input/word-input",
"word-card": "../../components/word-card/word-card"
"word-card": "../../components/word-card/word-card",
"color-picker": "../../components/color-picker/color-picker",
"toy-button": "../../ui/button/button"
}
}
+79 -2
View File
@@ -67,9 +67,12 @@ page {
justify-content: center;
background-color: #fff;
box-shadow: 0px -2px 4px rgba(0, 0, 0, 0.25);
padding-top: 24rpx;
}
.btn-green {
/* .btn-green {
display: flex;
justify-content: center;
align-items: center;
@@ -86,4 +89,78 @@ page {
.btn-text {
margin-left: 24rpx;
}
}
&.disabled {
background: rgba(147, 211, 51, 0.5);
box-shadow: 0px 10rpx 4rpx rgba(121, 185, 21, 0.5);
}
}
*/
/* .color-picker-popup {
border-radius: 20rpx;
.color-picker-container {
width: 642rpx;
// height: 876rpx;
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: 20rpx 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: 6rpx;
margin: 14rpx;
display: inline-block;
cursor: pointer;
border: 1rpx solid #ccc;
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
}
}
}
} */
+35 -1
View File
@@ -10,6 +10,10 @@ Page({
data: {
cardList: [] as Array<{ color: string; word: string }>,
showColorPopup: false,
currentKey: 0,
currentColor: '',
WATER_COLORS: WATER_COLORS,
},
onReady() {
@@ -126,7 +130,7 @@ Page({
/** 下载打印 */
exportToPrint() {
console.log('this.canvas:', this.canvas);
if (this.canvas) {
if (this.canvas && this.data.cardList.length > 0) {
wx.canvasToTempFilePath({
canvas: this.canvas,
fileType: 'png',
@@ -150,4 +154,34 @@ Page({
return;
}
},
onColorTap(e: WechatMiniprogram.CustomEvent) {
const { key, word, color } = e.detail;
console.log('onColorTap key:', key, 'word:', word, 'color:', color);
this.setData({
showColorPopup: true,
currentKey: key,
currentColor: color,
});
// const { cardList } = this.data;
// const updatedCardList = cardList.map((item, index) =>
// index === key ? { ...item, color } : item,
// );
// this.setData({ cardList: updatedCardList });
// wx.showToast({
// title: `已更改 "${word}" 的颜色`,
// icon: 'none',
// duration: 2000,
// });
// // this.renderCanvas();
// this.textDrawService?.draw(updatedCardList);
},
onCloseColorPopup() {
this.setData({
showColorPopup: false,
currentKey: 0,
currentColor: '',
});
},
});
+55 -4
View File
@@ -12,13 +12,15 @@
key="{{index}}"
word="{{item.word}}"
color="{{item.color}}"
bind:onDelete="deleteWordCard" />
bind:onDelete="deleteWordCard"
bind:onColorTap="onColorTap" />
<word-card
wx:if="{{cardList[index + 1]}}"
key="{{index + 1}}"
word="{{cardList[index + 1].word}}"
color="{{cardList[index + 1].color}}"
bind:onDelete="deleteWordCard" />
bind:onDelete="deleteWordCard"
bind:onColorTap="onColorTap" />
</view>
</block>
</view>
@@ -36,10 +38,59 @@
</view>
</view>
<view class="empty"></view>
<color-picker
show="{{showColorPopup}}"
currentColor="{{currentColor}}"
bind:onClose="onCloseColorPopup" />
<!-- <van-popup
show="{{ showColorPopup }}"
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"
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="{{WATER_COLORS.extended24}}" wx:key="index">
<view
class="color-option"
style="background-color: {{item.hex}};"
bindtap="onSelectColor"
data-color="{{item.hex}}"></view>
</block>
</view>
</view>
</van-popup> -->
</view>
<view class="btn-area">
<view class="btn btn-green" bindtap="exportToPrint">
<!-- <view
class="btn btn-green {{cardList.length > 0 ? '' : 'disabled'}}"
bindtap="exportToPrint">
<van-icon class-prefix="j-icon" name="download" size="44rpx" />
<text class="btn-text">下载打印</text>
</view>
</view> -->
<toy-button
type="green"
bind:click="exportToPrint"
width="680rpx"
disabled="{{cardList.length <= 0}}"
icon="download"
icon-class-prefix="j-icon">
下载打印
</toy-button>
</view>
+4 -2
View File
@@ -1,5 +1,7 @@
{
"component": true,
"styleIsolation": "apply-shared",
"usingComponents": {}
"usingComponents": {
"van-icon": "@vant/weapp/icon/index",
"van-loading": "@vant/weapp/loading/index"
}
}
+41
View File
@@ -0,0 +1,41 @@
@button-default-height: 86rpx;
@button-border-radius: 18rpx;
@button-default-font-size: 32rpx;
@button-default-color: #fff;
.toy-button {
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
height: @button-default-height;
line-height: @button-default-height;
border-radius: @button-border-radius;
font-size: @button-default-font-size;
color: @button-default-color;
&--primary {
background: rgba(255, 215, 25, 1);
box-shadow: 0px 10rpx 4rpx #DBB917;
&.disabled {
background: rgba(255, 215, 25, 0.5);
box-shadow: 0px 10rpx 4rpx rgba(219, 185, 23, 0.5);
}
}
&--green {
background: rgba(147, 211, 51, 1);
box-shadow: 0px 10rpx 4rpx rgba(121, 185, 21, 1);
&.disabled {
background: rgba(147, 211, 51, 0.5);
box-shadow: 0px 10rpx 4rpx rgba(121, 185, 21, 0.5);
}
}
.loading-class,
&__icon {
margin-right: 24rpx;
}
}
+52 -6
View File
@@ -8,16 +8,12 @@ Component({
properties: {
type: {
type: String,
value: 'default', // default, green, white
value: 'default', // primary, green, white
},
size: {
type: String,
value: 'normal', // large, normal, small, mini
},
icon: {
type: String,
value: '', // 图标名称
},
disabled: {
type: Boolean,
value: false, // 是否禁用
@@ -30,6 +26,52 @@ Component({
type: Boolean,
value: false, // 是否加载中
},
style: {
type: String,
value: '', // 自定义样式
},
// className: {
// type: String,
// value: '', // 自定义类名
// },
width: {
type: String,
value: '', // 按钮宽度
},
height: {
type: String,
value: '',
},
loadingType: {
type: String,
value: 'circular',
},
loadingSize: {
type: String,
value: '20px',
},
loadingColor: {
type: String,
value: '#ffffff',
},
// icon
icon: {
type: String,
value: '',
},
iconClassPrefix: {
type: String,
value: 'j-icon',
},
iconSize: {
type: String,
value: '44rpx',
},
iconColor: {
type: String,
value: '#ffffff',
},
},
/**
* 组件的初始数据
@@ -41,5 +83,9 @@ Component({
/**
* 组件的方法列表
*/
methods: {},
methods: {
onClick(e: WechatMiniprogram.TouchEvent): void {
this.triggerEvent('click', e);
},
},
});
+41
View File
@@ -0,0 +1,41 @@
<wxs src="../wxs/base.wxs" module="Utils" />
<button
class="toy-button toy-button--{{type}} {{ disabled ? 'toy-button--disabled' : '' }} {{Utils.classNames({disabled: disabled, loading: loading })}}"
style="{{style}};{{width ? 'width:' + width + ';' : ''}};{{height ? 'height:' + height + ';' : ''}}"
session-from="{{ sessionFrom }}"
send-message-title="{{ sendMessageTitle }}"
send-message-path="{{ sendMessagePath }}"
send-message-img="{{ sendMessageImg }}"
show-message-card="{{ showMessageCard }}"
app-parameter="{{ appParameter }}"
aria-label="{{ ariaLabel }}"
bindtap="{{ disabled || loading ? '' : 'onClick' }}"
bindgetuserinfo="onGetUserInfo"
bindcontact="onContact"
bindgetphonenumber="onGetPhoneNumber"
bindgetrealtimephonenumber="onGetRealTimePhoneNumber"
bindagreeprivacyauthorization="onAgreePrivacyAuthorization"
binderror="onError"
bindlaunchapp="onLaunchApp"
bindopensetting="onOpenSetting"
bindchooseavatar="onChooseAvatar">
<block wx:if="{{ loading }}">
<van-loading
custom-class="loading-class"
size="{{ loadingSize || iconSize }}"
type="{{ loadingType }}"
color="{{ loadingColor }}" />
</block>
<block wx:else>
<van-icon
wx:if="{{ icon }}"
size="1.2em"
name="{{ icon }}"
size="{{ iconSize }}"
color="{{ iconColor }}"
class-prefix="{{ iconClassPrefix }}"
class="toy-button__icon" />
</block>
<slot></slot>
</button>