Files
shanxia2.0/web-admin/src/components/UserSelector.vue
T
2026-06-30 23:44:22 +08:00

202 lines
5.5 KiB
Vue

<template>
<el-dialog
title="选择用户"
v-model="dialogVisible"
width="900px"
align-center
class="dialog-form-layout"
modal-class="order-module-dialog-mask"
:close-on-click-modal="false"
append-to-body
>
<!-- 查询表单 -->
<el-form :model="queryParams" ref="queryFormRef" :inline="true" class="mb-3 search-form-inline">
<el-form-item label="用户昵称" prop="keyword">
<el-input v-model="queryParams.keyword" placeholder="请输入用户昵称" clearable @keyup.enter="handleQuery" style="width: 180px" />
</el-form-item>
<el-form-item class="form-buttons-right">
<el-button type="primary" :loading="loading" @click="handleQuery">
<el-icon><Search /></el-icon>搜索
</el-button>
<el-button :loading="loading" @click="resetQuery">
<el-icon><Refresh /></el-icon>重置
</el-button>
</el-form-item>
</el-form>
<!-- 用户列表 -->
<el-table v-loading="loading" :data="userList" @current-change="handleCurrentChange" :max-height="400" border highlight-current-row>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column label="用户编号" prop="userNo" width="120" align="center" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" prop="nickName" min-width="150" :show-overflow-tooltip="true" />
<el-table-column label="手机号" prop="phoneNo" width="130" align="center" />
<el-table-column label="所属部门" prop="deptName" width="150" :show-overflow-tooltip="true" />
<el-table-column label="状态" prop="status" width="80" align="center">
<template #default="scope">
<el-tag :type="scope.row.status === '0' ? 'success' : 'danger'" size="small">
{{ scope.row.status === '0' ? '正常' : '停用' }}
</el-tag>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<ListPagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
class="mt-3"
/>
<!-- 当前选中用户 -->
<template v-if="currentUser">
<el-divider content-position="left">当前选中用户</el-divider>
<div class="selected-user">
<el-descriptions :column="3" border>
<el-descriptions-item label="用户昵称">{{ currentUser.nickName }}</el-descriptions-item>
<el-descriptions-item label="用户编号">{{ currentUser.userNo }}</el-descriptions-item>
<el-descriptions-item label="所属部门">{{ currentUser.deptName || '-' }}</el-descriptions-item>
</el-descriptions>
</div>
</template>
<template #footer>
<div class="dialog-footer">
<el-button class="btn-ghost" @click="handleClose">
<el-icon><Close /></el-icon>取消
</el-button>
<el-button class="btn-main" type="primary" @click="handleConfirm" :disabled="!currentUser">
<el-icon><Check /></el-icon>确定
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts" name="UserSelector">
import ListPagination from '@/components/ListPagination/index.vue'
import { Check, Close, Refresh, Search } from '@element-plus/icons-vue'
import { ref, watch } from 'vue'
import type { ElFormInstance } from 'element-plus'
import { fetchUserList } from '@/api/admin'
interface UserItem {
id: string
userNo: string
nickName: string
phoneNo: string
deptName?: string
status: string
}
interface Props {
visible: boolean
}
const props = defineProps<Props>()
const emit = defineEmits(['update:visible', 'confirm'])
const dialogVisible = ref(false)
watch(
() => props.visible,
(val) => {
dialogVisible.value = val
if (val) getList()
}
)
watch(dialogVisible, (val) => {
emit('update:visible', val)
})
const queryParams = ref({
pageNum: 1,
pageSize: 20,
keyword: undefined as string | undefined
})
const userList = ref<UserItem[]>([])
const loading = ref(false)
const total = ref(0)
const currentUser = ref<UserItem | null>(null)
const queryFormRef = ref<ElFormInstance>()
const getList = async () => {
loading.value = true
try {
const res = await fetchUserList({
page: queryParams.value.pageNum,
pageSize: queryParams.value.pageSize,
keyword: queryParams.value.keyword,
status: '0'
})
const data = (res as any)?.data || res || {}
userList.value = data.list || []
total.value = data.total ?? 0
} catch (error) {
console.error('获取用户列表失败:', error)
} finally {
loading.value = false
}
}
const handleQuery = () => {
queryParams.value.pageNum = 1
getList()
}
const resetQuery = () => {
queryFormRef.value?.resetFields()
handleQuery()
}
const handleCurrentChange = (row: UserItem) => {
currentUser.value = row
}
const handleConfirm = () => {
if (currentUser.value) {
// 适配 ContractFormPanel 期望的 { userId, nickName } 结构
emit('confirm', {
userId: currentUser.value.id,
nickName: currentUser.value.nickName,
...currentUser.value
})
}
handleClose()
}
const handleClose = () => {
currentUser.value = null
dialogVisible.value = false
}
</script>
<style scoped>
.selected-user {
padding: 10px;
background-color: #f5f7fa;
border-radius: 4px;
}
.mb-3 {
margin-bottom: 16px;
}
.mt-3 {
margin-top: 16px;
}
.search-form-inline {
display: flex;
flex-wrap: wrap;
}
.form-buttons-right {
margin-left: auto !important;
}
</style>