采用ep重写dept页面

pull/36/head
admin 2023-03-19 13:04:59 +08:00
parent 2cf384d7ab
commit 15ac1d9d8b
4 changed files with 352 additions and 249 deletions

View File

@ -23,8 +23,6 @@ declare module '@vue/runtime-core' {
DictTag: typeof import('./../components/DictTag/src/DictTag.vue')['default'] DictTag: typeof import('./../components/DictTag/src/DictTag.vue')['default']
Echart: typeof import('./../components/Echart/src/Echart.vue')['default'] Echart: typeof import('./../components/Echart/src/Echart.vue')['default']
Editor: typeof import('./../components/Editor/src/Editor.vue')['default'] Editor: typeof import('./../components/Editor/src/Editor.vue')['default']
ElAutoResizer: typeof import('element-plus/es')['ElAutoResizer']
ElAvatar: typeof import('element-plus/es')['ElAvatar']
ElBadge: typeof import('element-plus/es')['ElBadge'] ElBadge: typeof import('element-plus/es')['ElBadge']
ElButton: typeof import('element-plus/es')['ElButton'] ElButton: typeof import('element-plus/es')['ElButton']
ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'] ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
@ -35,7 +33,6 @@ declare module '@vue/runtime-core' {
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem'] ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
ElCollapseTransition: typeof import('element-plus/es')['ElCollapseTransition'] ElCollapseTransition: typeof import('element-plus/es')['ElCollapseTransition']
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem'] ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
ElDialog: typeof import('element-plus/es')['ElDialog'] ElDialog: typeof import('element-plus/es')['ElDialog']
@ -54,7 +51,6 @@ declare module '@vue/runtime-core' {
ElForm: typeof import('element-plus/es')['ElForm'] ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem'] ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElIcon: typeof import('element-plus/es')['ElIcon'] ElIcon: typeof import('element-plus/es')['ElIcon']
ElImage: typeof import('element-plus/es')['ElImage']
ElImageViewer: typeof import('element-plus/es')['ElImageViewer'] ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
ElInput: typeof import('element-plus/es')['ElInput'] ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
@ -62,26 +58,16 @@ declare module '@vue/runtime-core' {
ElOption: typeof import('element-plus/es')['ElOption'] ElOption: typeof import('element-plus/es')['ElOption']
ElPagination: typeof import('element-plus/es')['ElPagination'] ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopover: typeof import('element-plus/es')['ElPopover'] ElPopover: typeof import('element-plus/es')['ElPopover']
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElRow: typeof import('element-plus/es')['ElRow'] ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
ElSelect: typeof import('element-plus/es')['ElSelect'] ElSelect: typeof import('element-plus/es')['ElSelect']
ElSkeleton: typeof import('element-plus/es')['ElSkeleton'] ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
ElSpace: typeof import('element-plus/es')['ElSpace']
ElSwitch: typeof import('element-plus/es')['ElSwitch'] ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable'] ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTableV2: typeof import('element-plus/es')['ElTableV2']
ElTabPane: typeof import('element-plus/es')['ElTabPane'] ElTabPane: typeof import('element-plus/es')['ElTabPane']
ElTabs: typeof import('element-plus/es')['ElTabs'] ElTabs: typeof import('element-plus/es')['ElTabs']
ElTag: typeof import('element-plus/es')['ElTag']
ElTimeline: typeof import('element-plus/es')['ElTimeline']
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElTransfer: typeof import('element-plus/es')['ElTransfer']
ElTree: typeof import('element-plus/es')['ElTree']
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
ElUpload: typeof import('element-plus/es')['ElUpload'] ElUpload: typeof import('element-plus/es')['ElUpload']
Error: typeof import('./../components/Error/src/Error.vue')['default'] Error: typeof import('./../components/Error/src/Error.vue')['default']

View File

@ -1,84 +0,0 @@
import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas'
const { t } = useI18n() // 国际化
// 表单校验
export const rules = reactive({
name: [required],
sort: [required],
// email: [required],
email: [
{ required: true, message: t('profile.rules.mail'), trigger: 'blur' },
{
type: 'email',
message: t('profile.rules.truemail'),
trigger: ['blur', 'change']
}
],
phone: [
{
len: 11,
trigger: 'blur',
message: '请输入正确的手机号码'
}
]
})
// CrudSchema
const crudSchemas = reactive<VxeCrudSchema>({
primaryKey: 'id',
primaryType: null,
action: true,
columns: [
{
title: '上级部门',
field: 'parentId',
isTable: false
},
{
title: '部门名称',
field: 'name',
isSearch: true,
table: {
treeNode: true,
align: 'left'
}
},
{
title: '负责人',
field: 'leaderUserId',
table: {
slots: {
default: 'leaderUserId_default'
}
}
},
{
title: '联系电话',
field: 'phone'
},
{
title: '邮箱',
field: 'email',
isTable: false
},
{
title: '显示排序',
field: 'sort'
},
{
title: t('common.status'),
field: 'status',
dictType: DICT_TYPE.COMMON_STATUS,
dictClass: 'number',
isSearch: true
},
{
title: t('common.createTime'),
field: 'createTime',
formatter: 'formatDate',
isForm: false
}
]
})
export const { allSchemas } = useVxeCrudSchemas(crudSchemas)

View File

@ -0,0 +1,195 @@
<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 props.userOption"
: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>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="modelVisible = false"> </el-button>
</div>
</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 formData = ref({
id: undefined,
title: '',
parentId: undefined,
name: undefined,
sort: undefined,
leaderUserId: undefined,
phone: undefined,
email: undefined,
status: undefined
})
const props = defineProps({
userOption: {
type: Array,
default: () => [] as UserVO[]
}
})
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) => {
modelVisible.value = true
modelTitle.value = t('action.' + type)
formType.value = type
resetForm()
console.log(id)
//
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

@ -1,174 +1,180 @@
<template> <template>
<ContentWrap> <ContentWrap>
<!-- 列表 --> <!-- 搜索工作栏 -->
<XTable ref="xGrid" @register="registerTable" show-overflow> <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<template #toolbar_buttons> <el-form-item label="部门名称" prop="title">
<!-- 操作新增 --> <el-input v-model="queryParams.name" placeholder="请输入部门名称" clearable />
<XButton </el-form-item>
type="primary" <el-form-item label="部门状态" prop="status">
preIcon="ep:zoom-in" <el-select v-model="queryParams.status" placeholder="请选择" clearable>
:title="t('action.add')"
v-hasPermi="['system:dept:create']"
@click="handleCreate()"
/>
<XButton title="展开所有" @click="xGrid?.Ref.setAllTreeExpand(true)" />
<XButton title="关闭所有" @click="xGrid?.Ref.clearTreeExpand()" />
</template>
<template #leaderUserId_default="{ row }">
<span>{{ userNicknameFormat(row) }}</span>
</template>
<template #actionbtns_default="{ row }">
<!-- 操作修改 -->
<XTextButton
preIcon="ep:edit"
:title="t('action.edit')"
v-hasPermi="['system:dept:update']"
@click="handleUpdate(row.id)"
/>
<!-- 操作删除 -->
<XTextButton
preIcon="ep:delete"
:title="t('action.del')"
v-hasPermi="['system:dept:delete']"
@click="deleteData(row.id)"
/>
</template>
</XTable>
</ContentWrap>
<!-- 添加或修改菜单对话框 -->
<XModal id="deptModel" v-model="dialogVisible" :title="dialogTitle">
<!-- 对话框(添加 / 修改) -->
<Form ref="formRef" :schema="allSchemas.formSchema" :rules="rules">
<template #parentId="form">
<el-tree-select
node-key="id"
v-model="form['parentId']"
:props="defaultProps"
:data="deptOptions"
:default-expanded-keys="[100]"
check-strictly
/>
</template>
<template #leaderUserId="form">
<el-select v-model="form['leaderUserId']">
<el-option <el-option
v-for="item in userOption" v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="item.id" :key="parseInt(dict.value)"
:label="item.nickname" :label="dict.label"
:value="item.id" :value="parseInt(dict.value)"
/> />
</el-select> </el-select>
</template> </el-form-item>
</Form> <el-form-item>
<template #footer> <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>
<XButton </el-form-item>
v-if="['create', 'update'].includes(actionType)" </el-form>
type="primary" <el-row :gutter="10" class="mb8">
:loading="actionLoading" <el-col :span="1.5">
@click="submitForm()" <el-button
:title="t('action.save')" type="primary"
plain
@click="openModal('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>
<!-- 列表 -->
<el-table
v-if="refreshTable"
v-loading="loading"
:data="deptDatas"
row-key="id"
: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="sort" label="排序" width="200" />
<el-table-column prop="status" label="状态" width="100">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
width="180"
:formatter="dateFormatter"
/> />
<!-- 按钮关闭 --> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<XButton :loading="actionLoading" @click="dialogVisible = false" :title="t('dialog.close')" /> <template #default="scope">
</template> <el-button
</XModal> link
type="primary"
icon="el-icon-edit"
@click="openModal('update', scope.row.id)"
v-hasPermi="['system:dept:update']"
>修改</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
>
</template>
</el-table-column>
</el-table>
</ContentWrap>
<!-- 添加或修改部门对话框 -->
<dept-form ref="modalRef" @success="getList" :userOption="userOption" />
</template> </template>
<script setup lang="ts" name="Dept"> <script setup lang="ts" name="Dept">
import { handleTree, defaultProps } from '@/utils/tree' import { handleTree } from '@/utils/tree'
import type { FormExpose } from '@/components/Form'
import { allSchemas, rules } from './dept.data'
import * as DeptApi from '@/api/system/dept' import * as DeptApi from '@/api/system/dept'
import { getListSimpleUsersApi, UserVO } from '@/api/system/user' import { getListSimpleUsersApi, UserVO } from '@/api/system/user'
import { DICT_TYPE, getDictOptions } from '@/utils/dict'
const { t } = useI18n() // import DeptForm from './form.vue'
import { dateFormatter } from '@/utils/formatTime'
const message = useMessage() // const message = useMessage() //
// const { t } = useI18n() //
const xGrid = ref<any>() // Grid Ref //
const treeConfig = { const queryParams = reactive({
transform: true, title: '',
rowField: 'id', name: undefined,
parentField: 'parentId', status: undefined,
expandAll: true pageNo: 1,
} pageSize: 100
})
// //
const dialogVisible = ref(false) // const queryFormRef = ref()
const dialogTitle = ref('edit') // //
const actionType = ref('') // const deptDatas = ref()
const actionLoading = ref(false) //
const formRef = ref<FormExpose>() // Ref
const deptOptions = ref() //
const userOption = ref<UserVO[]>([]) const userOption = ref<UserVO[]>([])
//
const isExpandAll = ref(true)
//
const refreshTable = ref(true)
//
const loading = ref(true)
//
const getUserList = async () => { const getUserList = async () => {
const res = await getListSimpleUsersApi() const res = await getListSimpleUsersApi()
userOption.value = res userOption.value = res
} }
// []
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)
}
const [registerTable, { reload, deleteData }] = useXTable({
allSchemas: allSchemas,
treeConfig: treeConfig,
getListApi: DeptApi.getDeptPageApi,
deleteApi: DeptApi.deleteDeptApi
})
// ========== / ==========
// /** 展开/折叠操作 */
const setDialogTile = (type: string) => { const toggleExpandAll = () => {
dialogTitle.value = t('action.' + type) refreshTable.value = false
actionType.value = type isExpandAll.value = !isExpandAll.value
dialogVisible.value = true console.log(isExpandAll.value)
} nextTick(() => {
refreshTable.value = true
//
const handleCreate = async () => {
setDialogTile('create')
}
//
const handleUpdate = async (rowId: number) => {
setDialogTile('update')
//
const res = await DeptApi.getDeptApi(rowId)
await nextTick()
unref(formRef)?.setValues(res)
}
// /
const submitForm = async () => {
const elForm = unref(formRef)?.getElFormRef()
if (!elForm) return
elForm.validate(async (valid) => {
if (valid) {
actionLoading.value = true
//
try {
const data = unref(formRef)?.formModel as DeptApi.DeptVO
if (actionType.value === 'create') {
await DeptApi.createDeptApi(data)
message.success(t('common.createSuccess'))
} else if (actionType.value === 'update') {
await DeptApi.updateDeptApi(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
} finally {
actionLoading.value = false
await getTree()
await reload()
}
}
}) })
} }
/** 搜索按钮操作 */
const handleQuery = () => {
getList()
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await DeptApi.deleteDeptApi(id)
message.success(t('common.delSuccess'))
//
await getList()
} 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)
}
const userNicknameFormat = (row) => { const userNicknameFormat = (row) => {
if (!row || !row.leaderUserId) { if (!row || !row.leaderUserId) {
return '未设置' return '未设置'
@ -184,6 +190,6 @@ const userNicknameFormat = (row) => {
// ========== ========== // ========== ==========
onMounted(async () => { onMounted(async () => {
await getUserList() await getUserList()
await getTree() await getList()
}) })
</script> </script>