From 30cbd3ba9e87e1fc53fd84aac18e0c36a4de3494 Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Thu, 15 Jan 2026 09:08:28 +0800
Subject: [PATCH] feat: 转换后的user
---
applications/drone-command/src/views/system/user/FormDiaLog.vue | 451 ++++++++++++++++++++++++++++
applications/drone-command/src/views/system/user/index.vue | 504 +++++++++++++++++++++++++++++++
2 files changed, 955 insertions(+), 0 deletions(-)
diff --git a/applications/drone-command/src/views/system/user/FormDiaLog.vue b/applications/drone-command/src/views/system/user/FormDiaLog.vue
new file mode 100644
index 0000000..8aba6fe
--- /dev/null
+++ b/applications/drone-command/src/views/system/user/FormDiaLog.vue
@@ -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>
diff --git a/applications/drone-command/src/views/system/user/index.vue b/applications/drone-command/src/views/system/user/index.vue
new file mode 100644
index 0000000..af2de07
--- /dev/null
+++ b/applications/drone-command/src/views/system/user/index.vue
@@ -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>
--
Gitblit v1.9.3