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"
>
<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 label="部门状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择" clearable>
<el-select
v-model="queryParams.status"
placeholder="请选择不么你状态"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="parseInt(dict.value)"
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.label"
:value="parseInt(dict.value)"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<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-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
@click="openModal('create')"
@click="openForm('create')"
v-hasPermi="['system:dept:create']"
><Icon icon="ep:plus" class="mr-5px" /> 新增</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain @click="toggleExpandAll"
><Icon icon="ep:sort" class="mr-5px" /> 展开/折叠</el-button
>
</el-col>
</el-row>
<!-- 列表 -->
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button type="danger" plain @click="toggleExpandAll">
<Icon icon="ep:sort" class="mr-5px" /> 展开/折叠
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-if="refreshTable"
v-loading="loading"
:data="deptDatas"
:data="list"
row-key="id"
v-if="refreshTable"
:default-expand-all="isExpandAll"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<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="status" label="状态" width="100">
<template #default="scope">
@ -66,43 +77,44 @@
width="180"
: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">
<el-button
link
type="primary"
icon="el-icon-edit"
@click="openModal('update', scope.row.id)"
@click="openForm('update', scope.row.id)"
v-hasPermi="['system:dept:update']"
>修改</el-button
>
修改
</el-button>
<el-button
v-if="scope.row.parentId !== 0"
link
type="danger"
icon="el-icon-delete"
@click="handleDelete(scope.row.id)"
v-hasPermi="['system:dept:delete']"
>删除</el-button
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</ContentWrap>
<!-- 添加或修改部门对话框 -->
<dept-form ref="modalRef" @success="getList" />
<!-- 表单弹窗添加/修改 -->
<DeptForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts" name="Dept">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { handleTree } from '@/utils/tree'
import * as DeptApi from '@/api/system/dept'
import { DICT_TYPE, getDictOptions } from '@/utils/dict'
import DeptForm from './form.vue'
import { dateFormatter } from '@/utils/formatTime'
import { getSimpleUserList, UserVO } from '@/api/system/user'
import DeptForm from './DeptForm.vue'
import * as UserApi from '@/api/system/user'
const message = useMessage() //
const { t } = useI18n() //
//
const loading = ref(true) //
const list = ref() //
const queryParams = reactive({
title: '',
name: undefined,
@ -110,19 +122,20 @@ const queryParams = reactive({
pageNo: 1,
pageSize: 100
})
const queryFormRef = ref() //
const deptDatas = ref() //
const userOption = ref<UserVO[]>([])
const isExpandAll = ref(true) //
const refreshTable = ref(true) //
const loading = ref(true) //
const userList = ref<UserApi.UserVO[]>([]) //
//
const getUserList = async () => {
const res = await getSimpleUserList()
userOption.value = res
/** 查询部门列表 */
const getList = async () => {
loading.value = true
try {
const data = await DeptApi.getDeptPageApi(queryParams)
list.value = handleTree(data)
} finally {
loading.value = false
}
}
/** 展开/折叠操作 */
@ -140,6 +153,19 @@ const handleQuery = () => {
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) => {
try {
@ -153,47 +179,10 @@ const handleDelete = async (id: number) => {
} 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 () => {
await getUserList()
await getList()
//
userList.value = await UserApi.getSimpleUserList()
})
</script>

View File

@ -99,7 +99,7 @@
width="180"
: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">
<el-button
link

View File

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