用户管理
This commit is contained in:
parent
56b01565a7
commit
53d676e179
|
|
@ -16,4 +16,13 @@ export async function getDeptSelectApi(params) {
|
|||
method: 'get',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
||||
// 角色下拉选
|
||||
export async function getRoleSelectApi(params) {
|
||||
return await request({
|
||||
url: '/smartArchives/system/role/select',
|
||||
method: 'get',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ export function addUser(data) {
|
|||
export function updateUser(data) {
|
||||
return request({
|
||||
url: '/smartArchives/system/user',
|
||||
method: 'put',
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,10 +100,22 @@ export function validAlphabets(str) {
|
|||
*/
|
||||
export function validEmail(email) {
|
||||
const reg =
|
||||
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@(([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
return reg.test(email)
|
||||
}
|
||||
|
||||
/**
|
||||
* 中国大陆手机号校验
|
||||
* 规则:可选国家码(+86/0086/86),以 1 开头的 11 位号码,号段 1[3-9]
|
||||
* @param {string|number} mobile
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validMobile(mobile) {
|
||||
const value = String(mobile || '').trim()
|
||||
const reg = /^(?:(?:\+|00)?86)?1[3-9]\d{9}$/
|
||||
return reg.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @returns {Boolean}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
export const formLabel = [
|
||||
{
|
||||
isShow: false, // 是否展示label
|
||||
f_type: 'ipt',
|
||||
f_label: '用户名',
|
||||
f_model: 'nickName',
|
||||
f_max: 32,
|
||||
},
|
||||
{
|
||||
isShow: false, // 是否展示label
|
||||
f_type: 'ipt',
|
||||
f_label: '手机号',
|
||||
f_model: 'phonenumber',
|
||||
f_max: 32,
|
||||
},
|
||||
{
|
||||
isShow: false, // 是否展示label
|
||||
f_type: 'sel',
|
||||
f_label: '角色',
|
||||
f_model: 'roleId',
|
||||
f_selList: [],
|
||||
},
|
||||
]
|
||||
|
||||
export const columnsList = [
|
||||
{ t_props: 'userName', t_label: '用户账号' },
|
||||
{ t_props: 'nickName', t_label: '用户姓名' },
|
||||
{ t_props: 'phonenumberDes', t_label: '手机号' },
|
||||
{ t_slot: 'deptName', t_label: '组织部门' },
|
||||
{ t_slot: 'roleName', t_label: '角色' },
|
||||
]
|
||||
|
|
@ -1,764 +1,168 @@
|
|||
<template>
|
||||
<!-- 用户管理 -->
|
||||
<div class="app-container">
|
||||
<el-row :gutter="20">
|
||||
<!--用户数据-->
|
||||
|
||||
<el-col>
|
||||
<el-form
|
||||
:model="queryParams"
|
||||
ref="queryForm"
|
||||
size="small"
|
||||
:inline="true"
|
||||
v-show="showSearch"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item prop="userName">
|
||||
<el-input
|
||||
v-model="queryParams.userName"
|
||||
placeholder="用户名"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
<TableModel :formLabel="formLabel" :showOperation="true" :showRightTools="true" ref="userTableRef"
|
||||
:columnsList="columnsList" :request-api="listUser">
|
||||
<template #form="{ queryParams }">
|
||||
<el-form-item prop="deptId" style="width: 240px;">
|
||||
<treeselect v-model="queryParams.deptId" :options="treeDataList" placeholder="请选择部门" value-key="id"
|
||||
:disable-branch-nodes="false" noChildrenText="没有数据了" noOptionsText="没有数据了" noResultsText="没有搜索结果"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="phonenumber">
|
||||
<el-input
|
||||
v-model="queryParams.phonenumber"
|
||||
placeholder="手机号"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="status">
|
||||
<el-select
|
||||
clearable
|
||||
placeholder="部门"
|
||||
style="width: 240px"
|
||||
v-model="queryParams.status"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in dict.type.sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="status">
|
||||
<el-select
|
||||
clearable
|
||||
placeholder="角色"
|
||||
style="width: 240px"
|
||||
v-model="queryParams.status"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in dict.type.sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-search"
|
||||
size="mini"
|
||||
@click="handleQuery"
|
||||
>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button
|
||||
icon="el-icon-refresh"
|
||||
size="mini"
|
||||
@click="resetQuery"
|
||||
>
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['system:user:add']"
|
||||
>新增</el-button
|
||||
>
|
||||
</el-col>
|
||||
|
||||
<right-toolbar
|
||||
:showSearch.sync="showSearch"
|
||||
@queryTable="getList"
|
||||
:columns="columns"
|
||||
>
|
||||
</right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table
|
||||
border
|
||||
:data="userList"
|
||||
v-loading="loading"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column
|
||||
type="index"
|
||||
width="50"
|
||||
label="序号"
|
||||
align="center"
|
||||
/>
|
||||
|
||||
<el-table-column
|
||||
label="用户账号"
|
||||
align="center"
|
||||
key="userName"
|
||||
prop="userName"
|
||||
v-if="columns.userName.visible"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="用户姓名"
|
||||
align="center"
|
||||
key="nickName"
|
||||
prop="nickName"
|
||||
v-if="columns.nickName.visible"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="手机号"
|
||||
align="center"
|
||||
key="phonenumber"
|
||||
prop="phonenumber"
|
||||
v-if="columns.phonenumber.visible"
|
||||
width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
label="组织部门"
|
||||
align="center"
|
||||
key="deptName"
|
||||
prop="dept.deptName"
|
||||
v-if="columns.deptName.visible"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="角色"
|
||||
align="center"
|
||||
key="deptName"
|
||||
prop="dept.deptName"
|
||||
v-if="columns.deptName.visible"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
|
||||
<el-table-column label="操作" align="center" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['system:user:edit']"
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
style="color: #f56c6c"
|
||||
@click="handleDelete(scope.row)"
|
||||
v-hasPermi="['system:user:remove']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-key"
|
||||
style="color: #039088"
|
||||
@click="handleResetPwd(scope.row)"
|
||||
v-hasPermi="['system:user:remove']"
|
||||
>
|
||||
重置密码
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 添加或修改用户配置对话框 -->
|
||||
<el-dialog
|
||||
width="50%"
|
||||
:title="title"
|
||||
append-to-body
|
||||
:visible.sync="open"
|
||||
>
|
||||
<el-form
|
||||
ref="form"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户账号" prop="userName">
|
||||
<el-input
|
||||
maxlength="30"
|
||||
show-word-limit
|
||||
v-model="form.userName"
|
||||
placeholder="请输入用户账号"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户姓名" prop="nickName">
|
||||
<el-input
|
||||
maxlength="30"
|
||||
show-word-limit
|
||||
v-model="form.nickName"
|
||||
placeholder="请输入用户姓名"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="手机号码" prop="phonenumber">
|
||||
<el-input
|
||||
maxlength="11"
|
||||
show-word-limit
|
||||
v-model="form.phonenumber"
|
||||
placeholder="请输入手机号码"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属部门" prop="deptId">
|
||||
<treeselect
|
||||
v-model="form.deptId"
|
||||
:options="enabledDeptOptions"
|
||||
:show-count="true"
|
||||
placeholder="请选择所属部门"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="角色" prop="roleId">
|
||||
<el-select
|
||||
v-model="form.roleId"
|
||||
style="width: 100%"
|
||||
placeholder="请选择角色"
|
||||
>
|
||||
<el-option
|
||||
:key="item.roleId"
|
||||
:value="item.roleId"
|
||||
:label="item.roleName"
|
||||
v-for="item in roleOptions"
|
||||
:disabled="item.status == 1"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 用户导入对话框 -->
|
||||
<el-dialog
|
||||
:title="upload.title"
|
||||
:visible.sync="upload.open"
|
||||
width="400px"
|
||||
append-to-body
|
||||
>
|
||||
<el-upload
|
||||
ref="upload"
|
||||
:limit="1"
|
||||
accept=".xlsx, .xls"
|
||||
:headers="upload.headers"
|
||||
:action="upload.url + '?updateSupport=' + upload.updateSupport"
|
||||
:disabled="upload.isUploading"
|
||||
:on-progress="handleFileUploadProgress"
|
||||
:on-success="handleFileSuccess"
|
||||
:auto-upload="false"
|
||||
drag
|
||||
>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text"
|
||||
>将文件拖到此处,或<em>点击上传</em></div
|
||||
>
|
||||
<div class="el-upload__tip text-center" slot="tip">
|
||||
<div class="el-upload__tip" slot="tip">
|
||||
<el-checkbox
|
||||
v-model="upload.updateSupport"
|
||||
/>是否更新已经存在的用户数据
|
||||
</div>
|
||||
<span>仅允许导入xls、xlsx格式文件。</span>
|
||||
<el-link
|
||||
type="primary"
|
||||
:underline="false"
|
||||
style="font-size: 12px; vertical-align: baseline"
|
||||
@click="importTemplate"
|
||||
>下载模板</el-link
|
||||
>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitFileForm"
|
||||
>确 定</el-button
|
||||
>
|
||||
<el-button @click="upload.open = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template slot="btn">
|
||||
<el-button plain size="mini" type="primary" icon="el-icon-plus" v-hasPermi="['system:user:add']"
|
||||
@click="handleAdd">
|
||||
新增
|
||||
</el-button>
|
||||
</template>
|
||||
<template slot="deptName" slot-scope="{ data }">
|
||||
<span>{{ data.dept.deptName || '--' }}</span>
|
||||
</template>
|
||||
<template slot="roleName" slot-scope="{ data }">
|
||||
<span>{{ data.roles[0].roleName || '--'}}</span>
|
||||
</template>
|
||||
<template slot="handle" slot-scope="{ data }">
|
||||
<el-button plain size="mini" type="primary" icon="el-icon-edit" v-hasPermi="['system:user:edit']"
|
||||
@click="handleUpdate(data)">
|
||||
修改
|
||||
</el-button>
|
||||
<el-button plain size="mini" type="danger" icon="el-icon-delete" v-hasPermi="['system:user:remove']"
|
||||
@click="handleDelete(data)">
|
||||
删除
|
||||
</el-button>
|
||||
<el-button plain size="mini" style="color: #039088"
|
||||
@click="handleResetPwd(scope.row)" v-hasPermi="['system:user:remove']">
|
||||
重置密码
|
||||
</el-button>
|
||||
</template>
|
||||
</TableModel>
|
||||
<!-- 新增/编辑 -->
|
||||
<UserForm v-if="isflag" :isAdd="isAdd" :rowData="row" @handleQuery="handleQuery" :title="title"
|
||||
@closeDialog="closeDialog" @showColose="showColose" :dataForm="row" :disabled="loading" :width="600" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TableModel from '@/components/TableModel'
|
||||
import { columnsList, formLabel } from './config'
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
import {
|
||||
listUser,
|
||||
getUser,
|
||||
delUser,
|
||||
addUser,
|
||||
updateUser,
|
||||
resetUserPwd,
|
||||
changeUserStatus,
|
||||
deptTreeSelect,
|
||||
} from '@/api/system/user'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import Treeselect from '@riophae/vue-treeselect'
|
||||
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
|
||||
import { Splitpanes, Pane } from 'splitpanes'
|
||||
import 'splitpanes/dist/splitpanes.css'
|
||||
import { getDeptSelectApi,getRoleSelectApi } from '@/api/select'
|
||||
import UserForm from './profile/userForm'
|
||||
|
||||
|
||||
export default {
|
||||
name: 'User',
|
||||
dicts: ['sys_normal_disable', 'sys_user_sex'],
|
||||
components: { Treeselect, Splitpanes, Pane },
|
||||
name: 'DataClassManage',
|
||||
components: {
|
||||
TableModel,
|
||||
UserForm,
|
||||
Treeselect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 用户表格数据
|
||||
userList: null,
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
// 所有部门树选项
|
||||
deptOptions: undefined,
|
||||
// 过滤掉已禁用部门树选项
|
||||
enabledDeptOptions: undefined,
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 部门名称
|
||||
deptName: undefined,
|
||||
// 默认密码
|
||||
initPassword: undefined,
|
||||
// 日期范围
|
||||
dateRange: [],
|
||||
// 岗位选项
|
||||
postOptions: [],
|
||||
// 角色选项
|
||||
roleOptions: [],
|
||||
// 表单参数
|
||||
form: {},
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'label',
|
||||
},
|
||||
// 用户导入参数
|
||||
upload: {
|
||||
// 是否显示弹出层(用户导入)
|
||||
open: false,
|
||||
// 弹出层标题(用户导入)
|
||||
title: '',
|
||||
// 是否禁用上传
|
||||
isUploading: false,
|
||||
// 是否更新已经存在的用户数据
|
||||
updateSupport: 0,
|
||||
// 设置上传的请求头部
|
||||
headers: { Authorization: 'Bearer ' + getToken() },
|
||||
// 上传的地址
|
||||
url: process.env.VUE_APP_BASE_API + '/system/user/importData',
|
||||
},
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
userName: undefined,
|
||||
phonenumber: undefined,
|
||||
status: undefined,
|
||||
deptId: undefined,
|
||||
},
|
||||
// 列信息
|
||||
columns: {
|
||||
userId: { label: '用户编号', visible: true },
|
||||
userName: { label: '用户名称', visible: true },
|
||||
nickName: { label: '用户昵称', visible: true },
|
||||
deptName: { label: '部门', visible: true },
|
||||
phonenumber: { label: '手机号码', visible: true },
|
||||
status: { label: '状态', visible: true },
|
||||
createTime: { label: '创建时间', visible: true },
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
userName: [
|
||||
{
|
||||
required: true,
|
||||
message: '用户名称不能为空',
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
min: 2,
|
||||
max: 20,
|
||||
message: '用户名称长度必须介于 2 和 20 之间',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
nickName: [
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
message: '用户姓名不能为空',
|
||||
},
|
||||
],
|
||||
deptId: [
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
message: '所属部门不能为空',
|
||||
},
|
||||
],
|
||||
roleId: [
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
message: '角色不能为空',
|
||||
},
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
message: '用户密码不能为空',
|
||||
},
|
||||
|
||||
{
|
||||
trigger: 'blur',
|
||||
pattern:
|
||||
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\d\s]).{8,20}$/,
|
||||
// 正则检验前先将值转为字符串
|
||||
message:
|
||||
'密码需包含大小写字母、数字和特殊字符,长度为8到20个字符',
|
||||
},
|
||||
],
|
||||
|
||||
phonenumber: [
|
||||
{
|
||||
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
|
||||
message: '请输入正确的手机号码',
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
message: '请输入手机号码',
|
||||
},
|
||||
],
|
||||
},
|
||||
formLabel,
|
||||
columnsList,
|
||||
listUser,
|
||||
title: "",
|
||||
isflag: false,
|
||||
isAdd: '',
|
||||
row: {},
|
||||
loading: false,
|
||||
treeDataList:[],
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 根据名称筛选部门树
|
||||
deptName(val) {
|
||||
this.$refs.tree.filter(val)
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
this.getList()
|
||||
this.getDeptTree()
|
||||
this.getConfigKey('sys.user.initPassword').then((response) => {
|
||||
this.initPassword = response.msg
|
||||
})
|
||||
this.initData();
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
/** 查询用户列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(
|
||||
(response) => {
|
||||
this.userList = response.rows
|
||||
this.total = response.total
|
||||
this.loading = false
|
||||
},
|
||||
)
|
||||
},
|
||||
/** 查询部门下拉树结构 */
|
||||
getDeptTree() {
|
||||
deptTreeSelect().then((response) => {
|
||||
this.deptOptions = response.data
|
||||
this.enabledDeptOptions = this.filterDisabledDept(
|
||||
JSON.parse(JSON.stringify(response.data)),
|
||||
)
|
||||
})
|
||||
},
|
||||
// 过滤禁用的部门
|
||||
filterDisabledDept(deptList) {
|
||||
return deptList.filter((dept) => {
|
||||
if (dept.disabled) {
|
||||
return false
|
||||
}
|
||||
if (dept.children && dept.children.length) {
|
||||
dept.children = this.filterDisabledDept(dept.children)
|
||||
}
|
||||
return true
|
||||
})
|
||||
},
|
||||
// 筛选节点
|
||||
filterNode(value, data) {
|
||||
if (!value) return true
|
||||
return data.label.indexOf(value) !== -1
|
||||
},
|
||||
// 节点单击事件
|
||||
handleNodeClick(data) {
|
||||
this.queryParams.deptId = data.id
|
||||
this.handleQuery()
|
||||
},
|
||||
// 用户状态修改
|
||||
handleStatusChange(row) {
|
||||
let text = row.status === '0' ? '启用' : '停用'
|
||||
this.$modal
|
||||
.confirm('确认要"' + text + '""' + row.userName + '"用户吗?')
|
||||
.then(function () {
|
||||
return changeUserStatus(row.userId, row.status)
|
||||
})
|
||||
.then(() => {
|
||||
this.$modal.msgSuccess(text + '成功')
|
||||
})
|
||||
.catch(function () {
|
||||
row.status = row.status === '0' ? '1' : '0'
|
||||
})
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
userId: undefined,
|
||||
deptId: undefined,
|
||||
userName: undefined,
|
||||
nickName: undefined,
|
||||
password: undefined,
|
||||
phonenumber: undefined,
|
||||
email: undefined,
|
||||
sex: undefined,
|
||||
status: '0',
|
||||
remark: undefined,
|
||||
postIds: [],
|
||||
roleId: '',
|
||||
roleIds: [],
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = []
|
||||
this.resetForm('queryForm')
|
||||
this.queryParams.deptId = undefined
|
||||
this.$refs.tree.setCurrentKey(null)
|
||||
this.handleQuery()
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map((item) => item.userId)
|
||||
this.single = selection.length != 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
// 更多操作触发
|
||||
handleCommand(command, row) {
|
||||
switch (command) {
|
||||
case 'handleResetPwd':
|
||||
this.handleResetPwd(row)
|
||||
break
|
||||
case 'handleAuthRole':
|
||||
this.handleAuthRole(row)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
async initData() {
|
||||
await getDeptSelectApi().then(res => {
|
||||
this.treeDataList = this.convertToVueTree(res.data);
|
||||
});
|
||||
const item = this.formLabel.find(item => item.f_model === 'roleId');
|
||||
await getRoleSelectApi().then(res => {
|
||||
console.log(res.data)
|
||||
res.data.forEach(item => {
|
||||
item.label = item.name;
|
||||
item.value = item.id;
|
||||
});
|
||||
this.$set(item, 'f_selList', res.data)
|
||||
});
|
||||
},
|
||||
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
getUser().then((response) => {
|
||||
this.postOptions = response.posts
|
||||
this.roleOptions = response.roles
|
||||
this.open = true
|
||||
this.title = '添加用户'
|
||||
this.form.password = this.initPassword
|
||||
})
|
||||
this.title = "新增";
|
||||
this.isAdd = 'add';
|
||||
this.isflag = true;
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
closeDialog() {
|
||||
this.isflag = false;
|
||||
},
|
||||
showColose() {
|
||||
this.isflag = false;
|
||||
},
|
||||
/** 修改操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
const userId = row.userId || this.ids
|
||||
getUser(userId).then((response) => {
|
||||
this.form = response.data
|
||||
this.postOptions = response.posts
|
||||
this.roleOptions = response.roles
|
||||
this.$set(this.form, 'postIds', response.postIds)
|
||||
this.$set(this.form, 'roleIds', response.roleIds)
|
||||
this.open = true
|
||||
this.title = '修改用户'
|
||||
this.form.password = ''
|
||||
})
|
||||
this.title = "修改";
|
||||
this.isAdd = 'edit';
|
||||
this.row = row;
|
||||
this.isflag = true;
|
||||
},
|
||||
/** 重置密码按钮操作 */
|
||||
handleResetPwd(row) {
|
||||
this.$prompt('请输入"' + row.userName + '"的新密码', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
closeOnClickModal: false,
|
||||
inputPattern:
|
||||
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\d\s]).{8,20}$/,
|
||||
inputErrorMessage:
|
||||
'用户密码长度必须介于 8 和 20 之间,且包含大小写字母、数字和特殊字符',
|
||||
inputValidator: (value) => {
|
||||
if (/<|>|"|'|\||\\/.test(value)) {
|
||||
return '不能包含非法字符:< > " \' \\\ |'
|
||||
}
|
||||
},
|
||||
})
|
||||
.then(({ value }) => {
|
||||
resetUserPwd(row.userId, value).then((response) => {
|
||||
this.$modal.msgSuccess('修改成功,新密码是:' + value)
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
/* 搜索操作 */
|
||||
handleQuery() {
|
||||
this.$refs.userTableRef.getTableList()
|
||||
},
|
||||
/** 分配角色操作 */
|
||||
handleAuthRole: function (row) {
|
||||
const userId = row.userId
|
||||
this.$router.push('/system/user-auth/role/' + userId)
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function () {
|
||||
this.$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.form.roleIds.push(this.form.roleId)
|
||||
if (this.form.userId != undefined) {
|
||||
updateUser(this.form).then((response) => {
|
||||
this.$modal.msgSuccess('修改成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
})
|
||||
/** 删除操作 */
|
||||
handleDelete(row) {
|
||||
this.$modal.confirm(`是否确认删除参数名称为"${row.configName}"的数据项?`).then(() => {
|
||||
// 显示加载遮罩
|
||||
this.$modal.loading("正在删除,请稍候...");
|
||||
deleteAPI({ id: row.id }).then(res => {
|
||||
this.$modal.closeLoading();
|
||||
if (res.code === 200) {
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
this.handleQuery();
|
||||
} else {
|
||||
addUser(this.form).then((response) => {
|
||||
this.$modal.msgSuccess('新增成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
})
|
||||
this.$modal.msgError(res.msg);
|
||||
}
|
||||
}).catch(error => {
|
||||
this.$modal.closeLoading();
|
||||
this.$modal.msgError(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
// 用户取消删除,不需要处理
|
||||
});
|
||||
},
|
||||
// 树数据过滤 - 支持无限层级转换
|
||||
convertToVueTree(data, level = 1) {
|
||||
if (!data || !Array.isArray(data)) {
|
||||
return []
|
||||
}
|
||||
|
||||
return data.map(item => {
|
||||
const node = {
|
||||
id: item.deptId,
|
||||
label: item.deptName,
|
||||
}
|
||||
|
||||
if (item.children && Array.isArray(item.children) && item.children.length > 0) {
|
||||
if (level < 3) {
|
||||
const children = this.convertToVueTree(item.children, level + 1)
|
||||
if (children.length > 0) node.children = children
|
||||
}
|
||||
}
|
||||
|
||||
return node
|
||||
})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const userIds = row.userId || this.ids
|
||||
this.$modal
|
||||
.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?')
|
||||
.then(function () {
|
||||
return delUser(userIds)
|
||||
})
|
||||
.then(() => {
|
||||
this.getList()
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
this.download(
|
||||
'smartArchives/system/user/export',
|
||||
{
|
||||
...this.queryParams,
|
||||
},
|
||||
`user_${new Date().getTime()}.xlsx`,
|
||||
)
|
||||
},
|
||||
/** 导入按钮操作 */
|
||||
handleImport() {
|
||||
this.upload.title = '用户导入'
|
||||
this.upload.open = true
|
||||
},
|
||||
/** 下载模板操作 */
|
||||
importTemplate() {
|
||||
this.download(
|
||||
'system/user/importTemplate',
|
||||
{},
|
||||
`user_template_${new Date().getTime()}.xlsx`,
|
||||
)
|
||||
},
|
||||
// 文件上传中处理
|
||||
handleFileUploadProgress(event, file, fileList) {
|
||||
this.upload.isUploading = true
|
||||
},
|
||||
// 文件上传成功处理
|
||||
handleFileSuccess(response, file, fileList) {
|
||||
this.upload.open = false
|
||||
this.upload.isUploading = false
|
||||
this.$refs.upload.clearFiles()
|
||||
this.$alert(
|
||||
"<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
|
||||
response.msg +
|
||||
'</div>',
|
||||
'导入结果',
|
||||
{ dangerouslyUseHTMLString: true },
|
||||
)
|
||||
this.getList()
|
||||
},
|
||||
// 提交上传文件
|
||||
submitFileForm() {
|
||||
this.$refs.upload.submit()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,764 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="20">
|
||||
<!--用户数据-->
|
||||
|
||||
<el-col>
|
||||
<el-form
|
||||
:model="queryParams"
|
||||
ref="queryForm"
|
||||
size="small"
|
||||
:inline="true"
|
||||
v-show="showSearch"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item prop="userName">
|
||||
<el-input
|
||||
v-model="queryParams.userName"
|
||||
placeholder="用户名"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="phonenumber">
|
||||
<el-input
|
||||
v-model="queryParams.phonenumber"
|
||||
placeholder="手机号"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="status">
|
||||
<el-select
|
||||
clearable
|
||||
placeholder="部门"
|
||||
style="width: 240px"
|
||||
v-model="queryParams.status"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in dict.type.sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="status">
|
||||
<el-select
|
||||
clearable
|
||||
placeholder="角色"
|
||||
style="width: 240px"
|
||||
v-model="queryParams.status"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in dict.type.sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-search"
|
||||
size="mini"
|
||||
@click="handleQuery"
|
||||
>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button
|
||||
icon="el-icon-refresh"
|
||||
size="mini"
|
||||
@click="resetQuery"
|
||||
>
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['system:user:add']"
|
||||
>新增</el-button
|
||||
>
|
||||
</el-col>
|
||||
|
||||
<right-toolbar
|
||||
:showSearch.sync="showSearch"
|
||||
@queryTable="getList"
|
||||
:columns="columns"
|
||||
>
|
||||
</right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table
|
||||
border
|
||||
:data="userList"
|
||||
v-loading="loading"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column
|
||||
type="index"
|
||||
width="50"
|
||||
label="序号"
|
||||
align="center"
|
||||
/>
|
||||
|
||||
<el-table-column
|
||||
label="用户账号"
|
||||
align="center"
|
||||
key="userName"
|
||||
prop="userName"
|
||||
v-if="columns.userName.visible"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="用户姓名"
|
||||
align="center"
|
||||
key="nickName"
|
||||
prop="nickName"
|
||||
v-if="columns.nickName.visible"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="手机号"
|
||||
align="center"
|
||||
key="phonenumber"
|
||||
prop="phonenumber"
|
||||
v-if="columns.phonenumber.visible"
|
||||
width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
label="组织部门"
|
||||
align="center"
|
||||
key="deptName"
|
||||
prop="dept.deptName"
|
||||
v-if="columns.deptName.visible"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="角色"
|
||||
align="center"
|
||||
key="deptName"
|
||||
prop="dept.deptName"
|
||||
v-if="columns.deptName.visible"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
|
||||
<el-table-column label="操作" align="center" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['system:user:edit']"
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
style="color: #f56c6c"
|
||||
@click="handleDelete(scope.row)"
|
||||
v-hasPermi="['system:user:remove']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-key"
|
||||
style="color: #039088"
|
||||
@click="handleResetPwd(scope.row)"
|
||||
v-hasPermi="['system:user:remove']"
|
||||
>
|
||||
重置密码
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 添加或修改用户配置对话框 -->
|
||||
<el-dialog
|
||||
width="50%"
|
||||
:title="title"
|
||||
append-to-body
|
||||
:visible.sync="open"
|
||||
>
|
||||
<el-form
|
||||
ref="form"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户账号" prop="userName">
|
||||
<el-input
|
||||
maxlength="30"
|
||||
show-word-limit
|
||||
v-model="form.userName"
|
||||
placeholder="请输入用户账号"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户姓名" prop="nickName">
|
||||
<el-input
|
||||
maxlength="30"
|
||||
show-word-limit
|
||||
v-model="form.nickName"
|
||||
placeholder="请输入用户姓名"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="手机号码" prop="phonenumber">
|
||||
<el-input
|
||||
maxlength="11"
|
||||
show-word-limit
|
||||
v-model="form.phonenumber"
|
||||
placeholder="请输入手机号码"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属部门" prop="deptId">
|
||||
<treeselect
|
||||
v-model="form.deptId"
|
||||
:options="enabledDeptOptions"
|
||||
:show-count="true"
|
||||
placeholder="请选择所属部门"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="角色" prop="roleId">
|
||||
<el-select
|
||||
v-model="form.roleId"
|
||||
style="width: 100%"
|
||||
placeholder="请选择角色"
|
||||
>
|
||||
<el-option
|
||||
:key="item.roleId"
|
||||
:value="item.roleId"
|
||||
:label="item.roleName"
|
||||
v-for="item in roleOptions"
|
||||
:disabled="item.status == 1"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 用户导入对话框 -->
|
||||
<el-dialog
|
||||
:title="upload.title"
|
||||
:visible.sync="upload.open"
|
||||
width="400px"
|
||||
append-to-body
|
||||
>
|
||||
<el-upload
|
||||
ref="upload"
|
||||
:limit="1"
|
||||
accept=".xlsx, .xls"
|
||||
:headers="upload.headers"
|
||||
:action="upload.url + '?updateSupport=' + upload.updateSupport"
|
||||
:disabled="upload.isUploading"
|
||||
:on-progress="handleFileUploadProgress"
|
||||
:on-success="handleFileSuccess"
|
||||
:auto-upload="false"
|
||||
drag
|
||||
>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text"
|
||||
>将文件拖到此处,或<em>点击上传</em></div
|
||||
>
|
||||
<div class="el-upload__tip text-center" slot="tip">
|
||||
<div class="el-upload__tip" slot="tip">
|
||||
<el-checkbox
|
||||
v-model="upload.updateSupport"
|
||||
/>是否更新已经存在的用户数据
|
||||
</div>
|
||||
<span>仅允许导入xls、xlsx格式文件。</span>
|
||||
<el-link
|
||||
type="primary"
|
||||
:underline="false"
|
||||
style="font-size: 12px; vertical-align: baseline"
|
||||
@click="importTemplate"
|
||||
>下载模板</el-link
|
||||
>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitFileForm"
|
||||
>确 定</el-button
|
||||
>
|
||||
<el-button @click="upload.open = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
listUser,
|
||||
getUser,
|
||||
delUser,
|
||||
addUser,
|
||||
updateUser,
|
||||
resetUserPwd,
|
||||
changeUserStatus,
|
||||
deptTreeSelect,
|
||||
} from '@/api/system/user'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import Treeselect from '@riophae/vue-treeselect'
|
||||
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
|
||||
import { Splitpanes, Pane } from 'splitpanes'
|
||||
import 'splitpanes/dist/splitpanes.css'
|
||||
|
||||
export default {
|
||||
name: 'User',
|
||||
dicts: ['sys_normal_disable', 'sys_user_sex'],
|
||||
components: { Treeselect, Splitpanes, Pane },
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 用户表格数据
|
||||
userList: null,
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
// 所有部门树选项
|
||||
deptOptions: undefined,
|
||||
// 过滤掉已禁用部门树选项
|
||||
enabledDeptOptions: undefined,
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 部门名称
|
||||
deptName: undefined,
|
||||
// 默认密码
|
||||
initPassword: undefined,
|
||||
// 日期范围
|
||||
dateRange: [],
|
||||
// 岗位选项
|
||||
postOptions: [],
|
||||
// 角色选项
|
||||
roleOptions: [],
|
||||
// 表单参数
|
||||
form: {},
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'label',
|
||||
},
|
||||
// 用户导入参数
|
||||
upload: {
|
||||
// 是否显示弹出层(用户导入)
|
||||
open: false,
|
||||
// 弹出层标题(用户导入)
|
||||
title: '',
|
||||
// 是否禁用上传
|
||||
isUploading: false,
|
||||
// 是否更新已经存在的用户数据
|
||||
updateSupport: 0,
|
||||
// 设置上传的请求头部
|
||||
headers: { Authorization: 'Bearer ' + getToken() },
|
||||
// 上传的地址
|
||||
url: process.env.VUE_APP_BASE_API + '/system/user/importData',
|
||||
},
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
userName: undefined,
|
||||
phonenumber: undefined,
|
||||
status: undefined,
|
||||
deptId: undefined,
|
||||
},
|
||||
// 列信息
|
||||
columns: {
|
||||
userId: { label: '用户编号', visible: true },
|
||||
userName: { label: '用户名称', visible: true },
|
||||
nickName: { label: '用户昵称', visible: true },
|
||||
deptName: { label: '部门', visible: true },
|
||||
phonenumber: { label: '手机号码', visible: true },
|
||||
status: { label: '状态', visible: true },
|
||||
createTime: { label: '创建时间', visible: true },
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
userName: [
|
||||
{
|
||||
required: true,
|
||||
message: '用户名称不能为空',
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
min: 2,
|
||||
max: 20,
|
||||
message: '用户名称长度必须介于 2 和 20 之间',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
nickName: [
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
message: '用户姓名不能为空',
|
||||
},
|
||||
],
|
||||
deptId: [
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
message: '所属部门不能为空',
|
||||
},
|
||||
],
|
||||
roleId: [
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
message: '角色不能为空',
|
||||
},
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
message: '用户密码不能为空',
|
||||
},
|
||||
|
||||
{
|
||||
trigger: 'blur',
|
||||
pattern:
|
||||
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\d\s]).{8,20}$/,
|
||||
// 正则检验前先将值转为字符串
|
||||
message:
|
||||
'密码需包含大小写字母、数字和特殊字符,长度为8到20个字符',
|
||||
},
|
||||
],
|
||||
|
||||
phonenumber: [
|
||||
{
|
||||
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
|
||||
message: '请输入正确的手机号码',
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
message: '请输入手机号码',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 根据名称筛选部门树
|
||||
deptName(val) {
|
||||
this.$refs.tree.filter(val)
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.getDeptTree()
|
||||
this.getConfigKey('sys.user.initPassword').then((response) => {
|
||||
this.initPassword = response.msg
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询用户列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(
|
||||
(response) => {
|
||||
this.userList = response.rows
|
||||
this.total = response.total
|
||||
this.loading = false
|
||||
},
|
||||
)
|
||||
},
|
||||
/** 查询部门下拉树结构 */
|
||||
getDeptTree() {
|
||||
deptTreeSelect().then((response) => {
|
||||
this.deptOptions = response.data
|
||||
this.enabledDeptOptions = this.filterDisabledDept(
|
||||
JSON.parse(JSON.stringify(response.data)),
|
||||
)
|
||||
})
|
||||
},
|
||||
// 过滤禁用的部门
|
||||
filterDisabledDept(deptList) {
|
||||
return deptList.filter((dept) => {
|
||||
if (dept.disabled) {
|
||||
return false
|
||||
}
|
||||
if (dept.children && dept.children.length) {
|
||||
dept.children = this.filterDisabledDept(dept.children)
|
||||
}
|
||||
return true
|
||||
})
|
||||
},
|
||||
// 筛选节点
|
||||
filterNode(value, data) {
|
||||
if (!value) return true
|
||||
return data.label.indexOf(value) !== -1
|
||||
},
|
||||
// 节点单击事件
|
||||
handleNodeClick(data) {
|
||||
this.queryParams.deptId = data.id
|
||||
this.handleQuery()
|
||||
},
|
||||
// 用户状态修改
|
||||
handleStatusChange(row) {
|
||||
let text = row.status === '0' ? '启用' : '停用'
|
||||
this.$modal
|
||||
.confirm('确认要"' + text + '""' + row.userName + '"用户吗?')
|
||||
.then(function () {
|
||||
return changeUserStatus(row.userId, row.status)
|
||||
})
|
||||
.then(() => {
|
||||
this.$modal.msgSuccess(text + '成功')
|
||||
})
|
||||
.catch(function () {
|
||||
row.status = row.status === '0' ? '1' : '0'
|
||||
})
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
userId: undefined,
|
||||
deptId: undefined,
|
||||
userName: undefined,
|
||||
nickName: undefined,
|
||||
password: undefined,
|
||||
phonenumber: undefined,
|
||||
email: undefined,
|
||||
sex: undefined,
|
||||
status: '0',
|
||||
remark: undefined,
|
||||
postIds: [],
|
||||
roleId: '',
|
||||
roleIds: [],
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = []
|
||||
this.resetForm('queryForm')
|
||||
this.queryParams.deptId = undefined
|
||||
this.$refs.tree.setCurrentKey(null)
|
||||
this.handleQuery()
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map((item) => item.userId)
|
||||
this.single = selection.length != 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
// 更多操作触发
|
||||
handleCommand(command, row) {
|
||||
switch (command) {
|
||||
case 'handleResetPwd':
|
||||
this.handleResetPwd(row)
|
||||
break
|
||||
case 'handleAuthRole':
|
||||
this.handleAuthRole(row)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
getUser().then((response) => {
|
||||
this.postOptions = response.posts
|
||||
this.roleOptions = response.roles
|
||||
this.open = true
|
||||
this.title = '添加用户'
|
||||
this.form.password = this.initPassword
|
||||
})
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
const userId = row.userId || this.ids
|
||||
getUser(userId).then((response) => {
|
||||
this.form = response.data
|
||||
this.postOptions = response.posts
|
||||
this.roleOptions = response.roles
|
||||
this.$set(this.form, 'postIds', response.postIds)
|
||||
this.$set(this.form, 'roleIds', response.roleIds)
|
||||
this.open = true
|
||||
this.title = '修改用户'
|
||||
this.form.password = ''
|
||||
})
|
||||
},
|
||||
/** 重置密码按钮操作 */
|
||||
handleResetPwd(row) {
|
||||
this.$prompt('请输入"' + row.userName + '"的新密码', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
closeOnClickModal: false,
|
||||
inputPattern:
|
||||
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\d\s]).{8,20}$/,
|
||||
inputErrorMessage:
|
||||
'用户密码长度必须介于 8 和 20 之间,且包含大小写字母、数字和特殊字符',
|
||||
inputValidator: (value) => {
|
||||
if (/<|>|"|'|\||\\/.test(value)) {
|
||||
return '不能包含非法字符:< > " \' \\\ |'
|
||||
}
|
||||
},
|
||||
})
|
||||
.then(({ value }) => {
|
||||
resetUserPwd(row.userId, value).then((response) => {
|
||||
this.$modal.msgSuccess('修改成功,新密码是:' + value)
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
/** 分配角色操作 */
|
||||
handleAuthRole: function (row) {
|
||||
const userId = row.userId
|
||||
this.$router.push('/system/user-auth/role/' + userId)
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm: function () {
|
||||
this.$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.form.roleIds.push(this.form.roleId)
|
||||
if (this.form.userId != undefined) {
|
||||
updateUser(this.form).then((response) => {
|
||||
this.$modal.msgSuccess('修改成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
})
|
||||
} else {
|
||||
addUser(this.form).then((response) => {
|
||||
this.$modal.msgSuccess('新增成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const userIds = row.userId || this.ids
|
||||
this.$modal
|
||||
.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?')
|
||||
.then(function () {
|
||||
return delUser(userIds)
|
||||
})
|
||||
.then(() => {
|
||||
this.getList()
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
this.download(
|
||||
'smartArchives/system/user/export',
|
||||
{
|
||||
...this.queryParams,
|
||||
},
|
||||
`user_${new Date().getTime()}.xlsx`,
|
||||
)
|
||||
},
|
||||
/** 导入按钮操作 */
|
||||
handleImport() {
|
||||
this.upload.title = '用户导入'
|
||||
this.upload.open = true
|
||||
},
|
||||
/** 下载模板操作 */
|
||||
importTemplate() {
|
||||
this.download(
|
||||
'system/user/importTemplate',
|
||||
{},
|
||||
`user_template_${new Date().getTime()}.xlsx`,
|
||||
)
|
||||
},
|
||||
// 文件上传中处理
|
||||
handleFileUploadProgress(event, file, fileList) {
|
||||
this.upload.isUploading = true
|
||||
},
|
||||
// 文件上传成功处理
|
||||
handleFileSuccess(response, file, fileList) {
|
||||
this.upload.open = false
|
||||
this.upload.isUploading = false
|
||||
this.$refs.upload.clearFiles()
|
||||
this.$alert(
|
||||
"<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
|
||||
response.msg +
|
||||
'</div>',
|
||||
'导入结果',
|
||||
{ dangerouslyUseHTMLString: true },
|
||||
)
|
||||
this.getList()
|
||||
},
|
||||
// 提交上传文件
|
||||
submitFileForm() {
|
||||
this.$refs.upload.submit()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,310 @@
|
|||
<template>
|
||||
<!-- 小型弹窗,用于完成,删除,保存等操作 -->
|
||||
<el-dialog class="l-dialog" :class="lDialog" :title="title" :visible.sync="dialogVisible" :showClose="true"
|
||||
:closeOnClickModal="false" @close="handleClose" :append-to-body="true">
|
||||
<div>
|
||||
<el-form :model="form" :rules="rules" ref="ruleForm" label-width="110px">
|
||||
<el-form-item label="用户账号" prop="userName">
|
||||
<el-input v-model="form.userName" placeholder="请输入用户账号" maxlength="32" show-word-limit :disabled="isRead"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户姓名" prop="nickName">
|
||||
<el-input v-model="form.nickName" placeholder="请输入用户账号" maxlength="32" show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号码" prop="phonenumber">
|
||||
<el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属部门" prop="deptId">
|
||||
<treeselect v-model="form.deptId" :options="treeDataList" placeholder="请选择部门" value-key="id"
|
||||
:disable-branch-nodes="true" noChildrenText="没有数据了" noOptionsText="没有数据了"
|
||||
noResultsText="没有搜索结果"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="系统角色" prop="roleId">
|
||||
<el-select v-model="form.roleId" placeholder="请选择系统角色" class="form-item" clearable>
|
||||
<el-option v-for="item in roleOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button class="clear-btn" @click="handleClose" :disabled="disabled">取消</el-button>
|
||||
<el-button type="primary" class="search-btn" :disabled="disabled"
|
||||
@click="submitForm('ruleForm')">确认</el-button>
|
||||
</span>
|
||||
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script>
|
||||
import _ from 'lodash'
|
||||
import {
|
||||
addUser,
|
||||
updateUser,
|
||||
} from '@/api/system/user'
|
||||
import { getDeptSelectApi,getRoleSelectApi } from '@/api/select'
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
import { validMobile } from '@/utils/validate'
|
||||
|
||||
export default {
|
||||
name: "UserForm",
|
||||
props: ["width", "dataForm", "title", "disabled", "isAdd", "rowData"],
|
||||
components: { Treeselect },
|
||||
data() {
|
||||
return {
|
||||
lDialog: this.width > 500 ? "w700" : "w500",
|
||||
dialogVisible: true,
|
||||
isDisabled: true,
|
||||
form: {
|
||||
userName: null,
|
||||
nickName: null,
|
||||
phonenumber:null,
|
||||
deptId:undefined,
|
||||
roleId:undefined
|
||||
},
|
||||
treeDataList: [],
|
||||
checkTreeData: [],
|
||||
loading: null,
|
||||
roleOptions: [],
|
||||
phonenumberDes:null,
|
||||
rules: {
|
||||
userName: [
|
||||
{ required: true, message: '请输入用户账号', trigger: 'blur' }
|
||||
],
|
||||
nickName: [
|
||||
{ required: true, message: '请输入用户姓名', trigger: 'blur' }
|
||||
],
|
||||
phonenumber: [
|
||||
{ required: true, message: '请输入手机号码', trigger: 'blur' },
|
||||
{ validator: (rule, value, callback) => this.validateMobile(rule, value, callback), trigger: 'blur' }
|
||||
],
|
||||
deptId: [
|
||||
{ required: true, message: '请选择所属部门', trigger: 'change' }
|
||||
],
|
||||
roleId: [
|
||||
{ required: true, message: '请选择系统角色', trigger: 'change' }
|
||||
],
|
||||
},
|
||||
errorObj: {
|
||||
userName: '用户账号',
|
||||
nickName: '用户姓名',
|
||||
phonenumber: '手机号码',
|
||||
},
|
||||
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.initFormData();
|
||||
},
|
||||
computed: {
|
||||
isRead(){
|
||||
return this.isAdd === 'edit';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 手机号校验(中国大陆,支持可选国家码)
|
||||
validateMobile(rule, value, callback) {
|
||||
const str = String(value || '').trim()
|
||||
if (!str) return callback()
|
||||
if(!this.phonenumberDes || this.phonenumberDes !== this.form.phonenumber){
|
||||
if (!validMobile(str)) {
|
||||
return callback(new Error('请输入合法的手机号码'))
|
||||
}
|
||||
}
|
||||
|
||||
callback()
|
||||
},
|
||||
/** 初始化表单数据 */
|
||||
async initFormData() {
|
||||
await getRoleSelectApi().then(res => {
|
||||
this.roleOptions = res.data;
|
||||
});
|
||||
await getDeptSelectApi().then(res => {
|
||||
this.treeDataList = this.convertToVueTree(res.data);
|
||||
});
|
||||
|
||||
|
||||
|
||||
if ((this.isAdd === 'edit' || this.isAdd === 'detail') && this.rowData) {
|
||||
// 编辑模式:填充表单数据
|
||||
this.form = {
|
||||
id: this.rowData.id || null,
|
||||
userName: this.rowData.userName || undefined,
|
||||
nickName: this.rowData.nickName || undefined,
|
||||
phonenumber: this.rowData.phonenumberDes || null,
|
||||
deptId: this.rowData.deptId || null,
|
||||
roleId: this.rowData.roles[0].roleId || null,
|
||||
};
|
||||
this.phonenumberDes = this.rowData.phonenumberDes || null;
|
||||
} else {
|
||||
// 新增模式:重置表单
|
||||
this.form = {
|
||||
userName: null,
|
||||
deptId: null,
|
||||
phonenumber: null,
|
||||
deptId: undefined,
|
||||
roleId: undefined,
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
closeDialog() {
|
||||
this.isflag = false;
|
||||
},
|
||||
showColose() {
|
||||
this.isflag = false;
|
||||
},
|
||||
/*关闭弹窗 */
|
||||
handleClose() {
|
||||
this.dialogVisible = false;
|
||||
this.$emit("closeDialog");
|
||||
/* setTimeout(() => {
|
||||
this.dialogVisible = true;
|
||||
}); */
|
||||
},
|
||||
/**确认弹窗 */
|
||||
sureBtnClick() {
|
||||
this.dialogVisible = false;
|
||||
this.$emit("closeDialog");
|
||||
/* setTimeout(() => {
|
||||
this.dialogVisible = true;
|
||||
}); */
|
||||
},
|
||||
/**重置表单*/
|
||||
reset() {
|
||||
this.form = {
|
||||
proId: undefined,
|
||||
deptId: undefined,
|
||||
transferTime: null,
|
||||
transferIssue: null,
|
||||
};
|
||||
this.resetForm("ruleForm");
|
||||
},
|
||||
handleReuslt(res) {
|
||||
this.$modal.msgSuccess(res.msg);
|
||||
this.reset();
|
||||
this.$emit('handleQuery');
|
||||
this.handleClose();
|
||||
},
|
||||
/**验证 */
|
||||
submitForm(formName) {
|
||||
this.$refs[formName].validate(valid => {
|
||||
if (valid) {
|
||||
// 显示遮罩层
|
||||
this.loading = this.$loading({
|
||||
lock: true,
|
||||
text: "数据提交中,请稍候...",
|
||||
background: 'rgba(0,0,0,0.5)',
|
||||
target: this.$el.querySelector('.el-dialog') || document.body
|
||||
})
|
||||
let params = _.cloneDeep(this.form);
|
||||
|
||||
console.log(params);
|
||||
|
||||
if (this.isAdd === 'add') {
|
||||
addUser(params).then(res => {
|
||||
this.loading.close();
|
||||
if (res.code === 200) {
|
||||
this.handleReuslt(res);
|
||||
} else {
|
||||
this.$modal.msgError(res.msg);
|
||||
}
|
||||
}).catch(error => {
|
||||
this.loading.close();
|
||||
this.$modal.msgError(this.errorMsg(error));
|
||||
});
|
||||
} else {
|
||||
updateUser(params).then(res => {
|
||||
this.loading.close();
|
||||
if (res.code === 200) {
|
||||
this.handleReuslt(res);
|
||||
} else {
|
||||
this.$modal.msgError(res.msg);
|
||||
}
|
||||
}).catch(error => {
|
||||
this.loading.close();
|
||||
this.$modal.msgError(this.errorMsg(error));
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// 树数据过滤 - 支持无限层级转换
|
||||
convertToVueTree(data, level = 1) {
|
||||
if (!data || !Array.isArray(data)) {
|
||||
return []
|
||||
}
|
||||
|
||||
return data.map(item => {
|
||||
const node = {
|
||||
id: item.deptId,
|
||||
label: item.deptName,
|
||||
}
|
||||
|
||||
if (item.children && Array.isArray(item.children) && item.children.length > 0) {
|
||||
if (level < 3) {
|
||||
const children = this.convertToVueTree(item.children, level + 1)
|
||||
if (children.length > 0) node.children = children
|
||||
}
|
||||
}
|
||||
|
||||
return node
|
||||
})
|
||||
},
|
||||
findNodeById(nodes, id) {
|
||||
for (const node of nodes) {
|
||||
if (node.id === id) return node;
|
||||
if (node.children) {
|
||||
const found = this.findNodeById(node.children, id);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
errorMsg(error) {
|
||||
const errorMessage = error.message;
|
||||
const errorArr = errorMessage.split(':');
|
||||
const errorObjData = errorArr.length > 1 ? JSON.parse(errorArr[1]) : '';
|
||||
if(errorObjData){
|
||||
return this.errorObj[errorObjData.paramName] + errorArr[0] + ':' + errorObjData.originalValue;
|
||||
}else{
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.w700 ::v-deep .el-dialog {
|
||||
width: 700px;
|
||||
}
|
||||
|
||||
.w500 ::v-deep .el-dialog {
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.w500 ::v-deep .el-dialog__header,
|
||||
.w700 ::v-deep .el-dialog__header {
|
||||
// background: #eeeeee;
|
||||
|
||||
.el-dialog__title {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.yxq .el-range-separator {
|
||||
margin-right: 7px !important;
|
||||
}
|
||||
|
||||
.el-date-editor--daterange.el-input__inner {
|
||||
width: 260px;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.select-style {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue