138 lines
2.4 KiB
Vue
138 lines
2.4 KiB
Vue
|
|
<template>
|
||
|
|
<label
|
||
|
|
class="check-item"
|
||
|
|
:class="{
|
||
|
|
'check-checked': modelValue,
|
||
|
|
'check-disabled': disabled,
|
||
|
|
}"
|
||
|
|
@click.stop="handleClick"
|
||
|
|
>
|
||
|
|
<view class="check-icon">
|
||
|
|
<!-- 未选中显示空心方框 -->
|
||
|
|
<view class="check-box" v-if="!modelValue"></view>
|
||
|
|
<!-- 选中显示带勾的方框 -->
|
||
|
|
<view class="check-box checked" v-else>
|
||
|
|
<uni-icons type="checkmarkempty" size="22" color="#fff"></uni-icons>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
<view class="check-label" v-if="label">
|
||
|
|
<slot>{{ label }}</slot>
|
||
|
|
</view>
|
||
|
|
<input
|
||
|
|
type="checkbox"
|
||
|
|
class="check-input"
|
||
|
|
:checked="modelValue"
|
||
|
|
:disabled="disabled"
|
||
|
|
/>
|
||
|
|
</label>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup>
|
||
|
|
// 组件属性定义
|
||
|
|
const props = defineProps({
|
||
|
|
// 绑定值(布尔值)
|
||
|
|
modelValue: {
|
||
|
|
type: Boolean,
|
||
|
|
default: false,
|
||
|
|
},
|
||
|
|
// 选项标签
|
||
|
|
label: {
|
||
|
|
type: String,
|
||
|
|
default: "",
|
||
|
|
},
|
||
|
|
// 是否禁用
|
||
|
|
disabled: {
|
||
|
|
type: Boolean,
|
||
|
|
default: false,
|
||
|
|
},
|
||
|
|
// 选中颜色
|
||
|
|
checkedColor: {
|
||
|
|
type: String,
|
||
|
|
default: "#007aff",
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
// 组件事件定义
|
||
|
|
const emit = defineEmits(["update:modelValue", "change"]);
|
||
|
|
|
||
|
|
// 点击处理
|
||
|
|
const handleClick = () => {
|
||
|
|
if (props.disabled) return;
|
||
|
|
|
||
|
|
const newValue = !props.modelValue;
|
||
|
|
emit("update:modelValue", newValue);
|
||
|
|
emit("change", newValue);
|
||
|
|
};
|
||
|
|
|
||
|
|
// 状态变化处理
|
||
|
|
const handleChange = (e) => {
|
||
|
|
if (props.disabled) return;
|
||
|
|
|
||
|
|
const newValue = e.target.checked;
|
||
|
|
emit("update:modelValue", newValue);
|
||
|
|
emit("change", newValue);
|
||
|
|
};
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.check-item {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
position: relative;
|
||
|
|
cursor: pointer;
|
||
|
|
user-select: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.check-icon {
|
||
|
|
margin-right: 12rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 方框样式 */
|
||
|
|
.check-box {
|
||
|
|
width: 45rpx;
|
||
|
|
height: 45rpx;
|
||
|
|
border: 2rpx solid #999;
|
||
|
|
border-radius: 4rpx;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
transition: all 0.2s ease;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 选中状态的方框 */
|
||
|
|
.check-box.checked {
|
||
|
|
background-color: v-bind(checkedColor);
|
||
|
|
border-color: v-bind(checkedColor);
|
||
|
|
}
|
||
|
|
|
||
|
|
.check-label {
|
||
|
|
font-size: 30rpx;
|
||
|
|
color: #333;
|
||
|
|
}
|
||
|
|
|
||
|
|
.check-checked .check-label {
|
||
|
|
color: v-bind(checkedColor);
|
||
|
|
}
|
||
|
|
|
||
|
|
.check-input {
|
||
|
|
position: absolute;
|
||
|
|
width: 0;
|
||
|
|
height: 0;
|
||
|
|
opacity: 0;
|
||
|
|
margin: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.check-disabled {
|
||
|
|
opacity: 0.6;
|
||
|
|
pointer-events: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.check-disabled .check-label {
|
||
|
|
color: #999;
|
||
|
|
}
|
||
|
|
|
||
|
|
.check-disabled .check-box {
|
||
|
|
border-color: #ccc;
|
||
|
|
}
|
||
|
|
</style>
|