| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- <script setup>
- import { ref, computed, watch } from 'vue'
- import { fetchUserOptions } from '@/api/admin'
- const props = defineProps({
- modelValue: { type: Array, default: () => [] },
- visible: { type: Boolean, default: false },
- title: { type: String, default: '选择审批人' },
- multiple: { type: Boolean, default: true }
- })
- const emit = defineEmits(['update:modelValue', 'update:visible', 'confirm'])
- const keyword = ref('')
- const loading = ref(false)
- const users = ref([])
- const draftIds = ref([])
- const filtered = computed(() => {
- const kw = String(keyword.value || '')
- .trim()
- .toLowerCase()
- if (!kw) return users.value
- return users.value.filter((u) => {
- const blob = `${u.nickName} ${u.userNo} ${u.userId}`.toLowerCase()
- return blob.includes(kw)
- })
- })
- const isChecked = (userId) => draftIds.value.includes(String(userId))
- const loadUsers = async () => {
- loading.value = true
- try {
- users.value = await fetchUserOptions()
- } catch (e) {
- uni.showToast({ title: e.message || '加载用户失败', icon: 'none' })
- users.value = []
- } finally {
- loading.value = false
- }
- }
- watch(
- () => props.visible,
- (v) => {
- if (!v) return
- draftIds.value = (props.modelValue || []).map(String)
- keyword.value = ''
- if (!users.value.length) loadUsers()
- }
- )
- const close = () => emit('update:visible', false)
- const toggle = (userId) => {
- const id = String(userId)
- if (!props.multiple) {
- draftIds.value = [id]
- return
- }
- const i = draftIds.value.indexOf(id)
- if (i >= 0) draftIds.value.splice(i, 1)
- else draftIds.value.push(id)
- }
- const confirm = () => {
- if (!draftIds.value.length) {
- uni.showToast({ title: '请至少选择一位审批人', icon: 'none' })
- return
- }
- emit('update:modelValue', [...draftIds.value])
- emit('confirm', [...draftIds.value])
- close()
- }
- /** 根据已选 ID 解析展示名(父级摘要用) */
- function resolveLabels(ids) {
- const set = new Set((ids || []).map(String))
- return users.value
- .filter((u) => set.has(u.userId))
- .map((u) => u.nickName || u.userNo || u.userId)
- }
- defineExpose({ loadUsers, resolveLabels, users })
- </script>
- <template>
- <view v-if="visible" class="mp-sheet-mask" @click="close">
- <view class="mp-sheet" @click.stop>
- <view class="mp-sheet__head">
- <text class="mp-sheet__cancel" @click="close">取消</text>
- <text class="mp-sheet__title">{{ title }}</text>
- <text class="mp-sheet__ok" @click="confirm">确定</text>
- </view>
- <view class="mp-sheet__search">
- <input
- v-model="keyword"
- class="mp-sheet__search-input"
- placeholder="搜索姓名 / 账号"
- />
- </view>
- <scroll-view scroll-y class="mp-sheet__body">
- <view v-if="loading" class="mp-sheet__hint">加载中…</view>
- <view v-else-if="!filtered.length" class="mp-sheet__hint">暂无用户</view>
- <view
- v-for="u in filtered"
- :key="u.userId"
- class="mp-sheet__row"
- @click="toggle(u.userId)"
- >
- <view class="mp-sheet__check" :class="{ 'mp-sheet__check--on': isChecked(u.userId) }" />
- <view class="mp-sheet__meta">
- <text class="mp-sheet__name">{{ u.nickName || u.userNo || u.userId }}</text>
- <text class="mp-sheet__sub">{{ u.userNo || u.userId }}</text>
- </view>
- </view>
- </scroll-view>
- <view class="mp-sheet__foot">已选 {{ draftIds.length }} 人</view>
- </view>
- </view>
- </template>
|