Vue3 重构:REVIEW 部门管理

This commit is contained in:
YunaiV 2023-03-25 09:11:46 +08:00
parent 44dc02a02e
commit c0d5a5663c
5 changed files with 251 additions and 275 deletions

View File

@ -0,0 +1,174 @@
<template>
<Dialog :title="modelTitle" v-model="modelVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="80px"
v-loading="formLoading"
>
<el-form-item label="上级部门" prop="parentId">
<el-tree-select
v-model="formData.parentId"
:data="deptTree"
:props="{ value: 'id', label: 'name', children: 'children' }"
value-key="deptId"
placeholder="请选择上级部门"
check-strictly
default-expand-all
/>
</el-form-item>
<el-form-item label="部门名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入部门名称" />
</el-form-item>
<el-form-item label="显示排序" prop="sort">
<el-input-number v-model="formData.sort" controls-position="right" :min="0" />
</el-form-item>
<el-form-item label="负责人" prop="leaderUserId">
<el-select
v-model="formData.leaderUserId"
placeholder="请输入负责人"
clearable
style="width: 100%"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="联系电话" prop="phone">
<el-input v-model="formData.phone" placeholder="请输入联系电话" maxlength="11" />
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="formData.email" placeholder="请输入邮箱" maxlength="50" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="formData.status" placeholder="请选择状态" clearable>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="modelVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { handleTree } from '@/utils/tree'
import * as DeptApi from '@/api/system/dept'
import * as UserApi from '@/api/system/user'
import { CommonStatusEnum } from '@/utils/constants'
const { t } = useI18n() //
const message = useMessage() //
const modelVisible = ref(false) //
const modelTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
title: '',
parentId: undefined,
name: undefined,
sort: undefined,
leaderUserId: undefined,
phone: undefined,
email: undefined,
status: CommonStatusEnum.ENABLE
})
const formRules = reactive({
parentId: [{ required: true, message: '上级部门不能为空', trigger: 'blur' }],
name: [{ required: true, message: '部门名称不能为空', trigger: 'blur' }],
sort: [{ required: true, message: '显示排序不能为空', trigger: 'blur' }],
email: [{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }],
phone: [
{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: '请输入正确的手机号码', trigger: 'blur' }
]
})
const formRef = ref() // Ref
const deptTree = ref() //
const userList = ref<UserApi.UserVO[]>([]) //
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
modelVisible.value = true
modelTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await DeptApi.getDeptApi(id)
} finally {
formLoading.value = false
}
}
//
userList.value = await UserApi.getSimpleUserList()
//
await getTree()
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
//
formLoading.value = true
try {
const data = formData.value as unknown as DeptApi.DeptVO
if (formType.value === 'create') {
await DeptApi.createDeptApi(data)
message.success(t('common.createSuccess'))
} else {
await DeptApi.updateDeptApi(data)
message.success(t('common.updateSuccess'))
}
modelVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
title: '',
parentId: undefined,
name: undefined,
sort: undefined,
leaderUserId: undefined,
phone: undefined,
email: undefined,
status: CommonStatusEnum.ENABLE
}
formRef.value?.resetFields()
}
/** 获得部门树 */
const getTree = async () => {
deptTree.value = []
const data = await DeptApi.listSimpleDeptApi()
let dept: Tree = { id: 0, name: '顶级部门', children: [] }
dept.children = handleTree(data)
deptTree.value.push(dept)
}
</script>

View File

