吉安感知网项目-前端
罗广辉
2026-01-15 30cbd3ba9e87e1fc53fd84aac18e0c36a4de3494
feat: 转换后的user
2 files added
955 ■■■■■ changed files
applications/drone-command/src/views/system/user/FormDiaLog.vue 451 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/system/user/index.vue 504 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/system/user/FormDiaLog.vue
New file
@@ -0,0 +1,451 @@
<template>
    <el-dialog v-model="visible" :title="titleEnum[dialogMode]" :close-on-click-modal="false" width="800px">
        <!-- 查看模式 -->
        <div v-if="readonly" class="view-mode">
            <el-row :gutter="16">
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">登录账号:</span>
                        {{ formData.account }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">用户姓名:</span>
                        {{ formData.realName }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">手机号码:</span>
                        {{ formData.phone }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">电子邮箱:</span>
                        {{ formData.email }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">用户性别:</span>
                        {{ getSexLabel(formData.sex) }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">用户生日:</span>
                        {{ formData.birthday }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">所属角色:</span>
                        {{ formData.roleName }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">所属部门:</span>
                        {{ formData.deptName }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">用户编号:</span>
                        {{ formData.code }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">账号状态:</span>
                        {{ formData.statusName }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">到期时间:</span>
                        {{ formData.expireTime }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">次数限制:</span>
                        {{ formData.maxLoginNum }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">飞行开始时间:</span>
                        {{ formData.flightStartTime }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">飞行结束时间:</span>
                        {{ formData.flightEndTime }}
                    </div>
                </el-col>
            </el-row>
        </div>
        <!-- 编辑/新增模式 -->
        <el-form v-else ref="formRef" :model="formData" :rules="rules" label-width="110px">
            <el-divider content-position="left">基础信息</el-divider>
            <el-row :gutter="16">
                <el-col :span="12">
                    <el-form-item label="登录账号" prop="account">
                        <el-input v-model="formData.account" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12" v-if="dialogMode === 'add'">
                    <el-form-item label="密码" prop="password">
                        <el-input
                            v-model="formData.password"
                            type="password"
                            maxlength="50"
                            placeholder="请输入"
                            clearable
                            show-password
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12" v-if="dialogMode === 'add'">
                    <el-form-item label="确认密码" prop="password2">
                        <el-input
                            v-model="formData.password2"
                            type="password"
                            maxlength="50"
                            placeholder="请输入"
                            clearable
                            show-password
                        />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-divider content-position="left">详细信息</el-divider>
            <el-row :gutter="16">
                <el-col :span="12">
                    <el-form-item label="用户姓名" prop="realName">
                        <el-input v-model="formData.realName" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="手机号码" prop="phone">
                        <el-input v-model="formData.phone" maxlength="20" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="电子邮箱" prop="email">
                        <el-input v-model="formData.email" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="用户性别" prop="sex">
                        <el-select v-model="formData.sex" placeholder="请选择" clearable>
                            <el-option label="男" :value="1" />
                            <el-option label="女" :value="2" />
                            <el-option label="未知" :value="3" />
                        </el-select>
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="用户生日" prop="birthday">
                        <el-date-picker
                            v-model="formData.birthday"
                            type="datetime"
                            placeholder="请选择"
                            format="YYYY-MM-DD HH:mm:ss"
                            value-format="YYYY-MM-DD HH:mm:ss"
                            clearable
                        />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-divider content-position="left">职责信息</el-divider>
            <el-row :gutter="16">
                <el-col :span="12">
                    <el-form-item label="用户编号" prop="code">
                        <el-input v-model="formData.code" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="所属角色" prop="roleId">
                        <el-tree-select
                            v-model="formData.roleId"
                            :data="roleTree"
                            :props="treeProps"
                            node-key="id"
                            check-strictly
                            clearable
                            placeholder="请选择"
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="所属部门" prop="deptId">
                        <el-tree-select
                            v-model="formData.deptId"
                            :data="deptTree"
                            :props="deptTreeSelectProps"
                            node-key="id"
                            check-strictly
                            clearable
                            placeholder="请选择"
                        />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-divider content-position="left">登录限制</el-divider>
            <el-row :gutter="16">
                <el-col :span="12">
                    <el-form-item label="到期时间" prop="expireTime">
                        <el-date-picker
                            v-model="formData.expireTime"
                            type="datetime"
                            placeholder="请选择"
                            format="YYYY-MM-DD HH:mm:ss"
                            value-format="YYYY-MM-DD HH:mm:ss"
                            clearable
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="次数限制" prop="maxLoginNum">
                        <el-input v-model="formData.maxLoginNum" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="飞行开始时间" prop="flightStartTime">
                        <el-time-picker
                            v-model="formData.flightStartTime"
                            placeholder="请选择"
                            format="HH:mm"
                            value-format="HH:mm"
                            clearable
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="飞行结束时间" prop="flightEndTime">
                        <el-time-picker
                            v-model="formData.flightEndTime"
                            placeholder="请选择"
                            format="HH:mm"
                            value-format="HH:mm"
                            clearable
                        />
                    </el-form-item>
                </el-col>
            </el-row>
        </el-form>
        <template #footer>
            <el-button @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
            <el-button v-if="!readonly" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit">
                确定
            </el-button>
        </template>
    </el-dialog>
</template>
<script setup>
import { computed, onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { getUser, add, update } from '@/api/system/user'
import { getDeptTree } from '@/api/system/dept'
import { getRoleTree } from '@/api/system/role'
import func from '@/utils/func'
// 初始化表单
const initForm = () => ({
    account: '',
    password: '',
    password2: '',
    realName: '',
    phone: '',
    email: '',
    sex: null,
    birthday: '',
    code: '',
    roleId: '',
    deptId: '',
    expireTime: '',
    maxLoginNum: '',
    flightStartTime: '',
    flightEndTime: '',
})
const treeProps = {
    label: 'title',
    children: 'children',
}
const deptTreeSelectProps = {
    label: 'name',
    value: 'id',
    children: 'children',
}
const emit = defineEmits(['success'])
const formRef = ref(null)
const formData = ref(initForm())
const visible = defineModel()
const dialogMode = ref('add')
const submitting = ref(false)
const readonly = computed(() => dialogMode.value === 'view')
const titleEnum = ref({ edit: '编辑用户', view: '查看用户', add: '新增用户' })
const roleTree = ref([])
const deptTree = ref([])
// 密码验证
const validatePass = (rule, value, callback) => {
    if (value === '') {
        callback(new Error('请输入密码'))
    } else {
        callback()
    }
}
const validatePass2 = (rule, value, callback) => {
    if (value === '') {
        callback(new Error('请再次输入密码'))
    } else if (value !== formData.value.password) {
        callback(new Error('两次输入密码不一致!'))
    } else {
        callback()
    }
}
const rules = {
    account: [{ required: true, message: '请输入登录账号', trigger: 'blur' }],
    password: [{ required: true, validator: validatePass, trigger: 'blur' }],
    password2: [{ required: true, validator: validatePass2, trigger: 'blur' }],
    realName: [
        { required: true, message: '请输入用户姓名', trigger: 'blur' },
        { min: 2, max: 50, message: '姓名长度在2到50个字符', trigger: 'blur' },
    ],
    roleId: [{ required: true, message: '请选择所属角色', trigger: 'change' }],
    deptId: [{ required: true, message: '请选择所属部门', trigger: 'change' }],
}
// 获取性别标签
function getSexLabel(sex) {
    const map = { 1: '男', 2: '女', 3: '未知' }
    return map[sex] || ''
}
// 获取角色树
async function getRoleTreeData() {
    const res = await getRoleTree('000000')
    roleTree.value = res.data.data
}
// 获取部门树
async function getDeptTreeData() {
    const res = await getDeptTree('000000')
    deptTree.value = res.data.data
}
// 关闭弹框
function handleCancel() {
    visible.value = false
}
// 验证飞行时间
function validateFlightTime() {
    if (formData.value.flightStartTime && formData.value.flightEndTime) {
        const [startHours, startMinutes] = formData.value.flightStartTime.split(':').map(Number)
        const [endHours, endMinutes] = formData.value.flightEndTime.split(':').map(Number)
        const startTotalMinutes = startHours * 60 + startMinutes
        const endTotalMinutes = endHours * 60 + endMinutes
        if (endTotalMinutes < startTotalMinutes) {
            ElMessage.error('飞行结束时间不能小于飞行开始时间')
            return false
        }
    }
    return true
}
// 提交新增/编辑
async function handleSubmit() {
    const isValid = await formRef.value?.validate().catch(() => false)
    if (!isValid) return
    if (!validateFlightTime()) return
    submitting.value = true
    try {
        const submitData = { ...formData.value }
        submitData.roleId = func.toStr(submitData.roleId)
        submitData.name = submitData.realName
        if (dialogMode.value === 'add') {
            await add(submitData)
            ElMessage.success('新增成功')
        } else {
            await update(submitData)
            ElMessage.success('更新成功')
        }
        visible.value = false
        emit('success')
    } finally {
        submitting.value = false
    }
}
// 加载详情
async function loadDetail() {
    if (!formData.value.id) return
    const res = await getUser(formData.value.id)
    const data = res?.data?.data ?? {}
    // 处理 roleId
    if (data.roleId) {
        data.roleId = func.split(data.roleId)[0] || data.roleId
    }
    formData.value = data
}
// 打开弹框
async function open({ mode, row } = {}) {
    dialogMode.value = mode || 'add'
    if (dialogMode.value === 'add') {
        formData.value = initForm()
    } else {
        formData.value = { id: row.id }
        await loadDetail()
    }
}
onMounted(() => {
    getRoleTreeData()
    getDeptTreeData()
})
defineExpose({ open })
</script>
<style scoped lang="scss">
.view-mode {
    .view-item {
        padding: 10px 0;
        .label {
            color: #606266;
            font-weight: 500;
        }
    }
}
:deep(.el-select) {
    width: 100%;
}
:deep(.el-date-editor) {
    width: 100%;
}
:deep(.el-tree-select) {
    width: 100%;
}
</style>
applications/drone-command/src/views/system/user/index.vue
New file
@@ -0,0 +1,504 @@
<template>
    <basic-container>
        <!-- 左侧部门树 -->
        <el-row :gutter="16" class="user-container">
            <el-col :span="4">
                <div class="tree-box">
                    <el-scrollbar>
                        <el-tree
                            :data="deptTree"
                            :props="deptTreeProps"
                            node-key="id"
                            :load="loadDeptTree"
                            lazy
                            @node-click="handleDeptNodeClick"
                        />
                    </el-scrollbar>
                </div>
            </el-col>
            <!-- 右侧列表区 -->
            <el-col :span="20">
                <!-- 搜索表单 -->
                <el-form ref="queryParamsRef" :model="searchParams">
                    <el-row :gutter="16">
                        <el-col :span="5">
                            <el-form-item label="登录账号" prop="account">
                                <el-input v-model="searchParams.account" placeholder="请输入" clearable @clear="handleSearch" />
                            </el-form-item>
                        </el-col>
                        <el-col :span="5">
                            <el-form-item label="用户姓名" prop="realName">
                                <el-input v-model="searchParams.realName" placeholder="请输入" clearable @clear="handleSearch" />
                            </el-form-item>
                        </el-col>
                        <el-col :span="4">
                            <el-form-item>
                                <el-button @click="resetForm">重置</el-button>
                                <el-button type="primary" @click="handleSearch">查询</el-button>
                            </el-form-item>
                        </el-col>
                    </el-row>
                </el-form>
                <!-- 操作按钮 -->
                <div class="btn-group">
                    <el-button v-if="permission.user_add && !auditMode" type="primary" @click="openForm('add')">新增</el-button>
                    <el-button
                        v-if="permission.user_delete && !auditMode"
                        type="danger"
                        :disabled="!selectedIds.length"
                        @click="handleDelete()"
                    >
                        删除
                    </el-button>
                    <el-button
                        v-if="userInfo.role_name?.includes('admin') && auditMode"
                        type="success"
                        :disabled="!selectedIds.length"
                        @click="handleAuditPass"
                    >
                        通过
                    </el-button>
                    <el-button
                        v-if="userInfo.role_name?.includes('admin') && auditMode"
                        type="danger"
                        :disabled="!selectedIds.length"
                        @click="handleAuditRefuse"
                    >
                        拒绝
                    </el-button>
                    <el-button
                        v-if="userInfo.role_name?.includes('admin') && auditMode"
                        type="primary"
                        plain
                        @click="handleAuditBack"
                    >
                        返回
                    </el-button>
                    <el-button
                        v-if="permission.user_role && !auditMode"
                        type="info"
                        plain
                        :disabled="!selectedIds.length"
                        @click="handleGrant"
                    >
                        角色配置
                    </el-button>
                    <el-button
                        v-if="permission.user_reset && !auditMode"
                        type="info"
                        plain
                        :disabled="!selectedIds.length"
                        @click="handleReset"
                    >
                        密码重置
                    </el-button>
                    <el-button
                        v-if="userInfo.role_name?.includes('admin') && !auditMode"
                        type="info"
                        plain
                        :disabled="!selectedIds.length"
                        @click="handleLock"
                    >
                        账号解封
                    </el-button>
                    <el-button
                        v-if="userInfo.role_name?.includes('admin') && !auditMode"
                        type="success"
                        plain
                        @click="handleImport"
                    >
                        导入
                    </el-button>
                    <el-button
                        v-if="userInfo.role_name?.includes('admin') && !auditMode"
                        type="warning"
                        plain
                        @click="handleExport"
                    >
                        导出
                    </el-button>
                </div>
                <!-- 用户列表 -->
                <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="55" />
                    <el-table-column type="index" width="60" label="序号" />
                    <el-table-column prop="account" label="登录账号" />
                    <el-table-column prop="realName" label="用户姓名" />
                    <el-table-column prop="roleName" label="所属角色">
                        <template v-slot="{ row }">
                            <el-tag v-if="row.roleName">{{ row.roleName }}</el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column prop="deptName" label="所属部门">
                        <template v-slot="{ row }">
                            <el-tag v-if="row.deptName">{{ row.deptName }}</el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column prop="phone" label="手机号码" />
                    <el-table-column label="操作" width="180">
                        <template v-slot="{ row }">
                            <el-link v-if="permission.user_view" @click="openForm('view', row)" type="primary">查看</el-link>
                            <el-link v-if="permission.user_edit && !auditMode" @click="openForm('edit', row)" type="warning">
                                编辑
                            </el-link>
                            <el-link v-if="permission.user_delete && !auditMode" @click="handleDelete(row)" type="danger">
                                删除
                            </el-link>
                        </template>
                    </el-table-column>
                </el-table>
                <!-- 分页 -->
                <div>
                    <el-pagination
                        v-model:current-page="searchParams.current"
                        v-model:page-size="searchParams.size"
                        :total="total"
                        @change="getList"
                    />
                </div>
            </el-col>
        </el-row>
        <!-- 用户表单弹框 -->
        <FormDiaLog v-if="dialogVisible" v-model="dialogVisible" ref="dialogRef" @success="getList" />
        <!-- 角色配置弹框 -->
        <el-dialog title="用户角色配置" append-to-body v-model="roleBox" width="345px">
            <el-tree
                :data="roleGrantList"
                show-checkbox
                check-strictly
                default-expand-all
                node-key="id"
                ref="treeRoleRef"
                :default-checked-keys="roleTreeObj"
                :props="roleProps"
            ></el-tree>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="roleBox = false">取 消</el-button>
                    <el-button type="primary" @click="submitRole">确 定</el-button>
                </span>
            </template>
        </el-dialog>
        <!-- 导入弹框 -->
        <el-dialog title="用户数据导入" append-to-body v-model="excelBox" width="555px">
            <el-form :model="excelForm" label-width="100px">
                <el-form-item label="数据覆盖">
                    <el-switch v-model="excelForm.isCovered" :active-value="1" :inactive-value="0" />
                </el-form-item>
                <el-form-item label="模板上传">
                    <el-upload
                        :action="uploadAction"
                        :on-success="handleUploadSuccess"
                        accept=".xls,.xlsx"
                        :show-file-list="false"
                    >
                        <el-button type="primary">点击上传</el-button>
                    </el-upload>
                    <div class="upload-tip">请上传 .xls,.xlsx 标准格式文件</div>
                </el-form-item>
                <el-form-item label="模板下载">
                    <el-button type="primary" @click="handleTemplate">点击下载</el-button>
                </el-form-item>
            </el-form>
        </el-dialog>
    </basic-container>
</template>
<script setup>
import { computed, nextTick, onMounted, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useStore } from 'vuex'
import FormDiaLog from './FormDiaLog.vue'
import { getList as getListApi, remove, grant, resetPassword, unlock, auditPass, auditRefuse } from '@/api/system/user'
import { exportBlob } from '@/api/common'
import { getDeptTree, getDeptLazyTree } from '@/api/system/dept'
import { getRoleTree } from '@/api/system/role'
import website from '@/config/website'
import { getToken } from '@/utils/auth'
import { downloadXls } from '@/utils/util'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import func from '@/utils/func'
const store = useStore()
const userInfo = computed(() => store.getters.userInfo)
const permission = computed(() => store.getters.permission)
// 初始化搜索参数
const initSearchParams = () => ({
    account: '',
    realName: '',
    current: 1,
    size: 10,
})
const searchParams = ref(initSearchParams())
const total = ref(0)
const loading = ref(false)
const list = ref([])
const selectedIds = ref([])
const selectionList = ref([])
const queryParamsRef = ref(null)
const dialogRef = ref(null)
const dialogVisible = ref(false)
const auditMode = ref(false)
const treeDeptId = ref('')
// 部门树
const deptTree = ref([])
const deptTreeProps = {
    label: 'title',
    children: 'children',
    isLeaf: 'leaf',
}
// 角色配置
const roleBox = ref(false)
const roleGrantList = ref([])
const roleTreeObj = ref([])
const treeRoleRef = ref(null)
const roleProps = {
    label: 'title',
    value: 'key',
}
// 导入相关
const excelBox = ref(false)
const excelForm = ref({
    isCovered: 0,
})
const uploadAction = computed(() => `/blade-system/user/import-user?isCovered=${excelForm.value.isCovered}`)
provide('treeDeptId', treeDeptId)
// 加载部门树节点
async function loadDeptTree(node, resolve) {
    const parentId = node.level === 0 ? 0 : node.data.id
    const param = {
        parentId: parentId,
        level: node.level,
    }
    const res = await getDeptLazyTree(param)
    resolve(
        res.data.data.map(item => ({
            ...item,
            leaf: !item.hasChildren,
        }))
    )
}
// 部门节点点击
function handleDeptNodeClick(data) {
    treeDeptId.value = data.id
    searchParams.value.current = 1
    getList()
}
// 获取列表
async function getList() {
    loading.value = true
    try {
        const res = await getListApi(
            searchParams.value.current,
            searchParams.value.size,
            {
                account: searchParams.value.account,
                realName: searchParams.value.realName,
                status: auditMode.value ? 0 : 1,
            },
            treeDeptId.value
        )
        list.value = res?.data?.data?.records ?? []
        total.value = res?.data?.data?.total ?? 0
    } finally {
        loading.value = false
    }
}
// 查询
function handleSearch() {
    searchParams.value.current = 1
    getList()
}
// 重置查询
function resetForm() {
    queryParamsRef.value?.resetFields()
    searchParams.value = initSearchParams()
    treeDeptId.value = ''
    getList()
}
// 删除
async function handleDelete(row) {
    const tips = row ? '该条' : '选中的项'
    await ElMessageBox.confirm(`确认删除${tips}吗?`, '提示', { type: 'warning' })
    const ids = row ? row.id : selectedIds.value.join(',')
    await remove(ids)
    ElMessage.success('删除成功')
    selectedIds.value = []
    getList()
}
// 勾选值设置
function handleSelectionChange(rows) {
    selectionList.value = rows
    selectedIds.value = rows.map(item => item.id)
}
// 角色配置
async function handleGrant() {
    if (selectedIds.value.length === 0) {
        ElMessage.warning('请选择至少一条数据')
        return
    }
    roleTreeObj.value = []
    if (selectionList.value.length === 1) {
        roleTreeObj.value = selectionList.value[0].roleId?.split(',') || []
    }
    const res = await getRoleTree()
    roleGrantList.value = res.data.data
    roleBox.value = true
}
// 提交角色配置
async function submitRole() {
    const roleList = treeRoleRef.value.getCheckedKeys().join(',')
    await grant(selectedIds.value.join(','), roleList)
    roleBox.value = false
    ElMessage.success('操作成功')
    getList()
}
// 密码重置
async function handleReset() {
    if (selectedIds.value.length === 0) {
        ElMessage.warning('请选择至少一条数据')
        return
    }
    await ElMessageBox.confirm('确定将选择账号密码重置为123456?', '提示', { type: 'warning' })
    await resetPassword(selectedIds.value.join(','))
    ElMessage.success('操作成功')
}
// 账号解封
async function handleLock() {
    if (selectedIds.value.length === 0) {
        ElMessage.warning('请选择至少一条数据')
        return
    }
    await ElMessageBox.confirm('确定将选择账号解封?', '提示', { type: 'warning' })
    await unlock(selectedIds.value.join(','))
    ElMessage.success('操作成功')
}
// 审核通过
async function handleAuditPass() {
    if (selectedIds.value.length === 0) {
        ElMessage.warning('请选择至少一条数据')
        return
    }
    await ElMessageBox.confirm('确定将选择数据通过审核?', '提示', { type: 'warning' })
    await auditPass(selectedIds.value.join(','))
    ElMessage.success('操作成功')
    getList()
}
// 审核拒绝
async function handleAuditRefuse() {
    if (selectedIds.value.length === 0) {
        ElMessage.warning('请选择至少一条数据')
        return
    }
    await ElMessageBox.confirm('确定将选择数据拒绝审核?', '提示', { type: 'warning' })
    await auditRefuse(selectedIds.value.join(','))
    ElMessage.success('操作成功')
    getList()
}
// 返回正常模式
function handleAuditBack() {
    auditMode.value = false
    getList()
}
// 导入
function handleImport() {
    excelBox.value = true
}
// 上传成功
function handleUploadSuccess() {
    excelBox.value = false
    getList()
    ElMessage.success('导入成功')
}
// 导出
function handleExport() {
    const account = func.toStr(searchParams.value.account)
    const realName = func.toStr(searchParams.value.realName)
    ElMessageBox.confirm('是否导出用户数据?', '提示', { type: 'warning' }).then(() => {
        NProgress.start()
        exportBlob(
            `/blade-system/user/export-user?${website.tokenHeader}=${getToken()}&account=${account}&realName=${realName}`
        ).then(res => {
            downloadXls(res.data, `用户数据表${new Date().toISOString().slice(0, 10)}.xlsx`)
            NProgress.done()
        })
    })
}
// 下载模板
function handleTemplate() {
    exportBlob(`/blade-system/user/export-template?${website.tokenHeader}=${getToken()}`).then(res => {
        downloadXls(res.data, '用户数据模板.xlsx')
    })
}
// 新增/编辑/查看 弹框
function openForm(mode, row) {
    dialogVisible.value = true
    nextTick(() => {
        dialogRef.value?.open({ mode, row })
    })
}
onMounted(() => {
    getList()
})
</script>
<style scoped lang="scss">
.user-container {
    height: 100%;
}
.tree-box {
    height: 100%;
    padding: 10px;
    border-radius: 5px;
    background-color: #fff;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    :deep(.el-scrollbar) {
        height: 100%;
    }
}
.btn-group {
    margin-bottom: 16px;
}
.upload-tip {
    color: #999;
    font-size: 12px;
    margin-top: 8px;
}
</style>