feat:用户列表完善

This commit is contained in:
fit2cloud-chenyw 2021-03-10 18:26:53 +08:00
parent afec128fc6
commit 1992e84b59
12 changed files with 709 additions and 267 deletions

View File

@ -33,8 +33,17 @@
left join sys_role r on r.role_id = ur.role_id
left join sys_dept d on d.dept_id = u.dept_id
<where>
<if test="request.quick != null and request.name == null">
AND u.nick_name like CONCAT('%', #{request.quick},'%')
</if>
<if test="request.name != null">
AND u.name like CONCAT('%', #{request.name},'%')
AND u.nick_name like CONCAT('%', #{request.name},'%')
</if>
<if test="request.enabled != null">
AND u.enabled = #{request.enabled}
</if>
<if test="request.deptId != null">
AND u.dept_id = #{request.deptId}
</if>
</where>
order by u.update_time desc

View File

@ -1,10 +1,18 @@
package io.dataease.controller.sys.request;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
public class UserGridRequest implements Serializable {
@ApiModelProperty("快速检索")
private String quick;
@ApiModelProperty("名称")
private String name;
@ApiModelProperty("组织")
private String deptId;
@ApiModelProperty("状态")
private String enabled;
}

View File

@ -0,0 +1,95 @@
<template>
<div>
<!-- <el-switch v-model="value" active-text="当前用户" /> -->
<treeselect
v-model="value"
:options="options"
:load-options="loadData"
style="width: 200px"
/>
</div>
</template>
<script>
import { ComplexCondition } from 'fit2cloud-ui/src/components/search-bar/model'
import { getDeptTree } from '@/api/system/dept'
import { LOAD_CHILDREN_OPTIONS, LOAD_ROOT_OPTIONS } from '@riophae/vue-treeselect'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
export default {
components: { Treeselect },
props: {
// eslint-disable-next-line vue/require-default-prop
field: String,
// eslint-disable-next-line vue/require-default-prop
label: String,
// eslint-disable-next-line vue/require-default-prop
defaultOperator: String
// eslint-disable-next-line vue/require-default-prop
// options: Array
// eslint-disable-next-line vue/require-default-prop
// loadData: Function
},
data() {
return {
value: undefined,
operator: 'dept',
operatorLabel: '组织',
options: null
}
},
computed: {
valueLabel() {
return this.value
}
},
// 2
methods: {
init() { //
//
this.value = undefined
},
getCondition() { //
const { field, label, operator, operatorLabel, value, valueLabel } = this
// ComplexCondition
return new ComplexCondition({ field, label, operator, operatorLabel, value, valueLabel })
},
//
loadData({ action, parentNode, callback }) {
if (action === LOAD_ROOT_OPTIONS) {
const _self = this
!this.options && getDeptTree('0').then(res => {
_self.options = res.data.map(node => _self.normalizer(node))
callback()
})
}
if (action === LOAD_CHILDREN_OPTIONS) {
const _self = this
getDeptTree(parentNode.id).then(res => {
parentNode.children = res.data.map(function(obj) {
return _self.normalizer(obj)
})
callback()
})
}
},
normalizer(node) {
if (node.hasChildren) {
node.children = null
}
return {
id: node.deptId,
label: node.name,
children: node.children
}
}
}
}
</script>
<style scoped>
</style>

View File

@ -11,17 +11,22 @@ import zhLocale from './zh'
import twLocale from './tw'
import esLocale from './es'
import jaLocale from './ja'
import fuZh from 'fit2cloud-ui/src/locale/lang/zh-CN' // 加载fit2cloud的内容
import fuEn from 'fit2cloud-ui/src/locale/lang/en_US' // 加载fit2cloud的内容
Vue.use(VueI18n)
const messages = {
en: {
...enLocale,
...elementEnLocale
...elementEnLocale,
...fuEn
},
zh: {
...zhLocale,
...elementZhLocale
...elementZhLocale,
...fuZh
},
tw: {
...twLocale,

View File

@ -424,6 +424,7 @@ export default {
input_email: '请输入邮箱',
input_password: '请输入密码',
input_phone: '请输入电话号码',
input_roles: '请选择角色',
special_characters_are_not_supported: '不支持特殊字符',
mobile_number_format_is_incorrect: '手机号码格式不正确',
email_format_is_incorrect: '邮箱格式不正确',

View File

@ -1,5 +1,6 @@
import Cookies from 'js-cookie'
import Config from '@/settings'
const TokenKey = Config.TokenKey
export function getToken() {
@ -13,3 +14,4 @@ export function setToken(token) {
export function removeToken() {
return Cookies.remove(TokenKey)
}

View File

@ -136,3 +136,17 @@ export function param2Obj(url) {
'"}'
)
}
export function formatCondition(param) {
if (!param) {
return null
}
const condition = {}
for (const key in param) {
if (Object.hasOwnProperty.call(param, key)) {
const element = param[key]
condition[element.field] = element.value
}
}
return condition
}

View File

@ -0,0 +1,9 @@
import store from '@/store'
export function checkPermission(pers) {
const permissions = store.getters.permissions
const hasPermission = pers.every(needP => {
const result = permissions.includes(needP)
return result
})
return hasPermission
}

View File

@ -18,3 +18,5 @@ export function validUsername(str) {
const valid_map = ['admin', 'cyw']
return valid_map.indexOf(str.trim()) >= 0
}
export const PHONE_REGEX = '^1[3|4|5|7|8][0-9]{9}$'

View File

@ -1,62 +1,44 @@
<template>
<div v-loading="$store.getters.loadingMap[$store.getters.currentPath]">
<el-card class="table-card">
<template v-slot:header>
<ms-table-header
:permission="permission"
:condition.sync="condition"
:create-tip="$t('user.create')"
:title="$t('commons.user')"
@search="search"
@create="create"
/>
<layout-content v-loading="$store.getters.loadingMap[$store.getters.currentPath]">
<complex-table
:data="data"
:columns="columns"
:buttons="buttons"
:header="header"
:search-config="searchConfig"
:pagination-config="paginationConfig"
@select="select"
@search="search"
>
<template #buttons>
<fu-table-button icon="el-icon-circle-plus-outline" :label="$t('user.create')" @click="create" />
</template>
<el-table border class="adjust-table" :data="tableData" style="width: 100%">
<el-table-column prop="username" label="ID" />
<el-table-column prop="nickName" :label="$t('commons.name')" width="200" />
<el-table-column prop="gender" label="性别" />
<el-table-column type="selection" fix />
<el-table-column prop="username" label="ID" width="80" />
<el-table-column prop="nickName" :label="$t('commons.name')" width="140" />
<el-table-column prop="gender" label="性别" width="50" />
<el-table-column :show-overflow-tooltip="true" prop="phone" width="100" label="电话" />
<el-table-column :show-overflow-tooltip="true" width="135" prop="email" :label="$t('commons.email')" />
<el-table-column :show-overflow-tooltip="true" prop="dept" :label="$t('commons.organization')">
<template slot-scope="scope">
<div>{{ scope.row.dept.deptName }}</div>
</template>
</el-table-column>
<el-table-column prop="status" :label="$t('commons.status')" width="120">
<template v-slot:default="scope">
<el-switch v-model="scope.row.enabled" :active-value="1" :inactive-value="0" inactive-color="#DCDFE6" @change="changeSwitch(scope.row)" />
</template>
</el-table-column>
<el-table-column prop="createTime" :label="$t('commons.create_time')">
<template v-slot:default="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<el-table-column :show-overflow-tooltip="true" prop="phone" width="200" label="电话" />
<el-table-column :show-overflow-tooltip="true" width="200" prop="email" :label="$t('commons.email')" />
<el-table-column :show-overflow-tooltip="true" prop="dept" :label="$t('commons.organization')">
<template slot-scope="scope">
<div>{{ scope.row.dept.deptName }}</div>
</template>
</el-table-column>
<el-table-column prop="status" :label="$t('commons.status')" width="60">
<template v-slot:default="scope">
<el-switch v-model="scope.row.enabled" :active-value="1" :inactive-value="0" inactive-color="#DCDFE6" @change="changeSwitch(scope.row)" />
</template>
</el-table-column>
<el-table-column prop="createTime" :label="$t('commons.create_time')" width="160">
<template v-slot:default="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<fu-table-operations :buttons="buttons" label="操作" fix />
</complex-table>
<!-- <el-table-column prop="source" :label="$t('user.source')"/> -->
<el-table-column :label="$t('commons.operating')" min-width="120px">
<template v-slot:default="scope">
<ms-table-operator :permission="permission" @editClick="edit(scope.row)" @deleteClick="del(scope.row)">
<template v-slot:behind>
<ms-table-operator-button
v-permission="permission.editPwd"
:tip="$t('member.edit_password')"
icon="el-icon-s-tools"
type="success"
@exec="editPassword(scope.row)"
/>
</template>
</ms-table-operator>
</template>
</el-table-column>
</el-table>
<ms-table-pagination :change="search" :current-page.sync="currentPage" :page-size.sync="pageSize" :total="total" />
</el-card>
<el-dialog
append-to-body
:close-on-click-modal="false"
@ -72,7 +54,7 @@
<el-input v-model="form.username" />
</el-form-item>
<el-form-item label="电话" prop="phone">
<el-input v-model.number="form.phone" />
<el-input v-model="form.phone" />
</el-form-item>
<el-form-item label="昵称" prop="nickName">
<el-input v-model="form.nickName" />
@ -102,11 +84,12 @@
placeholder="选择部门"
/>
</el-form-item>
<el-form-item style="margin-bottom: 0;" label="角色" prop="roles">
<el-form-item style="margin-bottom: 0;" label="角色" prop="roleIds">
<el-select
v-model="form.roleIds"
style="width: 430px"
multiple
required="true"
placeholder="请选择"
@remove-tag="deleteTag"
@change="changeRole"
@ -120,12 +103,10 @@
</el-select>
</el-form-item>
</el-form>
<template v-slot:footer>
<ms-dialog-footer
@cancel="dialogVisible = false"
@confirm="createUser('createUserForm')"
/>
</template>
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="dialogVisible = false">{{ $t('commons.cancel') }}</el-button>
<el-button type="primary" @click="createUser('createUserForm')">确认</el-button>
</div>
</el-dialog>
<!--Changing user password in system settings-->
@ -153,60 +134,76 @@
<el-input v-model="ruleForm.userId" autocomplete="off" :disabled="true" style="display:none" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<ms-dialog-footer
@cancel="editPasswordVisible = false"
@confirm="editUserPassword('editPasswordForm')"
/>
</span>
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="editPasswordVisible = false">{{ $t('commons.cancel') }}</el-button>
<el-button type="primary" @click="editUserPassword('editPasswordForm')">确认</el-button>
</div>
</el-dialog>
</div>
</layout-content>
</template>
<script>
// import MsCreateBox from '@/metersphere/common/components/CreateBox'
import MsTablePagination from '@/metersphere/common/pagination/TablePagination'
import MsTableHeader from '@/metersphere/common/components/MsTableHeader'
import MsTableOperator from '@/metersphere/common/components/MsTableOperator'
import MsDialogFooter from '@/metersphere/common/components/MsDialogFooter'
import MsTableOperatorButton from '@/metersphere/common/components/MsTableOperatorButton'
import { listenGoBack, removeGoBackListener } from '@/metersphere/common/js/utils'
import { PHONE_REGEX } from '@/metersphere/common/js/regex'
import LayoutContent from '@/components/business/LayoutContent'
import ComplexTable from '@/components/business/complex-table'
// import conditionTable from '@/components/business/condition-table'
// import CustomCondition from './CustomCondtion'
// import { GridButton } from '@/components/GridButton'
import { checkPermission } from '@/utils/permission'
import { formatCondition } from '@/utils/index'
import { PHONE_REGEX } from '@/utils/validate'
import { LOAD_CHILDREN_OPTIONS, LOAD_ROOT_OPTIONS } from '@riophae/vue-treeselect'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { userLists, addUser, editUser, delUser, editPassword, editStatus } from '@/api/system/user'
import { allRoles } from '@/api/system/role'
import { getDeptTree } from '@/api/system/dept'
export default {
name: 'MsUser',
components: {
// MsCreateBox,
MsTablePagination,
MsTableHeader,
MsTableOperator,
MsDialogFooter,
MsTableOperatorButton,
Treeselect
},
export default {
components: { ComplexTable, LayoutContent, Treeselect },
data() {
return {
queryPath: '/api/user/userGrid',
deletePath: '/api/user/delete/',
createPath: '/api/user/create',
updatePath: '/api/user/update',
editPasswordPath: '/api/user/password',
result: {},
header: '',
columns: [],
buttons: [
{
label: this.$t('commons.edit'), icon: 'el-icon-edit', click: this.edit
}, {
label: this.$t('commons.delete'), icon: 'el-icon-delete', type: 'danger', click: this.del
}, {
label: this.$t('member.edit_password'), icon: 'el-icon-s-tools', type: 'danger', click: this.editPassword,
show: checkPermission(['user:editPwd'])
}
],
searchConfig: {
quickPlaceholder: '按姓名搜索',
components: [
// { field: 'name', label: '', component: 'FuComplexInput', defaultOperator: 'eq' },
{ field: 'name', label: '姓名', component: 'FuComplexInput' },
{
field: 'enabled',
label: '状态',
component: 'FuComplexSelect',
options: [
{ label: '启用', value: '1' },
{ label: '禁用', value: '0' }
],
multiple: false
}
// { field: 'deptId', label: '', component: conditionTable }
]
},
paginationConfig: {
currentPage: 1,
pageSize: 10,
total: 0
},
data: [],
dialogVisible: false,
editPasswordVisible: false,
multipleSelection: [],
currentPage: 1,
pageSize: 10,
total: 0,
condition: {},
tableData: [],
form: {
roles: [{
id: ''
@ -215,7 +212,7 @@ export default {
checkPasswordForm: {},
ruleForm: {},
rule: {
id: [
username: [
{ required: true, message: this.$t('user.input_id'), trigger: 'blur' },
{ min: 1, max: 50, message: this.$t('commons.input_limit', [1, 50]), trigger: 'blur' },
{
@ -225,7 +222,7 @@ export default {
trigger: 'blur'
}
],
name: [
nickName: [
{ required: true, message: this.$t('user.input_name'), trigger: 'blur' },
{ min: 2, max: 50, message: this.$t('commons.input_limit', [2, 50]), trigger: 'blur' },
{
@ -267,7 +264,9 @@ export default {
message: this.$t('member.password_format_is_incorrect'),
trigger: 'blur'
}
]
],
roleIds: [{ required: true, message: this.$t('user.input_roles'), trigger: 'blur' }]
},
defaultForm: { id: null, username: null, nickName: null, gender: '男', email: null, enabled: 1, deptId: null, phone: null },
depts: null,
@ -283,7 +282,6 @@ export default {
}
}
},
activated() {
// this.form = Object.assign({}, this.defaultForm);
this.allRoles()
@ -291,25 +289,33 @@ export default {
},
methods: {
select(selection) {
console.log(selection)
},
search(condition) {
console.log(condition) // demo
const param = formatCondition(condition)
const { currentPage, pageSize } = this.paginationConfig
userLists(currentPage, pageSize, param || {}).then(response => {
this.data = response.data.listObject
this.paginationConfig.total = response.data.itemCount
})
},
create() {
this.formType = 'add'
this.form = Object.assign({}, this.defaultForm)
this.dialogVisible = true
listenGoBack(this.handleClose)
},
edit(row) {
this.formType = 'modify'
this.dialogVisible = true
this.form = Object.assign({}, row)
listenGoBack(this.handleClose)
},
editPassword(row) {
this.editPasswordVisible = true
const tempForm = Object.assign({}, row)
this.ruleForm = { userId: tempForm.userId }
listenGoBack(this.handleClose)
},
del(row) {
this.$confirm(this.$t('user.delete_confirm'), '', {
@ -354,23 +360,9 @@ export default {
}
})
},
search() {
userLists(this.currentPage, this.pageSize, this.condition).then(response => {
const data = response.data
this.total = data.itemCount
this.tableData = data.listObject
})
// this.result = this.$post(this.buildPagePath(this.queryPath), this.condition, response => {
// const data = response.data
// this.total = data.itemCount
// this.tableData = data.listObject
// })
},
handleClose() {
this.formType = 'add'
this.form = {}
removeGoBackListener(this.handleClose)
this.editPasswordVisible = false
this.dialogVisible = false
},
@ -381,10 +373,6 @@ export default {
this.$success(this.$t('commons.modify_success'))
})
},
handleSelectionChange(val) {
this.multipleSelection = val
},
//
loadDepts({ action, parentNode, callback }) {
if (action === LOAD_ROOT_OPTIONS) {
@ -434,11 +422,10 @@ export default {
this.roles = res.data
})
}
}
}
</script>
<style scoped>
@import "~@/metersphere/common/css/index.css";
</style>

View File

@ -1,134 +0,0 @@
<template>
<layout-content>
<complex-table
:data="data"
:columns="columns"
:buttons="buttons"
:header="header"
:search-config="searchConfig"
:pagination-config="paginationConfig"
@select="select"
@search="search"
>
<template #buttons>
<fu-table-button icon="el-icon-circle-plus-outline" :label="$t('user.create')" @click="add" />
</template>
<el-table-column type="selection" fix />
<el-table-column prop="username" label="ID" />
<el-table-column prop="nickName" :label="$t('commons.name')" width="200" />
<el-table-column prop="gender" label="性别" />
<el-table-column :show-overflow-tooltip="true" prop="phone" width="100" label="电话" />
<el-table-column :show-overflow-tooltip="true" width="135" prop="email" :label="$t('commons.email')" />
<el-table-column :show-overflow-tooltip="true" prop="dept" :label="$t('commons.organization')">
<template slot-scope="scope">
<div>{{ scope.row.dept.deptName }}</div>
</template>
</el-table-column>
<el-table-column prop="status" :label="$t('commons.status')" width="120">
<template v-slot:default="scope">
<el-switch v-model="scope.row.enabled" :active-value="1" :inactive-value="0" inactive-color="#DCDFE6" @change="changeSwitch(scope.row)" />
</template>
</el-table-column>
<el-table-column prop="createTime" :label="$t('commons.create_time')">
<template v-slot:default="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<fu-table-operations :buttons="buttons" label="操作" fix />
</complex-table>
</layout-content>
</template>
<script>
import LayoutContent from '@/components/business/LayoutContent'
import { userLists } from '@/api/system/user'
import ComplexTable from '@/components/business/complex-table'
import CustomCondition from './CustomCondtion'
// import { GridButton } from '@/components/GridButton'
// import { checkPermission } from '@/utils/permisstion'
const buttonClick = function(row) {
console.log(this.label + ': ' + row.id)
}
export default {
name: 'UserManagement',
components: { ComplexTable, LayoutContent },
data() {
return {
header: '',
columns: [],
buttons: [
{
label: '编辑', icon: 'el-icon-edit', click: this.edit
}, {
label: '执行', icon: 'el-icon-video-play', click: buttonClick
}, {
label: '删除', icon: 'el-icon-delete', type: 'danger', click: buttonClick
}, {
label: '删除(权限)', icon: 'el-icon-delete', type: 'danger', click: buttonClick
// show: checkPermission('editor') // editor
}, {
label: '复制', icon: 'el-icon-document-copy', click: buttonClick
}, {
label: '定时任务', icon: 'el-icon-timer', click: buttonClick
}
],
searchConfig: {
quickPlaceholder: '按 姓名/邮箱 搜索',
components: [
{ field: 'name', label: '姓名', component: 'FuComplexInput', defaultOperator: 'eq' },
{ field: 'email', label: 'Email', component: 'FuComplexInput' },
{
field: 'status',
label: '状态',
component: 'FuComplexSelect',
options: [
{ label: '运行中', value: 'Running' },
{ label: '成功', value: 'Success' },
{ label: '失败', value: 'Fail' }
],
multiple: true
},
{ field: 'create_time', label: '创建时间', component: 'FuComplexDateTime' },
{ field: 'user', component: CustomCondition } // CustomCondition
]
},
paginationConfig: {
currentPage: 1,
pageSize: 10,
total: 0
},
data: []
}
},
created() {
this.search()
},
methods: {
select(selection) {
console.log(selection)
},
edit(row) {
console.log('编辑: ', row)
},
add() {
},
search(condition) {
console.log(condition) // demo
const { currentPage, pageSize } = this.paginationConfig
userLists(currentPage, pageSize, {}).then(response => {
this.data = response.data.listObject
this.paginationConfig.total = response.data.itemCount
})
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,444 @@
<template>
<div v-loading="$store.getters.loadingMap[$store.getters.currentPath]">
<el-card class="table-card">
<template v-slot:header>
<ms-table-header
:permission="permission"
:condition.sync="condition"
:create-tip="$t('user.create')"
:title="$t('commons.user')"
@search="search"
@create="create"
/>
</template>
<el-table border class="adjust-table" :data="tableData" style="width: 100%">
<el-table-column prop="username" label="ID" />
<el-table-column prop="nickName" :label="$t('commons.name')" width="200" />
<el-table-column prop="gender" label="性别" />
<el-table-column :show-overflow-tooltip="true" prop="phone" width="100" label="电话" />
<el-table-column :show-overflow-tooltip="true" width="135" prop="email" :label="$t('commons.email')" />
<el-table-column :show-overflow-tooltip="true" prop="dept" :label="$t('commons.organization')">
<template slot-scope="scope">
<div>{{ scope.row.dept.deptName }}</div>
</template>
</el-table-column>
<el-table-column prop="status" :label="$t('commons.status')" width="120">
<template v-slot:default="scope">
<el-switch v-model="scope.row.enabled" :active-value="1" :inactive-value="0" inactive-color="#DCDFE6" @change="changeSwitch(scope.row)" />
</template>
</el-table-column>
<el-table-column prop="createTime" :label="$t('commons.create_time')">
<template v-slot:default="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<!-- <el-table-column prop="source" :label="$t('user.source')"/> -->
<el-table-column :label="$t('commons.operating')" min-width="120px">
<template v-slot:default="scope">
<ms-table-operator :permission="permission" @editClick="edit(scope.row)" @deleteClick="del(scope.row)">
<template v-slot:behind>
<ms-table-operator-button
v-permission="permission.editPwd"
:tip="$t('member.edit_password')"
icon="el-icon-s-tools"
type="success"
@exec="editPassword(scope.row)"
/>
</template>
</ms-table-operator>
</template>
</el-table-column>
</el-table>
<ms-table-pagination :change="search" :current-page.sync="currentPage" :page-size.sync="pageSize" :total="total" />
</el-card>
<el-dialog
append-to-body
:close-on-click-modal="false"
:title="formType=='add' ? $t('user.create') : $t('user.modify')"
:visible.sync="dialogVisible"
width="570px"
:destroy-on-close="true"
@closed="handleClose"
>
<el-form ref="createUserForm" :inline="true" :model="form" :rules="rule" size="small" label-width="66px">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" />
</el-form-item>
<el-form-item label="电话" prop="phone">
<el-input v-model.number="form.phone" />
</el-form-item>
<el-form-item label="昵称" prop="nickName">
<el-input v-model="form.nickName" />
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" />
</el-form-item>
<el-form-item label="性别">
<el-radio-group v-model="form.gender" style="width: 178px">
<el-radio label="男"></el-radio>
<el-radio label="女"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="form.enabled" style="width: 140px">
<el-radio :label="1">启用</el-radio>
<el-radio :label="0">停用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="部门" prop="dept">
<treeselect
v-model="form.deptId"
:options="depts"
:load-options="loadDepts"
style="width: 430px"
placeholder="选择部门"
/>
</el-form-item>
<el-form-item style="margin-bottom: 0;" label="角色" prop="roles">
<el-select
v-model="form.roleIds"
style="width: 430px"
multiple
placeholder="请选择"
@remove-tag="deleteTag"
@change="changeRole"
>
<el-option
v-for="item in roles"
:key="item.name"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-form>
<template v-slot:footer>
<ms-dialog-footer
@cancel="dialogVisible = false"
@confirm="createUser('createUserForm')"
/>
</template>
</el-dialog>
<!--Changing user password in system settings-->
<el-dialog
:close-on-click-modal="false"
:title="$t('member.edit_password')"
:visible.sync="editPasswordVisible"
width="30%"
:destroy-on-close="true"
left
@close="handleClose"
>
<el-form
ref="editPasswordForm"
:model="ruleForm"
label-position="right"
label-width="120px"
:rules="rule"
class="demo-ruleForm"
>
<el-form-item :label="$t('member.new_password')" prop="newpassword">
<el-input v-model="ruleForm.newPassword" type="password" autocomplete="off" show-password />
</el-form-item>
<el-form-item>
<el-input v-model="ruleForm.userId" autocomplete="off" :disabled="true" style="display:none" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<ms-dialog-footer
@cancel="editPasswordVisible = false"
@confirm="editUserPassword('editPasswordForm')"
/>
</span>
</el-dialog>
</div>
</template>
<script>
// import MsCreateBox from '@/metersphere/common/components/CreateBox'
import MsTablePagination from '@/metersphere/common/pagination/TablePagination'
import MsTableHeader from '@/metersphere/common/components/MsTableHeader'
import MsTableOperator from '@/metersphere/common/components/MsTableOperator'
import MsDialogFooter from '@/metersphere/common/components/MsDialogFooter'
import MsTableOperatorButton from '@/metersphere/common/components/MsTableOperatorButton'
import { listenGoBack, removeGoBackListener } from '@/metersphere/common/js/utils'
import { PHONE_REGEX } from '@/metersphere/common/js/regex'
import { LOAD_CHILDREN_OPTIONS, LOAD_ROOT_OPTIONS } from '@riophae/vue-treeselect'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { userLists, addUser, editUser, delUser, editPassword, editStatus } from '@/api/system/user'
import { allRoles } from '@/api/system/role'
import { getDeptTree } from '@/api/system/dept'
export default {
name: 'MsUser',
components: {
// MsCreateBox,
MsTablePagination,
MsTableHeader,
MsTableOperator,
MsDialogFooter,
MsTableOperatorButton,
Treeselect
},
data() {
return {
queryPath: '/api/user/userGrid',
deletePath: '/api/user/delete/',
createPath: '/api/user/create',
updatePath: '/api/user/update',
editPasswordPath: '/api/user/password',
result: {},
dialogVisible: false,
editPasswordVisible: false,
multipleSelection: [],
currentPage: 1,
pageSize: 10,
total: 0,
condition: {},
tableData: [],
form: {
roles: [{
id: ''
}]
},
checkPasswordForm: {},
ruleForm: {},
rule: {
id: [
{ required: true, message: this.$t('user.input_id'), trigger: 'blur' },
{ min: 1, max: 50, message: this.$t('commons.input_limit', [1, 50]), trigger: 'blur' },
{
required: true,
pattern: '^[^\u4e00-\u9fa5]+$',
message: this.$t('user.special_characters_are_not_supported'),
trigger: 'blur'
}
],
name: [
{ required: true, message: this.$t('user.input_name'), trigger: 'blur' },
{ min: 2, max: 50, message: this.$t('commons.input_limit', [2, 50]), trigger: 'blur' },
{
required: true,
message: this.$t('user.special_characters_are_not_supported'),
trigger: 'blur'
}
],
phone: [
{
pattern: PHONE_REGEX,
message: this.$t('user.mobile_number_format_is_incorrect'),
trigger: 'blur'
}
],
email: [
{ required: true, message: this.$t('user.input_email'), trigger: 'blur' },
{
required: true,
pattern: /^[a-zA-Z0-9_._-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/,
message: this.$t('user.email_format_is_incorrect'),
trigger: 'blur'
}
],
password: [
{ required: true, message: this.$t('user.input_password'), trigger: 'blur' },
{
required: true,
pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[^]{8,30}$/,
message: this.$t('member.password_format_is_incorrect'),
trigger: 'blur'
}
],
newPassword: [
{ required: true, message: this.$t('user.input_password'), trigger: 'blur' },
{
required: true,
pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[^]{8,30}$/,
message: this.$t('member.password_format_is_incorrect'),
trigger: 'blur'
}
]
},
defaultForm: { id: null, username: null, nickName: null, gender: '男', email: null, enabled: 1, deptId: null, phone: null },
depts: null,
roles: [],
roleDatas: [],
userRoles: [],
formType: 'add',
permission: {
add: ['user:add'],
edit: ['user:edit'],
del: ['user:del'],
editPwd: ['user:editPwd']
}
}
},
activated() {
// this.form = Object.assign({}, this.defaultForm);
this.allRoles()
this.search()
},
methods: {
create() {
this.formType = 'add'
this.form = Object.assign({}, this.defaultForm)
this.dialogVisible = true
listenGoBack(this.handleClose)
},
edit(row) {
this.formType = 'modify'
this.dialogVisible = true
this.form = Object.assign({}, row)
listenGoBack(this.handleClose)
},
editPassword(row) {
this.editPasswordVisible = true
const tempForm = Object.assign({}, row)
this.ruleForm = { userId: tempForm.userId }
listenGoBack(this.handleClose)
},
del(row) {
this.$confirm(this.$t('user.delete_confirm'), '', {
confirmButtonText: this.$t('commons.confirm'),
cancelButtonText: this.$t('commons.cancel'),
type: 'warning'
}).then(() => {
delUser(encodeURIComponent(row.userId)).then(res => {
this.$success(this.$t('commons.delete_success'))
this.search()
})
}).catch(() => {
this.$info(this.$t('commons.delete_cancel'))
})
},
createUser(createUserForm) {
this.$refs[createUserForm].validate(valid => {
if (valid) {
const method = this.formType === 'add' ? addUser : editUser
method(this.form).then(res => {
this.$success(this.$t('commons.save_success'))
this.search()
this.dialogVisible = false
})
} else {
return false
}
})
},
editUserPassword(editPasswordForm) {
this.$refs[editPasswordForm].validate(valid => {
if (valid) {
editPassword(this.ruleForm).then(res => {
this.$success(this.$t('commons.modify_success'))
this.editPasswordVisible = false
this.search()
window.location.reload()
})
} else {
return false
}
})
},
search() {
userLists(this.currentPage, this.pageSize, this.condition).then(response => {
const data = response.data
this.total = data.itemCount
this.tableData = data.listObject
})
// this.result = this.$post(this.buildPagePath(this.queryPath), this.condition, response => {
// const data = response.data
// this.total = data.itemCount
// this.tableData = data.listObject
// })
},
handleClose() {
this.formType = 'add'
this.form = {}
removeGoBackListener(this.handleClose)
this.editPasswordVisible = false
this.dialogVisible = false
},
changeSwitch(row) {
const { userId, enabled } = row
const param = { userId: userId, enabled: enabled }
editStatus(param).then(res => {
this.$success(this.$t('commons.modify_success'))
})
},
handleSelectionChange(val) {
this.multipleSelection = val
},
//
loadDepts({ action, parentNode, callback }) {
if (action === LOAD_ROOT_OPTIONS) {
const _self = this
!this.depts && getDeptTree('0').then(res => {
_self.depts = res.data.map(node => _self.normalizer(node))
callback()
})
}
if (action === LOAD_CHILDREN_OPTIONS) {
const _self = this
getDeptTree(parentNode.id).then(res => {
parentNode.children = res.data.map(function(obj) {
return _self.normalizer(obj)
})
callback()
})
}
},
normalizer(node) {
if (node.hasChildren) {
node.children = null
}
return {
id: node.deptId,
label: node.name,
children: node.children
}
},
deleteTag(value) {
this.userRoles.forEach(function(data, index) {
if (data.id === value) {
this.userRoles.splice(index, value)
}
}.bind(this))
},
changeRole(value) {
this.userRoles = []
value.forEach(function(data, index) {
const role = { id: data }
this.userRoles.push(role)
}.bind(this))
},
allRoles() {
allRoles().then(res => {
this.roles = res.data
})
}
}
}
</script>
<style scoped>
@import "~@/metersphere/common/css/index.css";
</style>