mirror of
https://gitee.com/bootx/dax-pay-ui.git
synced 2025-09-02 10:26:32 +00:00
feat 菜单管理移植
This commit is contained in:
Binary file not shown.
Before Width: | Height: | Size: 894 B After Width: | Height: | Size: 723 B |
@@ -5,6 +5,7 @@ export enum ResultEnum {
|
|||||||
SUCCESS = 0,
|
SUCCESS = 0,
|
||||||
ERROR = -1,
|
ERROR = -1,
|
||||||
TIMEOUT = 401,
|
TIMEOUT = 401,
|
||||||
|
NOT_LOGIN = 10004,
|
||||||
TYPE = 'success',
|
TYPE = 'success',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -89,7 +89,7 @@
|
|||||||
|
|
||||||
listenerRouteChange((route) => {
|
listenerRouteChange((route) => {
|
||||||
const { name } = route
|
const { name } = route
|
||||||
console.log(route)
|
// console.log(route)
|
||||||
if (name === REDIRECT_NAME || !route || !userStore.getToken) {
|
if (name === REDIRECT_NAME || !route || !userStore.getToken) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,8 @@ export function createPermissionGuard(router: Router) {
|
|||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
if (
|
if (
|
||||||
from.path === ROOT_PATH &&
|
from.path === ROOT_PATH &&
|
||||||
to.path === PageEnum.BASE_HOME &&
|
to.path === PageEnum.BASE_HOME
|
||||||
|
&&
|
||||||
// TODO 没有用户首页配置这个字段
|
// TODO 没有用户首页配置这个字段
|
||||||
userStore.getUserInfo.homePath &&
|
userStore.getUserInfo.homePath &&
|
||||||
userStore.getUserInfo.homePath !== PageEnum.BASE_HOME
|
userStore.getUserInfo.homePath !== PageEnum.BASE_HOME
|
||||||
|
@@ -29,7 +29,6 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
|
|||||||
item.component = null
|
item.component = null
|
||||||
} else {
|
} else {
|
||||||
// 内部打开, 开是否是 Iframe 方式
|
// 内部打开, 开是否是 Iframe 方式
|
||||||
console.log(item.component)
|
|
||||||
if ((item.component as string).toUpperCase() === 'IFRAME') {
|
if ((item.component as string).toUpperCase() === 'IFRAME') {
|
||||||
// item.meta.frameSrc = item.iframeUrl
|
// item.meta.frameSrc = item.iframeUrl
|
||||||
item.meta.frameSrc = 'https://vvbin.cn/doc-next/'
|
item.meta.frameSrc = 'https://vvbin.cn/doc-next/'
|
||||||
|
@@ -23,15 +23,7 @@ const dashboard: AppRouteModule = {
|
|||||||
title: t('routes.dashboard.analysis'),
|
title: t('routes.dashboard.analysis'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
]
|
||||||
path: 'workbench',
|
|
||||||
name: 'Workbench',
|
|
||||||
component: () => import('/@/views/dashboard/workbench/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: t('routes.dashboard.workbench'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default dashboard
|
export default dashboard
|
||||||
|
@@ -38,7 +38,7 @@ const setting: ProjectConfig = {
|
|||||||
// 灰度迷失
|
// 灰度迷失
|
||||||
grayMode: false,
|
grayMode: false,
|
||||||
|
|
||||||
// 色日模式
|
// 色弱模式
|
||||||
colorWeak: false,
|
colorWeak: false,
|
||||||
|
|
||||||
// 是否取消菜单,顶部,多选项卡页面显示,对于可能嵌入其他系统
|
// 是否取消菜单,顶部,多选项卡页面显示,对于可能嵌入其他系统
|
||||||
@@ -117,12 +117,13 @@ const setting: ProjectConfig = {
|
|||||||
mixSideFixed: false,
|
mixSideFixed: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Multi-label
|
// 多标签配置
|
||||||
multiTabsSetting: {
|
multiTabsSetting: {
|
||||||
|
// 缓存
|
||||||
cache: false,
|
cache: false,
|
||||||
// Turn on
|
// Turn on
|
||||||
show: true,
|
show: true,
|
||||||
// Is it possible to drag and drop sorting tabs
|
// 是否可以拖放排序标签
|
||||||
canDrag: true,
|
canDrag: true,
|
||||||
// Turn on quick actions
|
// Turn on quick actions
|
||||||
showQuick: true,
|
showQuick: true,
|
||||||
|
@@ -22,6 +22,7 @@ import { useMessage } from '/@/hooks/web/useMessage'
|
|||||||
import { PageEnum } from '/@/enums/pageEnum'
|
import { PageEnum } from '/@/enums/pageEnum'
|
||||||
import { getAppEnvConfig } from '/@/utils/env'
|
import { getAppEnvConfig } from '/@/utils/env'
|
||||||
import { PermMenu } from '/@/api/sys/model/menuModel'
|
import { PermMenu } from '/@/api/sys/model/menuModel'
|
||||||
|
import dashboard from '/@/router/routes/modules/dashboard'
|
||||||
|
|
||||||
interface PermissionState {
|
interface PermissionState {
|
||||||
// Permission code list
|
// Permission code list
|
||||||
@@ -118,7 +119,7 @@ export const usePermissionStore = defineStore({
|
|||||||
* 转换权限菜单为系统中的菜单
|
* 转换权限菜单为系统中的菜单
|
||||||
*/
|
*/
|
||||||
convertMenus(permMenus: PermMenu[]): AppRouteRecordRaw[] {
|
convertMenus(permMenus: PermMenu[]): AppRouteRecordRaw[] {
|
||||||
return permMenus.map((o) => {
|
return permMenus?.map((o) => {
|
||||||
const menu = {
|
const menu = {
|
||||||
name: o.name,
|
name: o.name,
|
||||||
path: o.path,
|
path: o.path,
|
||||||
@@ -136,8 +137,7 @@ export const usePermissionStore = defineStore({
|
|||||||
},
|
},
|
||||||
children: this.convertMenus(o.children),
|
children: this.convertMenus(o.children),
|
||||||
} as AppRouteRecordRaw
|
} as AppRouteRecordRaw
|
||||||
if (o.component.toUpperCase()){
|
if (o.component.toUpperCase()) {
|
||||||
|
|
||||||
}
|
}
|
||||||
return menu
|
return menu
|
||||||
})
|
})
|
||||||
@@ -228,12 +228,9 @@ export const usePermissionStore = defineStore({
|
|||||||
|
|
||||||
// 动态引入组件
|
// 动态引入组件
|
||||||
routeList = transformObjToRoute(routeList)
|
routeList = transformObjToRoute(routeList)
|
||||||
console.log(routeList)
|
|
||||||
|
|
||||||
// 后台路由到菜单结构
|
// 后台路由到菜单结构
|
||||||
const backMenuList = transformRouteToMenu(routeList)
|
const backMenuList = transformRouteToMenu(routeList)
|
||||||
this.setBackMenuList(backMenuList)
|
this.setBackMenuList(backMenuList)
|
||||||
|
|
||||||
// 删除 meta.ignoreRoute 项
|
// 删除 meta.ignoreRoute 项
|
||||||
routeList = filter(routeList, routeRemoveIgnoreFilter)
|
routeList = filter(routeList, routeRemoveIgnoreFilter)
|
||||||
routeList = routeList.filter(routeRemoveIgnoreFilter)
|
routeList = routeList.filter(routeRemoveIgnoreFilter)
|
||||||
@@ -244,6 +241,7 @@ export const usePermissionStore = defineStore({
|
|||||||
}
|
}
|
||||||
|
|
||||||
routes.push(ERROR_LOG_ROUTE)
|
routes.push(ERROR_LOG_ROUTE)
|
||||||
|
routes.push(dashboard)
|
||||||
patchHomeAffix(routes)
|
patchHomeAffix(routes)
|
||||||
return routes
|
return routes
|
||||||
},
|
},
|
||||||
|
@@ -58,10 +58,11 @@ const transform: AxiosTransform = {
|
|||||||
// 在此处根据自己项目的实际情况对不同的code执行不同的操作
|
// 在此处根据自己项目的实际情况对不同的code执行不同的操作
|
||||||
// 如果不希望中断当前请求,请return数据,否则直接抛出异常即可
|
// 如果不希望中断当前请求,请return数据,否则直接抛出异常即可
|
||||||
let timeoutMsg = ''
|
let timeoutMsg = ''
|
||||||
|
const userStore = useUserStoreWithOut()
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case ResultEnum.TIMEOUT:
|
case ResultEnum.TIMEOUT:
|
||||||
|
case ResultEnum.NOT_LOGIN:
|
||||||
timeoutMsg = '登录超时,请重新登录!'
|
timeoutMsg = '登录超时,请重新登录!'
|
||||||
const userStore = useUserStoreWithOut()
|
|
||||||
userStore.setToken(undefined)
|
userStore.setToken(undefined)
|
||||||
userStore.logout(true)
|
userStore.logout(true)
|
||||||
break
|
break
|
||||||
|
@@ -39,8 +39,9 @@
|
|||||||
<a href="javascript:" @click="edit(row)">编辑</a>
|
<a href="javascript:" @click="edit(row)">编辑</a>
|
||||||
</span>
|
</span>
|
||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
<a-popconfirm title="是否删除" @confirm="remove(row)" okText="是" cancelText="否">
|
<a-popconfirm :disabled="row.system" title="是否删除" @confirm="remove(row)" okText="是" cancelText="否">
|
||||||
<a href="javascript:" style="color: red">删除</a>
|
<a href="javascript:" v-if="!row.system" style="color: red">删除</a>
|
||||||
|
<a href="javascript:" v-else disabled>删除</a>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
@@ -67,7 +68,6 @@
|
|||||||
import { STRING } from '/@/components/Bootx/Query/SuperQueryCode'
|
import { STRING } from '/@/components/Bootx/Query/SuperQueryCode'
|
||||||
import { FormEditType } from '/@/enums/formTypeEnum'
|
import { FormEditType } from '/@/enums/formTypeEnum'
|
||||||
import { useMessage } from '/@/hooks/web/useMessage'
|
import { useMessage } from '/@/hooks/web/useMessage'
|
||||||
import { getAppEnvConfig } from "/@/utils/env";
|
|
||||||
|
|
||||||
// 使用hooks
|
// 使用hooks
|
||||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, pages, model, loading } = useTablePage(queryPage)
|
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, pages, model, loading } = useTablePage(queryPage)
|
||||||
|
@@ -46,7 +46,8 @@
|
|||||||
</span>
|
</span>
|
||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
<a-popconfirm title="是否删除" @confirm="remove(row)" okText="是" cancelText="否">
|
<a-popconfirm title="是否删除" @confirm="remove(row)" okText="是" cancelText="否">
|
||||||
<a href="javascript:" style="color: red">删除</a>
|
<a href="javascript:" v-if="!row.system" style="color: red">删除</a>
|
||||||
|
<a href="javascript:" v-else disabled>删除</a>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
@@ -66,13 +67,14 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from 'vue'
|
import { onMounted, ref } from 'vue'
|
||||||
import { del, page } from './LoginType.api'
|
import { del, LoginType, page } from "./LoginType.api";
|
||||||
import useTablePage from '/@/hooks/bootx/useTablePage'
|
import useTablePage from '/@/hooks/bootx/useTablePage'
|
||||||
import LoginTypeEdit from './LoginTypeEdit.vue'
|
import LoginTypeEdit from './LoginTypeEdit.vue'
|
||||||
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
|
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
|
||||||
import { FormEditType } from '/@/enums/formTypeEnum'
|
import { FormEditType } from '/@/enums/formTypeEnum'
|
||||||
import { useMessage } from '/@/hooks/web/useMessage'
|
import { useMessage } from '/@/hooks/web/useMessage'
|
||||||
import { STRING } from '/@/components/Bootx/Query/SuperQueryCode'
|
import { STRING } from '/@/components/Bootx/Query/SuperQueryCode'
|
||||||
|
import { BaseEntity } from "/#/web";
|
||||||
|
|
||||||
// 使用hooks
|
// 使用hooks
|
||||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, pages, model, loading } = useTablePage(queryPage)
|
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, pages, model, loading } = useTablePage(queryPage)
|
||||||
@@ -102,11 +104,11 @@
|
|||||||
loginTypeEdit.value.init(null, FormEditType.Add)
|
loginTypeEdit.value.init(null, FormEditType.Add)
|
||||||
}
|
}
|
||||||
// 查看
|
// 查看
|
||||||
function edit(record) {
|
function edit(record: LoginType) {
|
||||||
loginTypeEdit.value.init(record.id, FormEditType.Edit)
|
loginTypeEdit.value.init(record.id, FormEditType.Edit)
|
||||||
}
|
}
|
||||||
// 查看
|
// 查看
|
||||||
function show(record) {
|
function show(record: LoginType) {
|
||||||
loginTypeEdit.value.init(record.id, FormEditType.Show)
|
loginTypeEdit.value.init(record.id, FormEditType.Show)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
97
src/views/modules/system/menu/Menu.api.ts
Normal file
97
src/views/modules/system/menu/Menu.api.ts
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import { defHttp } from '/@/utils/http/axios'
|
||||||
|
import { PageResult, Result } from '/#/axios'
|
||||||
|
import { BaseEntity } from '/#/web'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 树列表
|
||||||
|
*/
|
||||||
|
export const menuTree = (clientCode: string) => {
|
||||||
|
return defHttp.get<Result<Array<Menu>>>({
|
||||||
|
url: '/perm/menu/menuTree',
|
||||||
|
params: { clientCode },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单条
|
||||||
|
*/
|
||||||
|
export const get = (id) => {
|
||||||
|
return defHttp.get<Result<Menu>>({
|
||||||
|
url: '/perm/menu/findById',
|
||||||
|
params: { id },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加
|
||||||
|
*/
|
||||||
|
export const add = (obj: Menu) => {
|
||||||
|
return defHttp.post({
|
||||||
|
url: '/perm/menu/add',
|
||||||
|
data: obj,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新
|
||||||
|
*/
|
||||||
|
export const update = (obj: Menu) => {
|
||||||
|
return defHttp.post({
|
||||||
|
url: '/perm/menu/update',
|
||||||
|
data: obj,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
export const del = (id) => {
|
||||||
|
return defHttp.delete({
|
||||||
|
url: '/perm/menu/delete',
|
||||||
|
params: { id },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限_菜单
|
||||||
|
*/
|
||||||
|
export interface Menu extends BaseEntity {
|
||||||
|
// 终端code
|
||||||
|
clientCode?: string
|
||||||
|
// 父id
|
||||||
|
parentId: number | null
|
||||||
|
// 菜单名称
|
||||||
|
title: string
|
||||||
|
// 路由名称
|
||||||
|
name: string
|
||||||
|
// 菜单权限编码
|
||||||
|
permCode: string
|
||||||
|
// 菜单图标
|
||||||
|
icon: string
|
||||||
|
// 是否隐藏
|
||||||
|
hidden: boolean
|
||||||
|
// 是否隐藏子菜单
|
||||||
|
hideChildrenInMenu: boolean
|
||||||
|
// 组件
|
||||||
|
component: string
|
||||||
|
// 组件名字
|
||||||
|
componentName: string
|
||||||
|
// 路径
|
||||||
|
path: string
|
||||||
|
// 菜单跳转地址(重定向)
|
||||||
|
redirect: string
|
||||||
|
// 菜单排序
|
||||||
|
sortNo: number
|
||||||
|
// 类型(0:一级菜单;1:子菜单 ;2:按钮权限)
|
||||||
|
menuType: number
|
||||||
|
// 是否缓存页面
|
||||||
|
keepAlive: boolean
|
||||||
|
// 是否外部打开方式
|
||||||
|
targetOutside: boolean
|
||||||
|
// 隐藏的标题内容
|
||||||
|
hiddenHeaderContent: boolean
|
||||||
|
// 系统菜单
|
||||||
|
admin?: boolean
|
||||||
|
// 描述
|
||||||
|
remark?: string
|
||||||
|
}
|
128
src/views/modules/system/menu/MenuEdit.vue
Normal file
128
src/views/modules/system/menu/MenuEdit.vue
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<template>
|
||||||
|
<a-drawer :title="title" width="50%" :mask-closable="showable" @close="handleCancel" :visible="visible" :confirmLoading="confirmLoading">
|
||||||
|
<a-spin :spinning="confirmLoading">
|
||||||
|
<a-form ref="formRef" class="small-from-item" :model="form" :rules="rules" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||||
|
<a-form-item name="id" hidden="true">
|
||||||
|
<a-input v-model="form.id" :disabled="showable" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="菜单名称" name="title">
|
||||||
|
<a-input v-model:value="form.title" :disabled="showable" placeholder="请输入title" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="路由名称" name="name">
|
||||||
|
<a-input v-model:value="form.name" :disabled="showable" placeholder="请输入路由名称" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="访问路径" name="path">
|
||||||
|
<a-input v-model:value="form.path" :disabled="showable" placeholder="请输入访问路径" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="组件名称" name="component">
|
||||||
|
<a-input v-model:value="form.component" :disabled="showable" placeholder="请输入组件名称" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="菜单跳转地址(重定向)" name="redirect">
|
||||||
|
<a-input v-model:value="form.redirect" :disabled="showable" placeholder="请输入重定向" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="排序" name="sortNo">
|
||||||
|
<a-input-number placeholder="请输入菜单排序,可以是小数" :disabled="showable" v-model:value="form.sortNo" style="width: 200px" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-spin>
|
||||||
|
</a-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import useFormEdit from '/@/hooks/bootx/useFormEdit'
|
||||||
|
import { nextTick, reactive, ref } from 'vue'
|
||||||
|
import { Rule } from 'ant-design-vue/lib/form'
|
||||||
|
import { $ref } from 'vue/macros'
|
||||||
|
import { add, get, Menu, update } from '/@/views/modules/system/menu/Menu.api'
|
||||||
|
import { FormEditType } from '/@/enums/formTypeEnum'
|
||||||
|
|
||||||
|
const {
|
||||||
|
initFormModel,
|
||||||
|
handleCancel,
|
||||||
|
search,
|
||||||
|
labelCol,
|
||||||
|
wrapperCol,
|
||||||
|
title,
|
||||||
|
modalWidth,
|
||||||
|
confirmLoading,
|
||||||
|
visible,
|
||||||
|
editable,
|
||||||
|
showable,
|
||||||
|
formEditType,
|
||||||
|
} = useFormEdit()
|
||||||
|
|
||||||
|
const formRef = ref()
|
||||||
|
|
||||||
|
let form = $ref({
|
||||||
|
parentId: null,
|
||||||
|
title: '',
|
||||||
|
name: '',
|
||||||
|
path: '',
|
||||||
|
component: '',
|
||||||
|
redirect: '',
|
||||||
|
sortNo: 0,
|
||||||
|
icon: '',
|
||||||
|
hidden: false,
|
||||||
|
hideChildrenInMenu: false,
|
||||||
|
keepAlive: true,
|
||||||
|
hiddenHeaderContent: false,
|
||||||
|
targetOutside: false,
|
||||||
|
menuType: 0,
|
||||||
|
} as Menu)
|
||||||
|
|
||||||
|
const rules = reactive({
|
||||||
|
title: [{ required: true, message: '请输入菜单或权限名称' }],
|
||||||
|
name: [{ required: true, message: '请输入路由名称' }],
|
||||||
|
path: [{ required: true, message: '请输入菜单路径' }],
|
||||||
|
url: [{ required: true, message: '请输入菜单路径' }],
|
||||||
|
} as Record<string, Rule[]>)
|
||||||
|
|
||||||
|
// 事件
|
||||||
|
const emits = defineEmits(['ok'])
|
||||||
|
// 入口
|
||||||
|
function init(id, editType: FormEditType) {
|
||||||
|
console.log(id)
|
||||||
|
initFormModel(id, editType)
|
||||||
|
resetForm()
|
||||||
|
getInfo(id, editType)
|
||||||
|
}
|
||||||
|
// 获取信息
|
||||||
|
function getInfo(id, editType: FormEditType) {
|
||||||
|
// this.initLoginTypes()
|
||||||
|
if ([FormEditType.Edit, FormEditType.Show].includes(editType)) {
|
||||||
|
confirmLoading.value = true
|
||||||
|
get(id).then(({ data }) => {
|
||||||
|
form = data
|
||||||
|
confirmLoading.value = false
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
confirmLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 保存
|
||||||
|
function handleOk() {
|
||||||
|
formRef.value!.validate().then(async () => {
|
||||||
|
confirmLoading.value = true
|
||||||
|
if (formEditType.value === FormEditType.Add) {
|
||||||
|
await add(form)
|
||||||
|
} else if (formEditType.value === FormEditType.Edit) {
|
||||||
|
await update(form)
|
||||||
|
}
|
||||||
|
confirmLoading.value = false
|
||||||
|
handleCancel()
|
||||||
|
emits('ok')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置表单的校验
|
||||||
|
function resetForm() {
|
||||||
|
nextTick(() => {
|
||||||
|
formRef.value!.resetFields()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
defineExpose({
|
||||||
|
init,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
189
src/views/modules/system/menu/MenuList.vue
Normal file
189
src/views/modules/system/menu/MenuList.vue
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="m-3 p-3 pt-5 bg-white">
|
||||||
|
<a-form class="query" layout="inline">
|
||||||
|
<a-row :gutter="10">
|
||||||
|
<a-col :md="6" :sm="24">
|
||||||
|
<a-form-item label="终端">
|
||||||
|
<a-select v-model:value="clientCode" @change="init" :default-value="clientCode" style="width: 100%">
|
||||||
|
<a-select-option v-for="o in clients" :key="o.code">{{ o.name }}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :md="8" :sm="24">
|
||||||
|
<a-form-item label="查询">
|
||||||
|
<a-input-search
|
||||||
|
v-model:value="searchName"
|
||||||
|
@search="search"
|
||||||
|
@keyup.enter="search"
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入菜单名称、路由名称、请求路径或组件名称"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
<div class="m-3 p-3 bg-white">
|
||||||
|
<vxe-toolbar zoom :refresh="{ query: init }">
|
||||||
|
<template #buttons>
|
||||||
|
<a-button type="primary" @click="add()"> 新建 </a-button>
|
||||||
|
<a-button style="margin-left: 8px" @click="allTreeExpand(true)">展开所有</a-button>
|
||||||
|
<a-button style="margin-left: 8px" @click="allTreeExpand(false)">关闭所有</a-button>
|
||||||
|
</template>
|
||||||
|
</vxe-toolbar>
|
||||||
|
<vxe-table
|
||||||
|
resizable
|
||||||
|
:stripe="false"
|
||||||
|
show-overflow
|
||||||
|
border="inner"
|
||||||
|
ref="xTree"
|
||||||
|
:loading="loading"
|
||||||
|
:tree-config="{ children: 'children' }"
|
||||||
|
:data="tableData"
|
||||||
|
>
|
||||||
|
<vxe-column field="title" title="菜单名称" tree-node />
|
||||||
|
<vxe-column field="name" title="路由名称" />
|
||||||
|
<vxe-column field="menuType" title="菜单类型">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span v-show="String(row.menuType) === '0'">一级菜单</span>
|
||||||
|
<span v-show="String(row.menuType) === '1'">子菜单</span>
|
||||||
|
<span v-show="String(row.menuType) === '2'">按钮/权限</span>
|
||||||
|
</template>
|
||||||
|
</vxe-column>
|
||||||
|
<vxe-column field="path" title="请求路径" />
|
||||||
|
<vxe-column field="sortNo" title="排序" :visible="false" />
|
||||||
|
<vxe-column field="component" title="组件" />
|
||||||
|
<vxe-column field="icon" title="图标" :visible="false">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<div v-if="row.icon !== ''">
|
||||||
|
<!-- <a-icon :type="row.icon" />-->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</vxe-column>
|
||||||
|
<vxe-column title="操作" fixed="right" width="240" :showOverflow="false">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<a href="javascript:" @click="show(row)">查看</a>
|
||||||
|
<a-divider type="vertical" />
|
||||||
|
<a href="javascript:" v-if="!row.admin" @click="edit(row)">编辑</a>
|
||||||
|
<a href="javascript:" v-else disabled>编辑</a>
|
||||||
|
<a-divider type="vertical" />
|
||||||
|
<a href="javascript:" @click="resourceList(row)">权限资源</a>
|
||||||
|
<a-divider type="vertical" />
|
||||||
|
<a-dropdown>
|
||||||
|
<a class="ant-dropdown-link"> 更多 </a>
|
||||||
|
<template #overlay>
|
||||||
|
<a-menu>
|
||||||
|
<a-menu-item>
|
||||||
|
<a @click="addChildren(row)">添加下级</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item>
|
||||||
|
<a @click="copy(row.id)">复制</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item>
|
||||||
|
<a-popconfirm title="是否删除菜单或权限" @confirm="remove(row)" okText="是" cancelText="否">
|
||||||
|
<a href="javascript:" v-if="!row.admin" style="color: red">删除</a>
|
||||||
|
<a href="javascript:" v-else disabled>删除</a>
|
||||||
|
</a-popconfirm>
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
</vxe-column>
|
||||||
|
</vxe-table>
|
||||||
|
<menu-edit ref="menuEdit" @ok="init" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { getAppEnvConfig } from '/@/utils/env'
|
||||||
|
|
||||||
|
import { $ref } from 'vue/macros'
|
||||||
|
import { nextTick, onMounted, ref } from 'vue'
|
||||||
|
import { Client, findAll } from '/@/views/modules/system/client/Client.api'
|
||||||
|
import XEUtils from 'xe-utils'
|
||||||
|
import { menuTree, Menu } from './Menu.api'
|
||||||
|
import { FormEditType } from '/@/enums/formTypeEnum'
|
||||||
|
import MenuEdit from './MenuEdit.vue'
|
||||||
|
const { VITE_GLOB_APP_CLIENT } = getAppEnvConfig()
|
||||||
|
let clientCode = $ref(VITE_GLOB_APP_CLIENT)
|
||||||
|
let searchName = $ref()
|
||||||
|
let loading = $ref(false)
|
||||||
|
let treeExpand = $ref(false)
|
||||||
|
let clients = $ref([] as Client[])
|
||||||
|
let remoteTableData = $ref([] as Menu[])
|
||||||
|
let tableData = $ref([] as Menu[])
|
||||||
|
let xTree = ref()
|
||||||
|
let menuEdit = ref()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
initClients()
|
||||||
|
init()
|
||||||
|
})
|
||||||
|
|
||||||
|
async function initClients() {
|
||||||
|
const { data } = await findAll()
|
||||||
|
clients = data
|
||||||
|
}
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
loading = true
|
||||||
|
menuTree(clientCode).then((res) => {
|
||||||
|
remoteTableData = res.data
|
||||||
|
search()
|
||||||
|
loading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function add() {
|
||||||
|
menuEdit.value.init(null, FormEditType.Add)
|
||||||
|
}
|
||||||
|
function edit(record: Menu) {
|
||||||
|
menuEdit.value.init(record.id, FormEditType.Edit)
|
||||||
|
}
|
||||||
|
function show(record: Menu) {
|
||||||
|
menuEdit.value.init(record.id, FormEditType.Show)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索
|
||||||
|
*/
|
||||||
|
function search() {
|
||||||
|
const search = XEUtils.toValueString(searchName).trim().toLowerCase()
|
||||||
|
if (search) {
|
||||||
|
const searchProps = ['name', 'title', 'path', 'component']
|
||||||
|
tableData = XEUtils.searchTree(remoteTableData, (item) =>
|
||||||
|
searchProps.some((key) => XEUtils.toValueString(item[key]).toLowerCase().indexOf(search) > -1),
|
||||||
|
)
|
||||||
|
// 搜索状态默认展开
|
||||||
|
treeExpand = true
|
||||||
|
} else {
|
||||||
|
tableData = remoteTableData
|
||||||
|
}
|
||||||
|
nextTick(() => {
|
||||||
|
xTree.value.setAllTreeExpand(treeExpand)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 展开or关闭
|
||||||
|
*/
|
||||||
|
function allTreeExpand(value) {
|
||||||
|
nextTick(() => {
|
||||||
|
xTree.value.setAllTreeExpand(treeExpand)
|
||||||
|
})
|
||||||
|
treeExpand = value
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.query {
|
||||||
|
.ant-form-item {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.ant-row {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
2
types/config.d.ts
vendored
2
types/config.d.ts
vendored
@@ -160,5 +160,5 @@ export interface GlobEnvConfig {
|
|||||||
// Upload url
|
// Upload url
|
||||||
VITE_GLOB_UPLOAD_URL?: string
|
VITE_GLOB_UPLOAD_URL?: string
|
||||||
// 终端类型
|
// 终端类型
|
||||||
VITE_GLOB_APP_CLIENT?: string
|
VITE_GLOB_APP_CLIENT: string
|
||||||
}
|
}
|
||||||
|
2
types/web.d.ts
vendored
2
types/web.d.ts
vendored
@@ -35,5 +35,5 @@ export interface TablePageModel<T = any> {
|
|||||||
* 基础实体对象
|
* 基础实体对象
|
||||||
*/
|
*/
|
||||||
export interface BaseEntity {
|
export interface BaseEntity {
|
||||||
id: number | null
|
id?: number | null | undefined
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user