@ -1,187 +0,0 @@
<template>
<Dialog :title="modelTitle" v-model="modelVisible" width="800">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px">
<el-row>
<el-col :span="24" v-if="formData.parentId !== 0">
<el-form-item label="上级部门" prop="parentId">
<el-tree-select
v-model="formData.parentId"
:data="deptOptions"
:props="{ value: 'id', label: 'name', children: 'children' }"
value-key="deptId"
placeholder="选择上级部门"
check-strictly
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="部门名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入部门名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="显示排序" prop="sort">
<el-input-number v-model="formData.sort" controls-position="right" :min="0" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="负责人" prop="leaderUserId">
<el-select
v-model="formData.leaderUserId"
placeholder="请输入负责人"
clearable
style="width: 100%"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系电话" prop="phone">
<el-input v-model="formData.phone" placeholder="请输入联系电话" maxlength="11" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="邮箱" prop="email">
<el-input v-model="formData.email" placeholder="请输入邮箱" maxlength="50" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-select v-model="formData.status" placeholder="请选择状态" clearable>
<el-option
v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="parseInt(dict.value)"
:label="dict.label"
:value="parseInt(dict.value)"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="modelVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { DICT_TYPE, getDictOptions } from '@/utils/dict'
import * as DeptApi from '@/api/system/dept'
import { UserVO } from '@/api/system/user'
import { handleTree } from '@/utils/tree'
const { t } = useI18n() //
const message = useMessage() //
const modelVisible = ref(false) //
const modelTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formRef = ref() // Ref
const deptOptions = ref() //
const userList = ref() //
const formData = ref({
id: undefined,
title: '',
parentId: undefined,
name: undefined,
sort: undefined,
leaderUserId: undefined,
phone: undefined,
email: undefined,
status: undefined
})
const formRules = reactive({
parentId: [{ required: true, message: '上级部门不能为空', trigger: 'blur' }],
name: [{ required: true, message: '部门名称不能为空', trigger: 'blur' }],
order: [{ required: true, message: '显示排序不能为空', trigger: 'blur' }],
email: [{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }],
phone: [
{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: '请输入正确的手机号码', trigger: 'blur' }
]
})
/** 打开弹窗 */
const openModal = async (type: string, id?: number, userOption?: UserVO[]) => {
userList.value = userOption
modelVisible.value = true
modelTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await DeptApi.getDeptApi(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ openModal }) // openModal
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
//
formLoading.value = true
try {
const data = formData.value as unknown as DeptApi.DeptVO
if (formType.value === 'create') {
await DeptApi.createDeptApi(data)
message.success(t('common.createSuccess'))
} else {
await DeptApi.updateDeptApi(data)
message.success(t('common.updateSuccess'))
}
modelVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
title: '',
parentId: undefined,
name: undefined,
sort: undefined,
leaderUserId: undefined,
phone: undefined,
email: undefined,
status: undefined
}
formRef.value?.resetFields()
}
// []
const getTree = async () => {
deptOptions.value = []
const res = await DeptApi.listSimpleDeptApi()
let dept: Tree = { id: 0, name: '顶级部门', children: [] }
dept.children = handleTree(res)
deptOptions.value.push(dept)
}
// ========== ==========
onMounted(async () => {
await getTree()
})
</script>

View File

