68 lines
2.0 KiB
Vue
68 lines
2.0 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
|
|
interface ServiceItem {
|
|
id: string
|
|
code: string
|
|
name: string
|
|
}
|
|
|
|
const props = defineProps<{
|
|
services: ServiceItem[]
|
|
modelValue: string[]
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'update:modelValue', value: string[]): void
|
|
}>()
|
|
|
|
const selectedSet = computed(() => new Set(props.modelValue))
|
|
|
|
const toggleService = (id: string, checked: boolean) => {
|
|
const next = new Set(props.modelValue)
|
|
if (checked) next.add(id)
|
|
else next.delete(id)
|
|
emit('update:modelValue', props.services.map(item => item.id).filter(itemId => next.has(itemId)))
|
|
}
|
|
|
|
const clearAll = () => {
|
|
emit('update:modelValue', [])
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="rounded-lg border bg-card p-2.5 shadow-sm">
|
|
<div class="mb-1 flex items-center justify-between gap-2">
|
|
<label class="block text-[11px] font-medium text-foreground leading-none">选择服务</label>
|
|
<button
|
|
type="button"
|
|
class="cursor-pointer h-6 rounded-md border px-2 text-[13px] text-muted-foreground transition hover:bg-accent"
|
|
@click="clearAll"
|
|
>
|
|
清空
|
|
</button>
|
|
</div>
|
|
<div class="rounded-md border p-1.5">
|
|
<div class="flex flex-wrap items-start gap-1">
|
|
<label
|
|
v-for="item in props.services"
|
|
:key="item.id"
|
|
class="inline-flex w-fit max-w-full cursor-pointer items-start gap-1.5 rounded-md border px-2 py-1 text-[11px] leading-4 hover:bg-muted/60"
|
|
>
|
|
<input
|
|
type="checkbox"
|
|
class="mt-0.5"
|
|
:checked="selectedSet.has(item.id)"
|
|
@change="toggleService(item.id, ($event.target as HTMLInputElement).checked)"
|
|
/>
|
|
<span class="text-muted-foreground shrink-0">{{ item.code }}</span>
|
|
<span class="text-foreground break-words">{{ item.name }}</span>
|
|
</label>
|
|
</div>
|
|
<div v-if="props.services.length === 0" class="px-2 py-4 text-center text-xs text-muted-foreground">
|
|
暂无服务
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|