139 lines
2.5 KiB
Vue
139 lines
2.5 KiB
Vue
![]() |
<template>
|
|||
|
<view class="cl-rate">
|
|||
|
<view class="cl-rate__icon" v-for="(item, index) in list" :key="index" @tap="onTap(index)">
|
|||
|
<cl-icon :class-name="icon" :size="size" :color="voidColor"></cl-icon>
|
|||
|
|
|||
|
<view
|
|||
|
class="cl-rate__icon-active"
|
|||
|
:style="{
|
|||
|
width: item.width,
|
|||
|
}"
|
|||
|
>
|
|||
|
<cl-icon :class-name="icon" :size="size" :color="item.color"></cl-icon>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
|
|||
|
<view class="cl-rate__text" v-if="showText">
|
|||
|
{{ text }}
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
|
|||
|
<script lang="ts">
|
|||
|
import { computed, defineComponent, ref, watch, type PropType } from "vue";
|
|||
|
import { useForm } from "../../hooks";
|
|||
|
import { getCurrentColor } from "../../utils";
|
|||
|
import { isEmpty } from "lodash-es";
|
|||
|
|
|||
|
export default defineComponent({
|
|||
|
name: "cl-rate",
|
|||
|
|
|||
|
props: {
|
|||
|
// 绑定值
|
|||
|
modelValue: {
|
|||
|
type: Number,
|
|||
|
default: 0,
|
|||
|
},
|
|||
|
// 评分图标
|
|||
|
icon: {
|
|||
|
type: String,
|
|||
|
default: "cl-icon-favor-fill",
|
|||
|
},
|
|||
|
// 选中颜色,Array下为多色
|
|||
|
color: {
|
|||
|
type: [String, Array] as PropType<string | string[]>,
|
|||
|
default: "",
|
|||
|
},
|
|||
|
// 空的颜色
|
|||
|
voidColor: {
|
|||
|
type: String,
|
|||
|
default: "#C6D1DE",
|
|||
|
},
|
|||
|
// 图标大小
|
|||
|
size: {
|
|||
|
type: [Number, String],
|
|||
|
default: 40,
|
|||
|
},
|
|||
|
// 最大值
|
|||
|
max: {
|
|||
|
type: Number,
|
|||
|
default: 5,
|
|||
|
},
|
|||
|
// 是否禁用
|
|||
|
disabled: {
|
|||
|
type: Boolean,
|
|||
|
default: null,
|
|||
|
},
|
|||
|
// 显示文本
|
|||
|
showText: {
|
|||
|
type: Boolean,
|
|||
|
default: null,
|
|||
|
},
|
|||
|
// 文本组
|
|||
|
texts: {
|
|||
|
type: Array,
|
|||
|
default: () => [],
|
|||
|
},
|
|||
|
},
|
|||
|
|
|||
|
setup(props, { emit }) {
|
|||
|
const { disabled } = useForm();
|
|||
|
|
|||
|
// 绑定值
|
|||
|
const value = ref(0);
|
|||
|
|
|||
|
watch(
|
|||
|
() => props.modelValue,
|
|||
|
(val) => {
|
|||
|
value.value = Number(val);
|
|||
|
},
|
|||
|
{
|
|||
|
immediate: true,
|
|||
|
},
|
|||
|
);
|
|||
|
|
|||
|
// 文本内容
|
|||
|
const text = computed(() => {
|
|||
|
return isEmpty(props.texts) ? value.value : props.texts[Math.ceil(value.value) - 1];
|
|||
|
});
|
|||
|
|
|||
|
// 列表
|
|||
|
const list = computed(() => {
|
|||
|
return new Array(props.max).fill(1).map((_, i) => {
|
|||
|
const int: number = parseInt(String(value.value));
|
|||
|
const dec: number = value.value - int;
|
|||
|
|
|||
|
// 处理宽度和颜色
|
|||
|
return {
|
|||
|
width: (value.value > i ? (int > i ? 100 : dec * 100) : 0) + "%",
|
|||
|
color: getCurrentColor({
|
|||
|
value: value.value,
|
|||
|
color: props.color,
|
|||
|
max: props.max,
|
|||
|
}),
|
|||
|
};
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
// 点击
|
|||
|
function onTap(index: number) {
|
|||
|
if (disabled.value || props.disabled) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
value.value = index + 1;
|
|||
|
|
|||
|
emit("update:modelValue", value.value);
|
|||
|
emit("change", value.value);
|
|||
|
}
|
|||
|
|
|||
|
return {
|
|||
|
value,
|
|||
|
list,
|
|||
|
text,
|
|||
|
onTap,
|
|||
|
};
|
|||
|
},
|
|||
|
});
|
|||
|
</script>
|