330 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<el-dialog
v-model="state.showDialog"
destroy-on-close
:title="title"
draggable
:close-on-click-modal="false"
:close-on-press-escape="false"
width="769px"
>
<el-form ref="formRef" :model="form" size="default" label-width="80px">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="姓名" prop="name" :rules="[{ required: true, message: '请输入姓名', trigger: ['blur', 'change'] }]">
<el-input v-model="form.name" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item
label="手机号"
prop="mobile"
:rules="[
{ required: true, message: '请输入手机号', trigger: ['blur', 'change'] },
{ validator: testMobile, trigger: ['blur', 'change'] },
]"
>
<el-input v-model="form.mobile" autocomplete="off" maxlength="11" @blur="onBlurMobile" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="部门" prop="orgIds" :rules="[{ required: true, message: '请选择部门', trigger: ['change'] }]">
<el-tree-select
ref="orgTreeSelectRef"
v-model="form.orgIds"
placeholder="请选择部门"
:data="state.orgTreeData"
node-key="id"
:props="{ label: 'name' }"
check-strictly
default-expand-all
render-after-expand
fit-input-width
clearable
multiple
collapse-tags
collapse-tags-tooltip
filterable
class="w100"
/>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="主属部门" prop="orgId" :rules="[{ required: true, message: '请选择主属部门', trigger: ['change'] }]">
<el-select v-model="form.orgId" placeholder="请选择主属部门" class="w100">
<el-option v-for="item in state.orgs" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="账号" prop="userName" :rules="[{ required: true, message: '请输入账号', trigger: ['blur', 'change'] }]">
<el-input v-model="form.userName" autocomplete="off" />
</el-form-item>
</el-col>
<el-col v-if="!isUpdate" :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item prop="password" :rules="[{ validator: validatorPwd, trigger: ['blur', 'change'] }]">
<template #label>
<div class="my-flex-y-center">
密码<el-tooltip effect="dark" placement="top" hide-after="0">
<template #content>选填,不填则使用系统默认密码<br />字母+数字+可选特殊字符长度在6-16之间</template>
<SvgIcon name="ele-InfoFilled" class="ml5" />
</el-tooltip>
</div>
</template>
<el-input
key="password"
v-model="form.password"
placeholder="选填,不填则使用系统默认密码"
@input="onInputPwd"
show-password
autocomplete="off"
/>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="直属主管" prop="managerUserId">
<my-select-user v-model="form.managerUserId" :name="form.managerUserName" clearable></my-select-user>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="角色" prop="roles">
<el-tree-select
v-model="form.roleIds"
placeholder="请选择角色"
:data="state.roleTreeData"
node-key="id"
:props="{ label: 'name' }"
default-expand-all
render-after-expand
fit-input-width
clearable
multiple
collapse-tags
collapse-tags-tooltip
filterable
class="w100"
/>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="span" :md="span" :lg="span" :xl="span">
<el-form-item label="邮箱" prop="email" :rules="[{ validator: testEmail, trigger: ['blur', 'change'] }]">
<el-input v-model="form.email" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="团队">
<el-select v-model="form.team" placeholder="请选择团队" class="w100">
<el-option v-for="item in state.teamList" :key="item.label" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<el-form-item label="性别">
<el-select v-model="form.staff.sex" placeholder="请选择性别" class="w100">
<el-option label="" :value="undefined" />
<el-option v-for="item in state.sexList" :key="item.label" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
<el-form-item label="消息方式" prop="messageMethods">
<el-checkbox label="sms" name="sms" v-model="form.isReceiveSMS">短信通知</el-checkbox>
<el-checkbox label="email" name="email" v-model="form.isReceiveEmail">邮件通知</el-checkbox>
<el-checkbox label="system" name="system" v-model="form.isReceiveSite">系统消息</el-checkbox>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="default"> </el-button>
<el-button type="primary" @click="onSure" size="default" :loading="state.sureLoading"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup name="admin/user/form">
import { reactive, toRefs, getCurrentInstance, ref, watch, defineAsyncComponent, computed } from 'vue'
import { UserAddInput, UserUpdateInput, OrgGetListOutput, RoleGetListOutput } from '/@/api/admin/data-contracts'
import { UserApi } from '/@/api/admin/User'
import { OrgApi } from '/@/api/admin/Org'
import { RoleApi } from '/@/api/admin/Role'
import { listToTree, treeToList } from '/@/utils/tree'
import { cloneDeep, fromPairs } from 'lodash-es'
import { isMobile, testMobile, testEmail } from '/@/utils/test'
import { validatorPwd } from '/@/utils/validators'
import eventBus from '/@/utils/mitt'
import { FormInstance } from 'element-plus'
import { verifyCnAndSpace } from '/@/utils/toolsValidate'
import { Sex, Team } from '/@/api/admin/enum-contracts'
import { toOptionsByValue } from '/@/utils/enum'
// 引入组件
const MySelectUser = defineAsyncComponent(() => import('./my-select-user.vue'))
defineProps({
title: {
type: String,
default: '',
},
})
const { proxy } = getCurrentInstance() as any
const orgTreeSelectRef = ref()
const formRef = ref<FormInstance>()
const state = reactive({
showDialog: false,
sureLoading: false,
form: {
orgIds: [] as any,
roleIds: [] as any,
} as UserAddInput & UserUpdateInput,
orgs: [] as any,
orgTreeData: [] as OrgGetListOutput[],
roleTreeData: [] as RoleGetListOutput[],
sexList: toOptionsByValue(Sex),
teamList: toOptionsByValue(Team),
})
const { form } = toRefs(state)
const isUpdate = computed(() => {
return state.form.id > 0
})
const span = computed(() => {
return isUpdate.value ? 12 : 24
})
watch(
() => state.form.orgIds,
(value) => {
if (value && value.length > 0) {
let orgs = [] as any
treeToList(cloneDeep(state.orgTreeData)).forEach((a: any) => {
if (value.some((b) => a.id === b)) {
orgs.push(a)
}
})
state.orgs = orgs
} else {
state.orgs = []
}
},
{
immediate: true,
}
)
watch(
() => state.orgs,
() => {
if (state.orgs?.some((a: any) => a.id === state.form.orgId)) {
return
}
state.form.orgId = state.orgs && state.orgs.length > 0 ? state.orgs[0].id : undefined
},
{
immediate: true,
deep: true,
}
)
const getOrgs = async () => {
const res = await new OrgApi().getList().catch(() => {
state.orgTreeData = []
})
if (res?.success && res.data && res.data.length > 0) {
state.orgTreeData = listToTree(res.data)
} else {
state.orgTreeData = []
}
}
const getRoles = async () => {
const res = await new RoleApi().getList().catch(() => {
state.roleTreeData = []
})
if (res?.success && res.data && res.data.length > 0) {
state.roleTreeData = listToTree(res.data)
} else {
state.roleTreeData = []
}
}
// 打开对话框
const open = async (row: UserUpdateInput & UserUpdateInput) => {
proxy.$modal.loading()
await getOrgs()
await getRoles()
if (row.id > 0) {
const res = await new UserApi().get({ id: row.id }).catch(() => {
proxy.$modal.closeLoading()
})
if (res?.success) {
state.form = res.data as UserAddInput & UserUpdateInput
}
} else {
state.form = {
roleIds: [] as number[],
staff: {},
} as UserAddInput & UserUpdateInput
}
proxy.$modal.closeLoading()
state.showDialog = true
}
// 输入密码
const onInputPwd = (val: string) => {
state.form.password = verifyCnAndSpace(val)
}
//手机号失去焦点
const onBlurMobile = () => {
if (!state.form.userName && state.form.mobile && isMobile(state.form.mobile)) {
state.form.userName = state.form.mobile
}
}
// 取消
const onCancel = () => {
state.showDialog = false
}
// 确定
const onSure = () => {
formRef.value!.validate(async (valid: boolean) => {
if (!valid) return
state.sureLoading = true
let res = {} as any
if (state.form.id != undefined && state.form.id > 0) {
res = await new UserApi().update(state.form, { showSuccessMessage: true }).catch(() => {
state.sureLoading = false
})
} else {
res = await new UserApi().add(state.form, { showSuccessMessage: true }).catch(() => {
state.sureLoading = false
})
}
state.sureLoading = false
if (res?.success) {
eventBus.emit('refreshUser')
state.showDialog = false
}
})
}
defineExpose({
open,
})
</script>