@ -9,50 +9,61 @@
label-width="68px" label-width="68px"
> >
<el-form-item label="部门名称" prop="title"> <el-form-item label="部门名称" prop="title">
<el-input v-model="queryParams.name" placeholder="请输入部门名称" clearable /> <el-input
v-model="queryParams.name"
placeholder="请输入部门名称"
clearable
class="!w-240px"
/>
</el-form-item> </el-form-item>
<el-form-item label="部门状态" prop="status"> <el-form-item label="部门状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择" clearable> <el-select
v-model="queryParams.status"
placeholder="请选择不么你状态"
clearable
class="!w-240px"
>
<el-option <el-option
v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)" v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="parseInt(dict.value)" :key="dict.value"
:label="dict.label" :label="dict.label"
:value="parseInt(dict.value)" :value="dict.value"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button <el-button
type="primary" type="primary"
plain plain
@click="openModal('create')" @click="openForm('create')"
v-hasPermi="['system:dept:create']" v-hasPermi="['system:dept:create']"
><Icon icon="ep:plus" class="mr-5px" /> 新增</el-button
> >
</el-col> <Icon icon="ep:plus" class="mr-5px" /> 新增
<el-col :span="1.5"> </el-button>
<el-button type="danger" plain @click="toggleExpandAll" <el-button type="danger" plain @click="toggleExpandAll">
><Icon icon="ep:sort" class="mr-5px" /> 展开/折叠</el-button <Icon icon="ep:sort" class="mr-5px" /> 展开/折叠
> </el-button>
</el-col> </el-form-item>
</el-row> </el-form>
</ContentWrap>
<!-- 列表 --> <!-- 列表 -->
<ContentWrap>
<el-table <el-table
v-if="refreshTable"
v-loading="loading" v-loading="loading"
:data="deptDatas" :data="list"
row-key="id" row-key="id"
v-if="refreshTable"
:default-expand-all="isExpandAll" :default-expand-all="isExpandAll"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
> >
<el-table-column prop="name" label="部门名称" width="260" /> <el-table-column prop="name" label="部门名称" width="260" />
<el-table-column prop="leader" label="负责人" :formatter="userNicknameFormat" width="120" /> <el-table-column prop="leader" label="负责人" width="120">
<template #default="scope">
{{ userList.find((user) => user.id === scope.row.leaderUserId)?.nickname }}
</template>
</el-table-column>
<el-table-column prop="sort" label="排序" width="200" /> <el-table-column prop="sort" label="排序" width="200" />
<el-table-column prop="status" label="状态" width="100"> <el-table-column prop="status" label="状态" width="100">
<template #default="scope"> <template #default="scope">
@ -66,43 +77,44 @@
width="180" width="180"
:formatter="dateFormatter" :formatter="dateFormatter"
/> />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="fixed-width">
<template #default="scope"> <template #default="scope">
<el-button <el-button
link link
type="primary" type="primary"
icon="el-icon-edit" @click="openForm('update', scope.row.id)"
@click="openModal('update', scope.row.id)"
v-hasPermi="['system:dept:update']" v-hasPermi="['system:dept:update']"
>修改</el-button
> >
修改
</el-button>
<el-button <el-button
v-if="scope.row.parentId !== 0"
link link
type="danger" type="danger"
icon="el-icon-delete"
@click="handleDelete(scope.row.id)" @click="handleDelete(scope.row.id)"
v-hasPermi="['system:dept:delete']" v-hasPermi="['system:dept:delete']"
>删除</el-button
> >
删除
</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</ContentWrap> </ContentWrap>
<!-- 添加或修改部门对话框 --> <!-- 表单弹窗添加/修改 -->
<dept-form ref="modalRef" @success="getList" /> <DeptForm ref="formRef" @success="getList" />
</template> </template>
<script setup lang="ts" name="Dept"> <script setup lang="ts" name="Dept">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { handleTree } from '@/utils/tree' import { handleTree } from '@/utils/tree'
import * as DeptApi from '@/api/system/dept' import * as DeptApi from '@/api/system/dept'
import { DICT_TYPE, getDictOptions } from '@/utils/dict' import DeptForm from './DeptForm.vue'
import DeptForm from './form.vue' import * as UserApi from '@/api/system/user'
import { dateFormatter } from '@/utils/formatTime'
import { getSimpleUserList, UserVO } from '@/api/system/user'
const message = useMessage() // const message = useMessage() //
const { t } = useI18n() // const { t } = useI18n() //
//
const loading = ref(true) //
const list = ref() //
const queryParams = reactive({ const queryParams = reactive({
title: '', title: '',
name: undefined, name: undefined,
@ -110,19 +122,20 @@ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 100 pageSize: 100
}) })
const queryFormRef = ref() // const queryFormRef = ref() //
const deptDatas = ref() //
const userOption = ref<UserVO[]>([])
const isExpandAll = ref(true) // const isExpandAll = ref(true) //
const refreshTable = ref(true) // const refreshTable = ref(true) //
const loading = ref(true) // const userList = ref<UserApi.UserVO[]>([]) //
// /** 查询部门列表 */
const getUserList = async () => { const getList = async () => {
const res = await getSimpleUserList() loading.value = true
userOption.value = res try {
const data = await DeptApi.getDeptPageApi(queryParams)
list.value = handleTree(data)
} finally {
loading.value = false
}
} }
/** 展开/折叠操作 */ /** 展开/折叠操作 */
@ -140,6 +153,19 @@ const handleQuery = () => {
getList() getList()
} }
/** 重置按钮操作 */
const resetQuery = () => {
queryParams.pageNo = 1
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */ /** 删除按钮操作 */
const handleDelete = async (id: number) => { const handleDelete = async (id: number) => {
try { try {
@ -153,47 +179,10 @@ const handleDelete = async (id: number) => {
} catch {} } catch {}
} }
/** 查询部门列表 */ /** 初始化 **/
const getList = async () => {
loading.value = true
try {
const res = await DeptApi.getDeptPageApi(queryParams)
deptDatas.value = handleTree(res)
} finally {
loading.value = false
}
}
/** 重置按钮操作 */
const resetQuery = () => {
queryParams.pageNo = 1
queryParams.name = undefined
queryParams.status = undefined
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const modalRef = ref()
const openModal = (type: string, id?: number) => {
modalRef.value.openModal(type, id, userOption.value)
}
const userNicknameFormat = (row) => {
if (!row || !row.leaderUserId) {
return '未设置'
}
for (const user of userOption.value) {
if (row.leaderUserId === user.id) {
return user.nickname
}
}
return '未知【' + row.leaderUserId + '】'
}
// ========== ==========
onMounted(async () => { onMounted(async () => {
await getUserList()
await getList() await getList()
//
userList.value = await UserApi.getSimpleUserList()
}) })
</script> </script>

View File

@ -99,7 +99,7 @@
width="180" width="180"
:formatter="dateFormatter" :formatter="dateFormatter"
/> />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-paddingfixed-width">
<template #default="scope"> <template #default="scope">
<el-button <el-button
link link

View File

@ -169,7 +169,7 @@
<el-table-column <el-table-column
label="操作" label="操作"
align="center" align="center"
class-name="small-padding fixed-width" class-name="fixed-width"
width="210" width="210"
fixed="right" fixed="right"
> >