Files
shanxia2.0/miniprogram/components/mp-approver-picker/mp-approver-picker.vue
T
2026-07-17 21:59:47 +08:00

123 lines
3.5 KiB
Vue

<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>