| | |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div v-show="showSearch" class="mb-[10px]"> |
| | | <el-card shadow="hover"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px"> |
| | | <el-form ref="queryFormRef" :model="queryParams" :inline="true"> |
| | | <el-form-item label="用户名称" prop="userName"> |
| | | <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="手机号码" prop="phonenumber"> |
| | | <el-input |
| | | v-model="queryParams.phonenumber" |
| | | placeholder="请输入手机号码" |
| | | clearable |
| | | style="width: 240px" |
| | | @keyup.enter="handleQuery" |
| | | /> |
| | | <el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="状态" prop="status"> |
| | | <el-select v-model="queryParams.status" placeholder="用户状态" clearable style="width: 240px"> |
| | | <el-select v-model="queryParams.status" placeholder="用户状态" clearable> |
| | | <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="创建时间" style="width: 308px"> |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | value-format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <el-dropdown-item icon="Download" @click="importTemplate">下载模板</el-dropdown-item> |
| | | <el-dropdown-item icon="Top" @click="handleImport"> 导入数据</el-dropdown-item> |
| | | <el-dropdown-item icon="Top" @click="handleImport">导入数据</el-dropdown-item> |
| | | <el-dropdown-item icon="Download" @click="handleExport"> 导出数据</el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </template> |
| | | </el-dropdown> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" :columns="columns" :search="true" @query-table="getList"></right-toolbar> |
| | | <right-toolbar v-model:show-search="showSearch" :columns="columns" :search="true" @query-table="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | |
| | | <el-table-column v-if="columns[0].visible" key="userId" label="用户编号" align="center" prop="userId" /> |
| | | <el-table-column v-if="columns[1].visible" key="userName" label="用户名称" align="center" prop="userName" :show-overflow-tooltip="true" /> |
| | | <el-table-column v-if="columns[2].visible" key="nickName" label="用户昵称" align="center" prop="nickName" :show-overflow-tooltip="true" /> |
| | | <el-table-column |
| | | v-if="columns[3].visible" |
| | | key="deptName" |
| | | label="部门" |
| | | align="center" |
| | | prop="dept.deptName" |
| | | :show-overflow-tooltip="true" |
| | | /> |
| | | <el-table-column v-if="columns[3].visible" key="deptName" label="部门" align="center" prop="deptName" :show-overflow-tooltip="true" /> |
| | | <el-table-column v-if="columns[4].visible" key="phonenumber" label="手机号码" align="center" prop="phonenumber" width="120" /> |
| | | <el-table-column v-if="columns[5].visible" key="status" label="状态" align="center"> |
| | | <template #default="scope"> |
| | |
| | | <el-form-item label="归属部门" prop="deptId"> |
| | | <el-tree-select |
| | | v-model="form.deptId" |
| | | :data="deptOptions" |
| | | :data="enabledDeptOptions" |
| | | :props="{ value: 'id', label: 'label', children: 'children' }" |
| | | value-key="id" |
| | | placeholder="请选择归属部门" |
| | | check-strictly |
| | | @change="handleDeptChange" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="状态"> |
| | | <el-radio-group v-model="form.status"> |
| | | <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio> |
| | | <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="角色"> |
| | | <el-select v-model="form.roleIds" multiple placeholder="请选择"> |
| | | <el-form-item label="角色" prop="roleIds"> |
| | | <el-select v-model="form.roleIds" filterable multiple placeholder="请选择"> |
| | | <el-option |
| | | v-for="item in roleOptions" |
| | | :key="item.roleId" |
| | |
| | | <script setup name="User" lang="ts"> |
| | | import api from '@/api/system/user'; |
| | | import { UserForm, UserQuery, UserVO } from '@/api/system/user/types'; |
| | | import { treeselect } from '@/api/system/dept'; |
| | | import { DeptVO } from '@/api/system/dept/types'; |
| | | import {DeptTreeVO, DeptVO} from '@/api/system/dept/types'; |
| | | import { RoleVO } from '@/api/system/role/types'; |
| | | import { PostVO } from '@/api/system/post/types'; |
| | | import { to } from 'await-to-js'; |
| | | import { PostQuery, PostVO } from '@/api/system/post/types'; |
| | | import { treeselect } from '@/api/system/dept'; |
| | | import { globalHeaders } from '@/utils/request'; |
| | | import { to } from 'await-to-js'; |
| | | import { optionselect } from '@/api/system/post'; |
| | | |
| | | const router = useRouter(); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const { sys_normal_disable, sys_user_sex } = toRefs<any>(proxy?.useDict('sys_normal_disable', 'sys_user_sex')); |
| | | |
| | | const userList = ref<UserVO[]>(); |
| | | const loading = ref(true); |
| | | const showSearch = ref(true); |
| | |
| | | const total = ref(0); |
| | | const dateRange = ref<[DateModelType, DateModelType]>(['', '']); |
| | | const deptName = ref(''); |
| | | const deptOptions = ref<DeptVO[]>([]); |
| | | const deptOptions = ref<DeptTreeVO[]>([]); |
| | | const enabledDeptOptions = ref<DeptTreeVO[]>([]); |
| | | const initPassword = ref<string>(''); |
| | | const postOptions = ref<PostVO[]>([]); |
| | | const roleOptions = ref<RoleVO[]>([]); |
| | |
| | | postIds: [], |
| | | roleIds: [] |
| | | }; |
| | | const data = reactive<PageData<UserForm, UserQuery>>({ |
| | | |
| | | const initData: PageData<UserForm, UserQuery> = { |
| | | form: { ...initFormData }, |
| | | queryParams: { |
| | | pageNum: 1, |
| | |
| | | userName: '', |
| | | phonenumber: '', |
| | | status: '', |
| | | deptId: '' |
| | | deptId: '', |
| | | roleId: '' |
| | | }, |
| | | rules: { |
| | | userName: [ |
| | |
| | | max: 20, |
| | | message: '用户密码长度必须介于 5 和 20 之间', |
| | | trigger: 'blur' |
| | | } |
| | | }, |
| | | { pattern: /^[^<>"'|\\]+$/, message: '不能包含非法字符:< > " \' \\ |', trigger: 'blur' } |
| | | ], |
| | | email: [ |
| | | { |
| | |
| | | message: '请输入正确的手机号码', |
| | | trigger: 'blur' |
| | | } |
| | | ] |
| | | ], |
| | | roleIds: [{ required: true, message: '用户角色不能为空', trigger: 'blur' }] |
| | | } |
| | | }); |
| | | }; |
| | | const data = reactive<PageData<UserForm, UserQuery>>(initData); |
| | | |
| | | const { queryParams, form, rules } = toRefs<PageData<UserForm, UserQuery>>(data); |
| | | |
| | |
| | | } |
| | | ); |
| | | |
| | | /** 查询部门下拉树结构 */ |
| | | const getTreeSelect = async () => { |
| | | const res = await api.deptTreeSelect(); |
| | | deptOptions.value = res.data; |
| | | }; |
| | | |
| | | /** 查询用户列表 */ |
| | | const getList = async () => { |
| | | loading.value = true; |
| | |
| | | loading.value = false; |
| | | userList.value = res.rows; |
| | | total.value = res.total; |
| | | }; |
| | | |
| | | /** 查询部门下拉树结构 */ |
| | | const getDeptTree = async () => { |
| | | const res = await api.deptTreeSelect(); |
| | | deptOptions.value = res.data; |
| | | enabledDeptOptions.value = filterDisabledDept(res.data); |
| | | }; |
| | | |
| | | /** 过滤禁用的部门 */ |
| | | const filterDisabledDept = (deptList: DeptTreeVO[]) => { |
| | | return deptList.filter(dept => { |
| | | if (dept.disabled) { |
| | | return false; |
| | | } |
| | | if (dept.children && dept.children.length) { |
| | | dept.children = filterDisabledDept(dept.children); |
| | | } |
| | | return true; |
| | | }); |
| | | }; |
| | | |
| | | /** 节点单击事件 */ |
| | |
| | | cancelButtonText: '取消', |
| | | closeOnClickModal: false, |
| | | inputPattern: /^.{5,20}$/, |
| | | inputErrorMessage: '用户密码长度必须介于 5 和 20 之间' |
| | | inputErrorMessage: '用户密码长度必须介于 5 和 20 之间', |
| | | inputValidator: (value) => { |
| | | if (/<|>|"|'|\||\\/.test(value)) { |
| | | return '不能包含非法字符:< > " \' \\ |'; |
| | | } |
| | | } |
| | | }) |
| | | ); |
| | | if (!err) { |
| | | if (!err && res) { |
| | | await api.resetUserPwd(row.userId, res.value); |
| | | proxy?.$modal.msgSuccess('修改成功,新密码是:' + res.value); |
| | | } |
| | |
| | | roleOptions.value = data.roles; |
| | | form.value.password = initPassword.value.toString(); |
| | | }; |
| | | |
| | | /** 修改按钮操作 */ |
| | | const handleUpdate = async (row?: UserForm) => { |
| | | reset(); |
| | |
| | | form.value.status = '1'; |
| | | }; |
| | | onMounted(() => { |
| | | getTreeSelect(); // 初始化部门数据 |
| | | getDeptTree(); // 初始化部门数据 |
| | | getList(); // 初始化列表数据 |
| | | proxy?.getConfigKey('sys.user.initPassword').then((response) => { |
| | | initPassword.value = response.data; |
| | | }); |
| | | }); |
| | | |
| | | async function handleDeptChange(value: number | string) { |
| | | const response = await optionselect(value); |
| | | postOptions.value = response.data; |
| | | form.value.postIds = []; |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |