chore: initialize qiming workspace repository
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<view class="segmented-control">
|
||||
<view
|
||||
v-for="(item, index) in options"
|
||||
:key="index"
|
||||
class="segment-item"
|
||||
:class="{ 'active': selectedIndex === index }"
|
||||
@click="handleSelect(index)"
|
||||
>
|
||||
<text class="segment-text" :class="{ 'active-text': selectedIndex === index }">
|
||||
{{ displayLabel(item.label) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { translateText } from "@/utils/i18n";
|
||||
|
||||
interface SegmentOption {
|
||||
label: string
|
||||
value: string | number
|
||||
}
|
||||
|
||||
interface Props {
|
||||
options: SegmentOption[]
|
||||
modelValue?: string | number
|
||||
defaultIndex?: number
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
defaultIndex: 0
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: string | number]
|
||||
'change': [value: string | number, index: number]
|
||||
}>()
|
||||
|
||||
const selectedIndex = ref<number>(props.defaultIndex)
|
||||
|
||||
// 监听外部传入的 modelValue 变化
|
||||
watch(() => props.modelValue, (newValue) => {
|
||||
if (newValue !== undefined) {
|
||||
const index = props.options.findIndex(option => option.value === newValue)
|
||||
if (index !== -1) {
|
||||
selectedIndex.value = index
|
||||
}
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
const handleSelect = (index: number) => {
|
||||
selectedIndex.value = index
|
||||
const selectedOption = props.options[index]
|
||||
emit('update:modelValue', selectedOption.value)
|
||||
emit('change', selectedOption.value, index)
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一兼容 key 和旧的字面量文案,减少调用方迁移成本。
|
||||
*/
|
||||
const displayLabel = (label: string): string => {
|
||||
return translateText(label)
|
||||
}
|
||||
|
||||
// 初始化时发送默认值
|
||||
onMounted(() => {
|
||||
if (props.modelValue === undefined && props.options.length > 0) {
|
||||
const defaultOption = props.options[props.defaultIndex]
|
||||
emit('update:modelValue', defaultOption.value)
|
||||
emit('change', defaultOption.value, props.defaultIndex)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.segmented-control {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 12rpx;
|
||||
padding: 6rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.segment-item {
|
||||
flex: 1;
|
||||
padding: 16rpx 24rpx;
|
||||
text-align: center;
|
||||
border-radius: 8rpx;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
margin-right: 8rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: #ffffff;
|
||||
z-index: 3;
|
||||
}
|
||||
}
|
||||
|
||||
.segment-text {
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
font-weight: 400;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
line-height: 44rpx;
|
||||
z-index: 4;
|
||||
|
||||
&.active-text {
|
||||
color: #5147FF;
|
||||
font-weight: 600;
|
||||
text-shadow: 0 1rpx 2rpx rgba(81, 71, 255, 0.1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user