提交
This commit is contained in:
1 parent
8be55c08e9
commit
a903fcf6d4
75 files changed
+9547
-124
No files matched your search
@@ -0,0 +1,122 @@
|
||||
<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>
|
||||
Reference in new issue
Block a user