Files
WAI_Project_UNIX/uni_modules/cool-ui/components/cl-progress/cl-progress.uvue
2025-07-21 16:47:04 +08:00

141 lines
2.4 KiB
Plaintext

<template>
<view class="cl-progress">
<view class="cl-progress__outer" :style="outerStyle">
<view class="cl-progress__inner" :style="innerStyle"></view>
</view>
<slot name="text">
<cl-rolling-number
:model-value="value"
:pt="{
className: 'w-[100rpx] text-center'
}"
unit="%"
v-if="showText"
>
</cl-rolling-number>
</slot>
</view>
</template>
<script lang="ts" setup>
import { computed, getCurrentInstance, onMounted, ref, watch } from "vue";
import { parseRpx } from "@/cool";
defineOptions({
name: "cl-progress"
});
const props = defineProps({
// 数值
value: {
type: Number,
default: 0
},
// 线条宽度
strokeWidth: {
type: Number,
default: 12
},
// 是否显示文本
showText: {
type: Boolean,
default: true
},
// 线条颜色
color: {
type: String,
default: null
},
// 底色
unColor: {
type: String,
default: null
}
});
const { proxy } = getCurrentInstance()!;
// 当前值
const value = ref(0);
// 进度条宽度
const width = ref(0);
// 外层样式
const outerStyle = computed(() => {
const style = new Map<string, string>();
style.set("height", parseRpx(props.strokeWidth));
if (props.unColor != null) {
style.set("backgroundColor", props.unColor!);
}
return style;
});
// 内层样式
const innerStyle = computed(() => {
const style = new Map<string, string>();
style.set("width", `${(value.value / 100) * width.value}px`);
if (props.color != null) {
style.set("backgroundColor", props.color!);
}
return style;
});
// 获取进度条宽度
function getWidth() {
uni.createSelectorQuery()
.in(proxy)
.select(".cl-progress__outer")
.boundingClientRect((node) => {
width.value = (node as NodeInfo).width ?? 0;
})
.exec();
}
onMounted(() => {
watch(
computed(() => props.value),
(val: number) => {
getWidth();
setTimeout(() => {
if (val > 100) {
value.value = 100;
} else if (val < 0) {
value.value = 0;
} else {
value.value = val;
}
}, 10);
},
{
immediate: true
}
);
});
</script>
<style lang="scss" scoped>
.cl-progress {
@apply flex flex-row items-center w-full rounded-md;
&__outer {
@apply bg-surface-100 relative rounded-md;
flex: 1;
}
&__inner {
@apply h-full absolute top-0 left-0 z-10 rounded-md;
@apply bg-primary-500;
transition-property: width;
transition-duration: 0.5s;
}
}
</style>