mirror of
https://github.com/dataease/dataease.git
synced 2026-05-21 04:08:10 +08:00
681 lines
16 KiB
Vue
681 lines
16 KiB
Vue
<template>
|
||
<el-dialog
|
||
v-loading="loading"
|
||
:title="formType == 'add' ? $t('user.create') : $t('user.modify')"
|
||
:visible.sync="dialogVisible"
|
||
class="user-editer-form"
|
||
width="840px"
|
||
:before-close="reset"
|
||
>
|
||
<div
|
||
v-if="formType === 'add'"
|
||
class="editer-form-title"
|
||
>
|
||
<i class="el-icon-info" />
|
||
<span
|
||
class="pwd"
|
||
type="text"
|
||
>{{
|
||
$t("commons.default_pwd") + ":" + defaultPWD
|
||
}}</span>
|
||
<el-button
|
||
v-clipboard:copy="defaultPWD"
|
||
v-clipboard:success="onCopy"
|
||
v-clipboard:error="onError"
|
||
class="btn-text"
|
||
type="text"
|
||
>
|
||
{{ $t("commons.copy") }}
|
||
</el-button>
|
||
</div>
|
||
|
||
<el-form
|
||
ref="createUserForm"
|
||
:model="form"
|
||
:rules="rule"
|
||
size="small"
|
||
label-width="80px"
|
||
label-position="right"
|
||
>
|
||
<el-row :gutter="24">
|
||
<el-col :span="12">
|
||
<el-form-item
|
||
:label="$t('commons.nick_name')"
|
||
prop="nickName"
|
||
>
|
||
<el-input
|
||
v-model="form.nickName"
|
||
:placeholder="$t('user.input_name')"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item
|
||
label="ID"
|
||
prop="username"
|
||
>
|
||
<el-input
|
||
v-model="form.username"
|
||
:placeholder="$t('user.input_id')"
|
||
:disabled="formType !== 'add'"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row :gutter="24">
|
||
<el-col :span="12">
|
||
<el-form-item
|
||
:label="$t('commons.email')"
|
||
prop="email"
|
||
>
|
||
<el-input
|
||
v-model="form.email"
|
||
:placeholder="$t('user.input_email')"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item
|
||
:label="$t('commons.mobile_phone_number')"
|
||
prop="phone"
|
||
>
|
||
<el-input
|
||
v-model="form.phone"
|
||
:placeholder="$t('commons.mobile_phone')"
|
||
class="input-with-select"
|
||
>
|
||
<el-select
|
||
slot="prepend"
|
||
v-model="form.phonePrefix"
|
||
:placeholder="$t('fu.search_bar.please_select')"
|
||
>
|
||
<el-option
|
||
label="+86"
|
||
value="+86"
|
||
/>
|
||
</el-select>
|
||
</el-input>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row :gutter="24">
|
||
<el-col :span="12">
|
||
<el-form-item
|
||
:label="$t('commons.gender')"
|
||
prop="gender"
|
||
>
|
||
<el-select
|
||
v-model="form.gender"
|
||
class="de-form-gender-select"
|
||
:placeholder="$t('user.select_gender')"
|
||
>
|
||
<el-option
|
||
:label="$t('commons.man')"
|
||
value="男"
|
||
/>
|
||
<el-option
|
||
:label="$t('commons.woman')"
|
||
value="女"
|
||
/>
|
||
<el-option
|
||
:label="$t('commons.keep_secret')"
|
||
value="保密"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item
|
||
v-show="isPluginLoaded"
|
||
:label="$t('commons.organization')"
|
||
prop="deptId"
|
||
>
|
||
<el-popover
|
||
placement="bottom"
|
||
popper-class="user-popper dept"
|
||
width="384"
|
||
trigger="click"
|
||
>
|
||
<el-tree
|
||
v-if="dialogVisible"
|
||
:load="loadNode"
|
||
:lazy="true"
|
||
:expand-on-click-node="false"
|
||
:data="depts"
|
||
:props="defaultProps"
|
||
@node-click="handleNodeClick"
|
||
/>
|
||
|
||
<el-select
|
||
slot="reference"
|
||
v-model="form.deptId"
|
||
clearable
|
||
class="de-form-gender-select"
|
||
popper-class="tree-select"
|
||
:placeholder="$t('commons.please_select')"
|
||
>
|
||
<el-option
|
||
v-for="item in selectDepts"
|
||
:key="item.label"
|
||
:label="item.label"
|
||
:value="item.id"
|
||
/>
|
||
</el-select>
|
||
</el-popover>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-form-item
|
||
v-show="isPluginLoaded"
|
||
:label="$t('commons.role')"
|
||
prop="roleIds"
|
||
>
|
||
<el-select
|
||
ref="roleSelect"
|
||
v-model="form.roleIds"
|
||
style="width: 100%"
|
||
:disabled="formType !== 'add' && form.isAdmin"
|
||
multiple
|
||
filterable
|
||
:placeholder="$t('user.input_roles')"
|
||
@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-item
|
||
:label="$t('commons.status')"
|
||
prop="enabled"
|
||
>
|
||
<el-switch
|
||
v-model="form.enabled"
|
||
:disabled="formType !== 'add' && form.isAdmin"
|
||
:active-value="1"
|
||
:inactive-value="0"
|
||
/>
|
||
</el-form-item>
|
||
</el-form>
|
||
<span
|
||
slot="footer"
|
||
class="dialog-footer"
|
||
>
|
||
<deBtn
|
||
secondary
|
||
@click="reset"
|
||
>{{
|
||
$t("commons.cancel")
|
||
}}</deBtn>
|
||
<deBtn
|
||
type="primary"
|
||
@click="save"
|
||
>{{
|
||
$t("commons.confirm")
|
||
}}</deBtn>
|
||
</span>
|
||
</el-dialog>
|
||
</template>
|
||
|
||
<script>
|
||
import { getDeptTree, treeByDeptId } from '@/api/system/dept'
|
||
import { addUser, editUser, allRoles, queryAssist } from '@/api/system/user'
|
||
import { pluginLoaded, defaultPwd, wecomStatus, dingtalkStatus, larkStatus } from '@/api/user'
|
||
export default {
|
||
data() {
|
||
return {
|
||
loading: false,
|
||
defaultProps: {
|
||
children: 'children',
|
||
label: 'label',
|
||
isLeaf: 'leaf'
|
||
},
|
||
selectDepts: [],
|
||
form: {
|
||
roles: [
|
||
{
|
||
id: ''
|
||
}
|
||
],
|
||
sysUserAssist: {
|
||
wecomId: null,
|
||
dingtalkId: null,
|
||
larkId: null
|
||
}
|
||
},
|
||
rule: {
|
||
username: [
|
||
{
|
||
required: true,
|
||
message: this.$t('user.id_mandatory'),
|
||
trigger: 'blur'
|
||
},
|
||
{
|
||
min: 1,
|
||
max: 50,
|
||
message: this.$t('commons.input_limit', [1, 50]),
|
||
trigger: 'blur'
|
||
},
|
||
{ required: true, validator: this.validateUsername, trigger: 'blur' }
|
||
],
|
||
nickName: [
|
||
{
|
||
required: true,
|
||
message: this.$t('user.name_mandatory'),
|
||
trigger: 'blur'
|
||
},
|
||
{
|
||
min: 2,
|
||
max: 50,
|
||
message: this.$t('commons.input_limit', [2, 50]),
|
||
trigger: 'blur'
|
||
},
|
||
{ required: true, validator: this.validateNickname, trigger: 'blur' }
|
||
|
||
],
|
||
phone: [
|
||
{
|
||
validator: this.phoneRegex,
|
||
message: this.$t('user.phone_format'),
|
||
trigger: 'blur'
|
||
}
|
||
],
|
||
email: [
|
||
{
|
||
required: true,
|
||
message: this.$t('user.email_mandatory'),
|
||
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'
|
||
}
|
||
],
|
||
confirmPassword: [
|
||
{
|
||
required: true,
|
||
message: this.$t('user.input_password'),
|
||
trigger: 'blur'
|
||
},
|
||
{ required: true, validator: this.repeatValidator, 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'
|
||
}
|
||
],
|
||
deptId: [],
|
||
gender: [],
|
||
enabled: [{ required: true, trigger: 'change' }]
|
||
},
|
||
defaultForm: {
|
||
id: null,
|
||
username: null,
|
||
nickName: null,
|
||
gender: '男',
|
||
email: null,
|
||
enabled: 1,
|
||
deptId: null,
|
||
phone: null,
|
||
phonePrefix: '+86',
|
||
roleIds: [2],
|
||
sysUserAssist: {
|
||
wecomId: null,
|
||
dingtalkId: null,
|
||
larkId: null
|
||
}
|
||
},
|
||
depts: [],
|
||
roles: [],
|
||
roleData: [],
|
||
userRoles: [],
|
||
formType: 'add',
|
||
isPluginLoaded: false,
|
||
defaultPWD: 'DataEase123..',
|
||
dialogVisible: false,
|
||
wecomOpen: false,
|
||
dingTalkOpen: false,
|
||
larkOpen: false,
|
||
assistInfo: {}
|
||
}
|
||
},
|
||
beforeCreate() {
|
||
pluginLoaded().then((res) => {
|
||
this.isPluginLoaded = res.success && res.data
|
||
})
|
||
wecomStatus().then(res => {
|
||
if (res.success && res.data) {
|
||
this.wecomOpen = true
|
||
}
|
||
})
|
||
|
||
dingtalkStatus().then(res => {
|
||
if (res.success && res.data) {
|
||
this.dingTalkOpen = true
|
||
}
|
||
})
|
||
|
||
larkStatus().then(res => {
|
||
if (res.success && res.data) {
|
||
this.larkOpen = true
|
||
}
|
||
})
|
||
defaultPwd().then((res) => {
|
||
if (res && res.data) {
|
||
this.defaultPWD = res.data
|
||
}
|
||
})
|
||
},
|
||
methods: {
|
||
repeatValidator(rule, value, callback) {
|
||
if (value !== this.form.password) {
|
||
callback(new Error(this.$t('member.inconsistent_passwords')))
|
||
} else {
|
||
callback()
|
||
}
|
||
},
|
||
validateNickname(rule, value, callback) {
|
||
const pattern = "[\\u00A0\\s\"`~!@#$%^&*()+=|{}':;',\\[\\]<>/?~!@#¥%……&*()——+|{}【】‘;:”“'。,、?]"
|
||
const regep = new RegExp(pattern)
|
||
|
||
if (regep.test(value)) {
|
||
const msg = this.$t('user.special_characters_are_not_supported')
|
||
callback(new Error(msg))
|
||
} else {
|
||
callback()
|
||
}
|
||
},
|
||
phoneRegex(rule, value, callback) {
|
||
if (!value || !`${value}`.trim()) {
|
||
callback()
|
||
return
|
||
}
|
||
const regep = new RegExp(/^1[3-9]\d{9}$/)
|
||
|
||
if (!regep.test(value)) {
|
||
const msg = this.$t('user.phone_format')
|
||
callback(new Error(msg))
|
||
} else {
|
||
callback()
|
||
}
|
||
},
|
||
validateUsername(rule, value, callback) {
|
||
const pattern = '^[a-zA-Z][a-zA-Z0-9\._-]*$'
|
||
const regep = new RegExp(pattern)
|
||
if (!regep.test(value) && this.formType === 'add') {
|
||
const msg = this.$t('user.user_name_pattern_error')
|
||
callback(new Error(msg))
|
||
} else {
|
||
callback()
|
||
}
|
||
},
|
||
create() {
|
||
this.formType = 'add'
|
||
this.form = Object.assign({}, JSON.parse(JSON.stringify(this.defaultForm)))
|
||
},
|
||
init(row) {
|
||
this.initRoles()
|
||
|
||
this.dialogVisible = true
|
||
if (!row) {
|
||
this.create()
|
||
return
|
||
}
|
||
this.initAssistInfo(row.userId).then(res => {
|
||
this.assistInfo = res.data
|
||
const { deptId: id, deptName: label } = (row.dept || {})
|
||
this.selectDepts = [{ id, label }]
|
||
this.formType = 'modify'
|
||
this.dialogVisible = true
|
||
row.sysUserAssist = JSON.parse(JSON.stringify(this.defaultForm.sysUserAssist))
|
||
this.form = Object.assign({}, row)
|
||
this.form.password = ''
|
||
if (this.form.deptId === 0) {
|
||
this.form.deptId = null
|
||
}
|
||
|
||
if (!this.form.phonePrefix) {
|
||
this.form.phonePrefix = '+86'
|
||
}
|
||
|
||
if (this.assistInfo) {
|
||
const info = JSON.parse(JSON.stringify(this.assistInfo))
|
||
delete info.needFirstNoti
|
||
delete info.userId
|
||
const assist = Object.assign(JSON.parse(JSON.stringify(this.defaultForm.sysUserAssist)), info)
|
||
this.form.sysUserAssist = assist
|
||
}
|
||
})
|
||
},
|
||
initRoles() {
|
||
allRoles().then((res) => {
|
||
this.roles = res.data
|
||
})
|
||
},
|
||
initAssistInfo(userId) {
|
||
return queryAssist(userId)
|
||
},
|
||
handleNodeClick({ id, label }) {
|
||
const [dept] = this.selectDepts
|
||
if (!dept || dept.id !== id) {
|
||
this.selectDepts = [{ id, label }]
|
||
this.form.deptId = id
|
||
return
|
||
}
|
||
|
||
if (dept.id === id) {
|
||
this.selectDepts = []
|
||
this.form.deptId = null
|
||
}
|
||
},
|
||
// 获取弹窗内部门数据
|
||
treeByDeptId() {
|
||
treeByDeptId(0).then((res) => {
|
||
this.depts = (res.data || []).map(ele => {
|
||
return {
|
||
...ele,
|
||
leaf: !ele.hasChildren
|
||
}
|
||
})
|
||
})
|
||
},
|
||
loadNode(node, resolve) {
|
||
if (!this.depts.length) {
|
||
this.treeByDeptId()
|
||
return
|
||
}
|
||
getDeptTree(node.data.id).then((res) => {
|
||
resolve(
|
||
res.data.map((dept) => {
|
||
return this.normalizer(dept)
|
||
})
|
||
)
|
||
})
|
||
},
|
||
normalizer(node) {
|
||
return {
|
||
id: node.deptId,
|
||
label: node.name,
|
||
leaf: !node.hasChildren
|
||
}
|
||
},
|
||
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)
|
||
)
|
||
},
|
||
reset() {
|
||
this.depts = []
|
||
this.form.sysUserAssist = JSON.parse(JSON.stringify(this.defaultForm.sysUserAssist))
|
||
this.$refs.createUserForm.resetFields()
|
||
this.dialogVisible = false
|
||
},
|
||
save() {
|
||
this.$refs.createUserForm.validate((valid) => {
|
||
if (valid) {
|
||
this.loading = true
|
||
const method = this.formType === 'add' ? addUser : editUser
|
||
method(this.form).then((res) => {
|
||
this.$success(this.$t('commons.save_success'))
|
||
this.reset()
|
||
this.$emit('saved')
|
||
this.loading = false
|
||
})
|
||
} else {
|
||
return false
|
||
}
|
||
})
|
||
},
|
||
onCopy(e) {
|
||
this.$success(this.$t('commons.copy_success'))
|
||
},
|
||
onError(e) {}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.user-editer-form {
|
||
::v-deep .el-dialog__body {
|
||
padding: 0 24px 24px 24px;
|
||
}
|
||
|
||
::v-deep .el-dialog__header {
|
||
padding: 24px 24px 16px 24px;
|
||
}
|
||
|
||
::v-deep .el-dialog__footer {
|
||
padding-top: 0;
|
||
}
|
||
|
||
.editer-form-title {
|
||
width: 100%;
|
||
border-radius: 4px;
|
||
background: #e1eaff;
|
||
padding: 9px 16px;
|
||
margin-bottom: 16px;
|
||
|
||
i {
|
||
color: #3370ff;
|
||
font-size: 14.666666030883789px;
|
||
}
|
||
|
||
.pwd,
|
||
.btn-text {
|
||
font-family: PingFang SC;
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
line-height: 22px;
|
||
text-align: left;
|
||
}
|
||
|
||
.pwd {
|
||
margin: 0 8px;
|
||
color: #1f2329;
|
||
}
|
||
|
||
.btn-text {
|
||
padding: 0;
|
||
border: none;
|
||
}
|
||
}
|
||
|
||
::v-deep .el-form-item__label {
|
||
width: 100% !important;
|
||
text-align: left;
|
||
}
|
||
|
||
::v-deep
|
||
.el-form-item.is-required:not(.is-no-asterisk)
|
||
> .el-form-item__label:before {
|
||
display: none;
|
||
}
|
||
|
||
::v-deep
|
||
.el-form-item.is-required:not(.is-no-asterisk)
|
||
> .el-form-item__label::after {
|
||
content: "*";
|
||
color: #f54a45;
|
||
margin-left: 2px;
|
||
}
|
||
|
||
::v-deep .el-form-item__content {
|
||
margin-left: 0 !important;
|
||
}
|
||
|
||
.input-with-select {
|
||
::v-deep .el-input-group__prepend {
|
||
background-color: #fff;
|
||
}
|
||
.el-select {
|
||
::v-deep .el-input__inner {
|
||
width: 72px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.de-form-gender-select {
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
</style>
|
||
<style lang="scss">
|
||
.tree-select {
|
||
display: none !important;
|
||
}
|
||
.user-popper {
|
||
background: #fff;
|
||
padding: 0;
|
||
.popper__arrow {
|
||
display: none;
|
||
}
|
||
}
|
||
.user-popper.dept {
|
||
height: 300px;
|
||
overflow: auto;
|
||
}
|
||
</style>
|