njzscloud-dispose-web/src/pages/sys/menus/MenuForm.vue

203 lines
5.4 KiB
Vue

<template>
<ElDialog v-model="showDialog"
:close-on-click-modal="false"
destroy-on-close
width="25vw"
>
<ElForm :model="menuForm"
class="menu-form"
label-width="auto">
<ElFormItem label="上级">
<ElTreeSelect
v-model="menuForm.pid"
:data="menuTreeDataSource"
:default-expanded-keys="['0']"
:disabled="status === 'view'"
:render-after-expand="false"
check-strictly
placeholder="选择上级菜单"
/>
</ElFormItem>
<ElFormItem label="类型">
<ElSelect
v-model="menuForm.menuCategory"
:data="menuCategoryData"
:disabled="status === 'view'"
placeholder="选择类型"
>
<ElOption v-for="menuCategory in menuCategoryData" :key="menuCategory.key" :label="menuCategory.label" :value="menuCategory.key"/>
</ElSelect>
</ElFormItem>
<ElFormItem label="名称">
<ElInput
v-model="menuForm.title"
:disabled="status === 'view'"
placeholder="名称"
/>
</ElFormItem>
<ElFormItem
v-if="menuForm.menuCategory === MenuCategory.Page || menuForm.menuCategory === MenuCategory.SubPage"
:disabled="status === 'view'"
label="路由名称">
<ElInput v-model="menuForm.routeName" :min="0" placeholder="路由名称"/>
</ElFormItem>
<ElFormItem
v-if="menuForm.menuCategory === MenuCategory.Page || menuForm.menuCategory === MenuCategory.SubPage"
:disabled="status === 'view'"
label="路由地址">
<ElInput v-model="menuForm.routePath" :min="0" placeholder="路由地址"/>
</ElFormItem>
<ElFormItem
label="编码">
<ElInput v-model="menuForm.sn"
:disabled="status === 'view'"
:min="0" placeholder="编码"/>
</ElFormItem>
<ElFormItem
label="图标">
<ElDropdown closable header="图标列表"
placement="bottom"
style="width: 100%" trigger="click">
<ElInput v-model="menuForm.icon"
:disabled="status === 'view'"
placeholder="选择图标"/>
<template #dropdown>
<ElTable
:data="iconTableDataSource"
empty-text="暂无数据"
style="width: 324px;"
>
<ElTableColumn label="图标" prop="name"/>
<ElTableColumn label="名称" prop="name"/>
</ElTable>
</template>
</ElDropdown>
</ElFormItem>
<ElFormItem label="排序">
<ElInputNumber
v-model="menuForm.sort"
:disabled="status === 'view'"
:min="0"
placeholder="排序"
style="width: 100%"
/>
</ElFormItem>
</ElForm>
<template #footer>
<ElButton @click="showDialog = false">{{ status === 'view' ? '关闭' : '取消' }}</ElButton>
<ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler"></ElButton>
</template>
</ElDialog>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import {
MenuCategory,
MenuCategoryDict,
} from '@/common/app/constants.ts'
import MenuApi from '@/pages/sys/menus/menu-api.ts'
import Colls from '@/common/utils/colls.ts'
import Strings from '@/common/utils/strings.ts'
import { ElMessage } from 'element-plus'
interface IconData {
name: string
}
const selectedRowKeys = ref<string[]>([])
const iconTableDataSource = ref<IconData[]>([].filter((_, i) => {
return i >= 0 && i < 5
}))
const showDialog = ref(false)
const submiting = ref(false)
const status = ref<'add' | 'view' | 'modify'>('add')
const pagination = reactive({
pageIndex: 1,
pageSize: 5,
total: 20,
size: 'sm',
showTotal: true,
onChange(pageIndex: number, pageSize: number) {
pagination.pageIndex = pageIndex
pagination.pageSize = pageSize
iconTableDataSource.value = [].filter((_, i) => {
return i >= (pageIndex - 1) * pageSize && i < pageIndex * pageSize
})
},
})
const menuForm = reactive<MenuTypes.MenuForm>({})
const menuCategoryData = computed(() => {
const data: { key: string, label: string }[] = []
for (const key in MenuCategoryDict) {
data.push({
key,
label: MenuCategoryDict[key as keyof typeof MenuCategoryDict],
})
}
return data
})
const menuTreeDataSource = ref<MenuTypes.SysMenu[]>()
function submitHandler() {
if (status.value === 'view') return
submiting.value = true
if (menuForm.id != null) {
MenuApi.modify(menuForm)
.then(() => {
ElMessage.success('修改成功')
})
.finally(() => {
submiting.value = false
})
} else {
MenuApi.add(menuForm)
.then(() => {
ElMessage.success('添加成功')
})
.finally(() => {
submiting.value = false
})
}
}
defineExpose({
open(data: MenuTypes.MenuForm = {}) {
if (!Strings.isBlank(data.id)) {
status.value = 'modify'
}
Object.assign(menuForm, data)
showDialog.value = true
if (data.icon != null) {
selectedRowKeys.value = [ data.icon ]
}
}
})
onMounted(() => {
MenuApi.list()
.then(({data}) => {
const nodes = Colls.toTree(data.map(it => ({value: it.id, label: it.title, ...it})))
menuTreeDataSource.value = [ {value: '0', label: '顶级菜单', id: '0', pid: '0', children: nodes} ]
})
})
</script>
<style lang="stylus" scoped>
.menu-form {
padding 20px
}
</style>