feat: 生产 shape
This commit is contained in:
@@ -3,7 +3,7 @@ Component({
|
||||
* 组件的属性列表
|
||||
*/
|
||||
properties: {
|
||||
key: {
|
||||
index: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
@@ -73,17 +73,18 @@ Component({
|
||||
});
|
||||
},
|
||||
onDelete() {
|
||||
const { key } = this.data;
|
||||
this.triggerEvent('onDelete', { key });
|
||||
const { index } = this.data;
|
||||
this.triggerEvent('onDelete', { index });
|
||||
},
|
||||
onColorTap() {
|
||||
const { key, fillColor } = this.data;
|
||||
this.triggerEvent('onColorTap', { key, fillColor });
|
||||
const { index, fillColor } = this.data;
|
||||
console.log('onColorTap', index, fillColor);
|
||||
this.triggerEvent('onColorTap', { index, fillColor });
|
||||
},
|
||||
|
||||
onShapeTap() {
|
||||
const { key } = this.data;
|
||||
this.triggerEvent('onShapeTap', { key });
|
||||
const { index } = this.data;
|
||||
this.triggerEvent('onShapeTap', { index });
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
box-shadow: 0 3rpx 4rpx rgba(0, 0, 0, 0.15);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 36rpx 36rpx;
|
||||
padding: 32rpx 24rpx;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
|
||||
@@ -16,77 +16,67 @@
|
||||
font-size: 32rpx;
|
||||
color: #141414;
|
||||
font-weight: bold;
|
||||
margin-bottom: 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.shape-options-wrapper {
|
||||
padding: 28rpx 0;
|
||||
margin: 34rpx 0;
|
||||
width: 100%;
|
||||
height: 500rpx;
|
||||
height: 670rpx;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.shape-options {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 186rpx);
|
||||
gap: 12rpx;
|
||||
grid-template-columns: repeat(3, 160rpx);
|
||||
gap: 38rpx;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
padding: 6rpx 0;
|
||||
|
||||
.shape-option {
|
||||
width: 140rpx;
|
||||
position: relative;
|
||||
width: 160rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
transition: all 0.2s ease;
|
||||
padding: 10rpx;
|
||||
border-radius: 10rpx;
|
||||
border: 1rpx solid transparent;
|
||||
padding: 4rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 1rpx solid #F2F2F2;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0px 8px 12px rgba(184, 210, 188, 0.2);
|
||||
overflow: hidden;
|
||||
|
||||
.shape-svg-container {
|
||||
.shape-svg {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1rpx solid #141414;
|
||||
border-radius: 8rpx;
|
||||
background-color: #fafafa;
|
||||
margin-bottom: 8rpx;
|
||||
position: relative;
|
||||
|
||||
.shape-svg {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.shape-name {
|
||||
font-size: 24rpx;
|
||||
color: #141414;
|
||||
text-align: center;
|
||||
line-height: 1.2;
|
||||
line-height: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
// transform: scale(1.1);
|
||||
// border: 1px solid rgb(147, 211, 51);
|
||||
// background-color: rgba(64, 150, 255, 0.05);
|
||||
|
||||
.shape-svg-container {
|
||||
border: 1px solid #93d333;
|
||||
// border: 1px solid #4096ff;
|
||||
// background-color: #fff;
|
||||
// box-shadow: 0 0 6rpx 2rpx rgba(147, 211, 51, 0.2);
|
||||
}
|
||||
border: 1px solid #93d333;
|
||||
|
||||
.shape-name {
|
||||
color: rgb(147, 211, 51);
|
||||
// font-weight: bold;
|
||||
color: #93d333;
|
||||
}
|
||||
}
|
||||
|
||||
.img-shape-selected {
|
||||
position: absolute;
|
||||
bottom: -2rpx;
|
||||
right: -2rpx;
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,9 @@ Component({
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
selectedShape: {
|
||||
type: String,
|
||||
value: '',
|
||||
},
|
||||
currentShapeKey: {
|
||||
type: String,
|
||||
value: '',
|
||||
singleMode: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
/**
|
||||
@@ -24,7 +20,7 @@ Component({
|
||||
*/
|
||||
data: {
|
||||
shapes: [] as (ShapeCard & { svgDataUrl: string })[],
|
||||
selectedShapes: [] as string[], // 多选模式下选中的形状数组
|
||||
totalSelected: 0,
|
||||
},
|
||||
lifetimes: {
|
||||
attached() {
|
||||
@@ -37,7 +33,6 @@ Component({
|
||||
svgDataUrl: svgDataUri
|
||||
};
|
||||
});
|
||||
console.log('shapesWithDataUrl---:', shapesWithDataUrl);
|
||||
this.setData({
|
||||
shapes: shapesWithDataUrl
|
||||
});
|
||||
@@ -53,28 +48,26 @@ Component({
|
||||
|
||||
onSelectShape(e: WechatMiniprogram.TouchEvent) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
const { currentShapeKey, shapes } = this.data;
|
||||
|
||||
if (currentShapeKey) {
|
||||
const { singleMode, shapes } = this.data;
|
||||
let newShapes = [];
|
||||
|
||||
if (singleMode) {
|
||||
// 单选模式:currentShapeKey 不为空时,只能选中一个形状
|
||||
this.setData({
|
||||
shapes: shapes.map((item, i) => ({
|
||||
...item,
|
||||
checked: i === index
|
||||
}))
|
||||
});
|
||||
newShapes = shapes.map((item, i) => ({
|
||||
...item,
|
||||
checked: i === index
|
||||
}));
|
||||
} else {
|
||||
// 多选模式:currentShapeKey 为空时,支持多选,最多可选6个
|
||||
let shapesCopy = this.data.shapes.map(item => ({ ...item }));
|
||||
newShapes = this.data.shapes.map(item => ({ ...item }));
|
||||
const targetIndex = index;
|
||||
|
||||
// 统计当前已选中的数量
|
||||
const checkedCount = shapesCopy.filter(item => item.checked).length;
|
||||
const checkedCount = newShapes.filter(item => item.checked).length;
|
||||
|
||||
if (shapesCopy[targetIndex].checked) {
|
||||
if (newShapes[targetIndex].checked) {
|
||||
// 如果已选中,则取消选中
|
||||
shapesCopy[targetIndex].checked = false;
|
||||
newShapes[targetIndex].checked = false;
|
||||
} else {
|
||||
if (checkedCount >= 6) {
|
||||
wx.showToast({
|
||||
@@ -85,38 +78,20 @@ Component({
|
||||
return;
|
||||
}
|
||||
// 如果未选中,则添加到选中列表
|
||||
shapesCopy[targetIndex].checked = true;
|
||||
newShapes[targetIndex].checked = true;
|
||||
}
|
||||
|
||||
this.setData({
|
||||
shapes: shapesCopy,
|
||||
});
|
||||
}
|
||||
const totalSelected = newShapes.filter(item => item.checked).length;
|
||||
this.setData({
|
||||
shapes: newShapes,
|
||||
totalSelected,
|
||||
});
|
||||
},
|
||||
|
||||
onChange() {
|
||||
const { selectedShape, selectedShapes, currentShapeKey } = this.data;
|
||||
|
||||
if (currentShapeKey) {
|
||||
// 单选模式:返回单个选中的形状
|
||||
this.triggerEvent('onChange', { shape: selectedShape, currentShapeKey });
|
||||
} else {
|
||||
// 多选模式:返回选中的形状数组
|
||||
this.triggerEvent('onChange', { shapes: selectedShapes });
|
||||
}
|
||||
},
|
||||
|
||||
// 获取选中状态的 CSS 类名
|
||||
getShapeClass(shapeId: string): string {
|
||||
const { currentShapeKey, selectedShapes } = this.data;
|
||||
|
||||
if (currentShapeKey) {
|
||||
// 单选模式:检查是否等于当前选中的形状
|
||||
return shapeId === currentShapeKey ? 'selected single-mode' : '';
|
||||
} else {
|
||||
// 多选模式:检查是否在选中列表中
|
||||
return selectedShapes.includes(shapeId) ? 'selected multi-mode' : '';
|
||||
}
|
||||
const { shapes } = this.data;
|
||||
const selectedShapes = shapes.filter(item => item.checked);
|
||||
this.triggerEvent('onChange', { shapes: selectedShapes, singleMode: this.data.singleMode });
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
custom-class="shape-picker-popup">
|
||||
<view class="shape-picker-container">
|
||||
<text class="shape-picker-title"
|
||||
>选择形状{{ currentShapeKey ? '' : '(多选)' }}</text
|
||||
>选择形状{{ singleMode ? '' : '(多选)' }}</text
|
||||
>
|
||||
<view class="shape-options-wrapper">
|
||||
<view class="shape-options">
|
||||
@@ -15,20 +15,16 @@
|
||||
bindtap="onSelectShape"
|
||||
data-index="{{index}}"
|
||||
data-shape="{{item.id}}">
|
||||
<view class="shape-svg-container">
|
||||
<image
|
||||
class="shape-svg"
|
||||
src="{{ item.svgDataUrl }}"
|
||||
mode="aspectFit" />
|
||||
<!-- 多选模式下显示选中标记 -->
|
||||
<view wx:if="{{ item.checked }}" class="selected-icon">
|
||||
<toy-icon
|
||||
name="ic_check"
|
||||
size="24"
|
||||
color="#93d333" />
|
||||
</view>
|
||||
</view>
|
||||
<image
|
||||
class="shape-svg"
|
||||
src="{{ item.svgDataUrl }}"
|
||||
mode="aspectFit" />
|
||||
<text class="shape-name">{{item.name}}</text>
|
||||
<image
|
||||
wx:if="{{item.checked}}"
|
||||
class="img-shape-selected"
|
||||
src="/assets/imgs/checked.png"
|
||||
mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -37,9 +33,8 @@
|
||||
type="primary"
|
||||
bind:click="onChange"
|
||||
width="400rpx"
|
||||
disabled="{{ currentShapeKey ? !selectedShape : selectedShapes.length === 0 }}">
|
||||
确认选择{{ !currentShapeKey && selectedShapes.length > 0 ? '('
|
||||
+ selectedShapes.length + '个)' : '' }}
|
||||
disabled="{{ totalSelected === 0 }}">
|
||||
确认选择{{ singleMode ? '' : '(' + totalSelected + '个)' }}
|
||||
</toy-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
Reference in New Issue
Block a user