Browse Source

路由问题

xiaochan 1 year ago
parent
commit
1499f882c4

+ 7 - 1
src/App.vue

@@ -22,7 +22,6 @@ import {formatDateToStr} from '@/utils/moment-utils'
 import {ElLink} from 'element-plus'
 import JsDialogComp from "@/components/js-dialog-comp/JsDialogComp.vue";
 import {CyMessageBox} from "@/components/cy/message-box";
-import {isDev} from "@/utils/public";
 
 const store = useStore()
 
@@ -621,4 +620,11 @@ input[type=number]::-webkit-outer-spin-button {
   @include cy-card;
 }
 
+.layout_card_main {
+  width: 100%;
+  height: 100%;
+  @include cy-card;
+}
+
+
 </style>

+ 18 - 1
src/api/settings/menu-settings.ts

@@ -7,7 +7,7 @@ export interface IntergrationMenu {
     path: string;
     icon: string;
     name: string;
-    parentId?: number;
+    parentId?: number | null;
     metaTitle: string;
     metaHideTabs?: boolean;
     metaPassRule?: boolean;
@@ -20,6 +20,7 @@ export interface IntergrationMenu {
     pathParams?: string;
     children?: IntergrationMenu[];
     completePath?: string
+    cascaders?: number[]
 }
 
 export function getMenuSettings() {
@@ -35,3 +36,19 @@ export function getUserMenu() {
         url: "/menuSettings/getUserMenu",
     })
 }
+
+export function updateMenuSettings(menuList: IntergrationMenu) {
+    return requestV2({
+        method: "post",
+        url: '/menuSettings/updateMenuSettings',
+        data: menuList
+    });
+}
+
+export function deleteMenuSettings(id: number) {
+    return requestV2({
+        method: "get",
+        url: "/menuSettings/deleteMenuSettings",
+        params: id
+    })
+}

+ 1 - 1
src/layout/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-container style="height: 100vh">
+  <el-container style="height: 100%;width: 100%">
     <div class="mask" v-show="!isCollapse && !contentFullScreen" @click="hideMenu"></div>
     <el-aside :width="isCollapse ? '50px' : '260px'"
               class="layout_aside"

+ 7 - 22
src/router/createNode.js

@@ -10,28 +10,13 @@ export function createNameComponent(component) {
                 const name = (comm.default.name || 'vueAdminBox') + '$' + Date.now()
                 const tempComm = defineComponent({
                     name,
-                    setup() {
-                        const isReload = ref(false)
-                        return {
-                            isReload,
-                        }
-                    },
-                    render: function () {
-                        if (this.isReload) {
-                            return h('div', {
-                                style: {
-                                    height: '100%',
-                                    width: '100%'
-                                }
-                            }, [h(reload)])
-                        } else {
-                            return h('div', {
-                                style: {
-                                    height: '100%',
-                                    width: '100%'
-                                }
-                            }, [createVNode(comm.default)])
-                        }
+                    render() {
+                        return h('div', {
+                            style: {
+                                height: '100%',
+                                width: '100%'
+                            }
+                        }, [createVNode(comm.default)])
                     },
                 })
                 res(tempComm)

+ 22 - 3
src/router/index.ts

@@ -19,9 +19,12 @@ import {userInfoStore} from "@/utils/store-public";
 import {stringIsBlank} from "@/utils/blank-utils";
 import XEUtils from "xe-utils";
 
+const whiteNameRouting = []
+
 function dashboardRouter(data: Array<RouteRecordRaw>) {
     data.forEach((item) => {
         XEUtils.set(item, "meta.needToken", false)
+        whiteNameRouting.push(item.path)
         if (item.children && item.children.length > 0) {
             dashboardRouter(item.children)
         }
@@ -67,6 +70,7 @@ function createNameComponent(item) {
                 const tmp = defineComponent({
                     name: item.name,
                     render() {
+                        let children = [createVNode(res.default)]
                         const style = {
                             height: '100%',
                             width: '100%',
@@ -78,10 +82,17 @@ function createNameComponent(item) {
                             props.class = 'cy_card'
                         }
                         if (item.mainOverflowAuto) {
-                            style.overflow = "auto";
+                            children = [
+                                h('div', {
+                                    style: {
+                                        height: '100%',
+                                        width: '100%',
+                                        overflow: 'auto'
+                                    }
+                                }, [createVNode(res.default)])
+                            ]
                         }
-
-                        return h('div', props, [createVNode(res.default)]);
+                        return h('div', props, children);
                     }
                 })
                 resolve(tmp)
@@ -132,6 +143,14 @@ router.beforeEach(async (to, _from, next) => {
             next(...arg);
         }
 
+        for (let i = 0; i < whiteNameRouting.length; i++) {
+            const tmp: string = whiteNameRouting[i]
+            if (tmp.startsWith(to.path)) {
+                tmpNext()
+                return
+            }
+        }
+
         if (!asyncFinished) {
             await beforeAddRoutes()
             tmpNext({path: to.path, query: to.query, replace: true});

+ 10 - 1
src/utils/request.js

@@ -1,5 +1,5 @@
 import axios from 'axios'
-import {ElMessage, ElMessageBox} from 'element-plus'
+import {ElMessage, ElMessageBox, ElNotification} from 'element-plus'
 import router from '@/router'
 import store from '@/store'
 import {startLoading, endLoading} from './loading'
@@ -81,6 +81,15 @@ service.interceptors.response.use(
             })
             response.data.data
         }
+        if (response.data.code === 203) {
+            ElNotification({
+                type: 'success',
+                message: response.data.message,
+                duration: 3000,
+                title: "成功"
+            })
+            response.data.data
+        }
 
 
         if (response.data.code > 1000 && response.data.code < 2000) {

+ 76 - 37
src/views/settings/menu-settings/MenuSettings.vue

@@ -1,62 +1,101 @@
 <script setup lang="ts">
 import {onMounted, ref} from "vue";
-import {getMenuSettings, IntergrationMenu} from "@/api/settings/menu-settings";
-import {ElButton, ElTable, ElButtonGroup} from "element-plus";
+import {deleteMenuSettings, getMenuSettings, IntergrationMenu} from "@/api/settings/menu-settings";
+import {ElButton, ElButtonGroup} from "element-plus";
 import Dialog from "@/views/settings/menu-settings/dialog.vue";
 
 const menuTreeData = ref<IntergrationMenu[]>([])
-const dialog = ref()
+const dialogRef = ref()
 
 function modify(row) {
-  dialog.value.openDialog(row)
+  dialogRef.value.openDialog(row)
 }
 
-onMounted(async () => {
+async function loadingData() {
   menuTreeData.value = await getMenuSettings()
+}
+
+function delById(id: number) {
+  deleteMenuSettings(id);
+  loadingData();
+}
+
+function addRouterClick(row: IntergrationMenu | null = null) {
+  let cascaders = []
+  if (row !== null) {
+    if (row.parentId === null) {
+      cascaders = [row.id];
+    } else {
+      if (row.type === 1) {
+        cascaders = [...row.cascaders, row.id];
+      } else {
+        cascaders = [...row.cascaders];
+      }
+    }
+  }
+
+  dialogRef.value.openDialog({
+    children: [],
+    component: "",
+    icon: "",
+    id: null,
+    metaHideTabs: false,
+    metaPassRule: false,
+    metaTitle: "",
+    name: "",
+    cascaders,
+    parentId: 0,
+    path: "",
+    pathParams: "",
+    redirect: "",
+    sort: 0,
+    type: 0
+  });
+}
+
+onMounted(() => {
+  loadingData()
 })
 </script>
 
 <template>
   <vxe-table
+      border="inner"
+      height="auto"
       show-overflow
       :row-config="{isHover: true, useKey: true}"
       :column-config="{resizable: true}"
-      :tree-config="{transform: true, rowField: 'id', parentField: 'parentId', line: true}"
+      :tree-config="{  rowField: 'id', parentField: 'parentId', showLine: true}"
       :data="menuTreeData">
-    <vxe-column field="metaTitle" title="标题" tree-node></vxe-column>
+    <vxe-column field="metaTitle" title="标题" tree-node>
+      <template #default="{row}">
+        <span :class="row.icon"></span>
+        {{ row.metaTitle }}
+      </template>
+    </vxe-column>
     <vxe-column field="path" title="路径"></vxe-column>
     <vxe-column field="component" title="组件路径"></vxe-column>
-    <vxe-column title="操作" fixed="right"></vxe-column>
+    <vxe-column title="操作" fixed="right" width="220">
+      <template #header>
+        <el-button
+            type="primary"
+            @click="addRouterClick()"
+        >
+          新增
+        </el-button>
+      </template>
+      <template #default="{row}">
+        <el-button-group>
+          <el-button text type="primary" @click="addRouterClick(row)">新增</el-button>
+          <el-button text type="primary" @click="modify(row)">修改</el-button>
+          <el-button text type="primary" @click="delById(row.id)">删除</el-button>
+        </el-button-group>
+      </template>
+    </vxe-column>
   </vxe-table>
-
-  <!--  <el-table-->
-  <!--      class="no_el-table"-->
-  <!--      :data="menuTreeData"-->
-  <!--      highlight-current-row-->
-  <!--      height="100%"-->
-  <!--      style="width: 100%"-->
-  <!--      row-key="id"-->
-  <!--      :tree-props="{ children: 'children' }"-->
-  <!--  >-->
-  <!--    <el-table-column prop="metaTitle" label="标题">-->
-  <!--      <template #default="{row}">-->
-  <!--        <span :class="`${row.icon}`"></span>-->
-  <!--        <span>&nbsp;&nbsp;&nbsp;{{ row.metaTitle }}</span>-->
-  <!--      </template>-->
-  <!--    </el-table-column>-->
-  <!--    <el-table-column prop="path" label="路径"/>-->
-  <!--    <el-table-column prop="component" label="组件路径"/>-->
-  <!--    <el-table-column label="操作">-->
-  <!--      <template #default="{row}">-->
-  <!--        <el-button-group>-->
-  <!--          <el-button type="primary" size="large" link @click="modify(row)">修改</el-button>-->
-  <!--          <el-button type="danger" size="large" link>删除</el-button>-->
-  <!--        </el-button-group>-->
-  <!--      </template>-->
-  <!--    </el-table-column>-->
-  <!--  </el-table>-->
-
-  <Dialog :menuTreeData="menuTreeData" ref="dialog"/>
+  <Dialog :cascaderData="menuTreeData"
+          @saveCallback="loadingData()"
+          ref="dialogRef"/>
 </template>
 
 <style lang="scss">

+ 123 - 28
src/views/settings/menu-settings/dialog.vue

@@ -1,7 +1,6 @@
 <script setup lang="ts">
 import {ref} from "vue";
-import {isDev} from "@/utils/public";
-import {IntergrationMenu} from "@/api/settings/menu-settings";
+import {IntergrationMenu, updateMenuSettings} from "@/api/settings/menu-settings";
 import {
   ElButton,
   ElCascader,
@@ -13,21 +12,28 @@ import {
   ElInput,
   ElPopover,
   ElInputNumber,
-  ElSwitch
+  ElSwitch,
+  FormRules,
+  ElSelectV2
 } from "element-plus";
 import XEUtils from "xe-utils";
 import icon from '@/icons/iconfont.css'
 import {eachAndReturnList} from "@/utils/cyRefList";
+import {useCompRef} from "@/utils/useCompRef";
 
 const props = defineProps<{
-  menuTreeData: any[],
+  cascaderData: any[],
+}>()
+
+const emits = defineEmits<{
+  (e: "saveCallback"): void,
 }>()
 
 declare type VueIntergrationPlatformMenu = {
-  parentCascader: number[]
+  cascaders: number[]
 } & IntergrationMenu
 
-const showDialog = ref(isDev)
+const showDialog = ref(false)
 const currentData = ref<VueIntergrationPlatformMenu>({
   children: [],
   component: "",
@@ -37,7 +43,7 @@ const currentData = ref<VueIntergrationPlatformMenu>({
   metaPassRule: false,
   metaTitle: "",
   name: "",
-  parentCascader: [],
+  cascaders: [],
   parentId: 0,
   path: "",
   pathParams: "",
@@ -46,18 +52,65 @@ const currentData = ref<VueIntergrationPlatformMenu>({
   type: 0
 })
 
-function save() {
-  if (currentData.value.parentCascader.length > 0) {
-    currentData.value.parentId = currentData.value.parentCascader[currentData.value.parentCascader.length - 1]
+const fromRef = useCompRef(ElForm)
+
+
+const rules: FormRules<VueIntergrationPlatformMenu> = reactive({})
+type D = keyof VueIntergrationPlatformMenu
+
+function addRequired(key: D[]) {
+  key.forEach(item => {
+    rules[item] = [{required: true, trigger: 'change', message: '必填'}]
+  })
+}
+
+addRequired(['path', 'component', 'name', 'metaTitle'])
+
+async function save() {
+  await fromRef.value?.validate()
+  if (currentData.value.cascaders.length > 0) {
+    currentData.value.parentId = currentData.value.cascaders[currentData.value.cascaders.length - 1]
   }
+  await updateMenuSettings(currentData.value)
+  emits('saveCallback')
+  showDialog.value = false
 }
 
+const icons = ref([])
+const routerKey = ref([])
+
+const layout = [
+  {
+    value: 'Layout',
+    label: 'Layout'
+  },
+  {
+    value: 'EmptyRouter',
+    label: 'EmptyRouter'
+  }
+]
+
+function dialogOpen() {
+  const regex = /.(?<icon>.*):before/g;
+  const matches = (icon as string).matchAll(regex);
+  icons.value = eachAndReturnList((matches as string[]), (item) => {
+    return item[1]
+  })
+
+  const view = import.meta.glob('/src/views/**/*.{vue,tsx}');
+
+  routerKey.value = eachAndReturnList(Object.keys(view), (item) => {
+    const tmp = item.replace("/src", "..")
+    return {
+      value: tmp,
+      label: tmp,
+    }
+  })
+
+  routerKey.value.push(...layout)
+
+}
 
-const regex = /.(?<icon>.*):before/g;
-const matches = (icon as string).matchAll(regex);
-const icons = ref(eachAndReturnList((matches as string[]), (item) => {
-  return item[1]
-}))
 
 function iconClick(icon) {
   currentData.value.icon = `iconfont ${icon}`
@@ -66,7 +119,6 @@ function iconClick(icon) {
 defineExpose({
   openDialog: (row: VueIntergrationPlatformMenu) => {
     currentData.value = XEUtils.clone(row, true)
-    currentData.value.parentCascader = []
     showDialog.value = true;
   }
 })
@@ -75,43 +127,54 @@ defineExpose({
 
 <template>
   <el-dialog v-model="showDialog"
+             @open="dialogOpen"
              title="菜单编辑"
              destroy-on-close
              draggable>
-    <el-form label-width="80px" size="default">
+    <el-form
+        ref="fromRef"
+        :model="currentData"
+        :rules="rules"
+        label-width="80px"
+        size="default">
       <el-row :gutter="10">
         <el-col :span="24">
-          <el-form-item label="父节点">
+          <el-form-item label="父节点" prop="cascaders">
             <el-cascader
-                v-model="currentData.parentCascader"
+                v-model="currentData.cascaders"
                 style="width: 100%"
                 :props="{ checkStrictly: true, value: 'id', label: 'metaTitle' }"
-                :options="menuTreeData"
+                :options="cascaderData"
                 clearable/>
           </el-form-item>
         </el-col>
 
-
         <el-col :span="24">
-          <el-form-item label="完整路径">
+          <el-form-item label="路径" prop="path">
             <el-input v-model="currentData.path"/>
           </el-form-item>
         </el-col>
 
         <el-col :span="24">
-          <el-form-item label="组件路径">
-            <el-input v-model="currentData.component"/>
+          <el-form-item label="组件路径" prop="component">
+            <el-select-v2
+                v-model="currentData.component"
+                :options="routerKey"
+                style="width: 100%"
+                filterable
+            />
+
           </el-form-item>
         </el-col>
 
         <el-col :span="24">
-          <el-form-item label="路径参数">
+          <el-form-item label="路径参数" prop="pathParams">
             <el-input v-model="currentData.pathParams"/>
           </el-form-item>
         </el-col>
 
         <el-col :span="12">
-          <el-form-item label="类型">
+          <el-form-item label="类型" prop="type">
             <el-switch v-model="currentData.type"
                        :active-value="1"
                        :inactive-value="2"
@@ -122,7 +185,7 @@ defineExpose({
         </el-col>
 
         <el-col :span="12">
-          <el-form-item label="路由名称">
+          <el-form-item label="路由名称" prop="name">
             <el-input v-model="currentData.name"
                       clearable maxlength="50"/>
           </el-form-item>
@@ -155,7 +218,7 @@ defineExpose({
         </el-col>
 
         <el-col :span="12">
-          <el-form-item label="菜单名称">
+          <el-form-item label="菜单名称" prop="metaTitle">
             <el-input v-model="currentData.metaTitle"
                       clearable maxlength="50"/>
           </el-form-item>
@@ -196,6 +259,38 @@ defineExpose({
           </el-form-item>
         </el-col>
 
+        <el-col :span="12">
+          <el-form-item label="卡片类型">
+            <el-switch v-model="currentData.mainCard"
+                       :active-value="1"
+                       :inactive-value="0"
+                       active-text="是"
+                       inactive-text="否"
+            />
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="12">
+          <el-form-item label="超出滚动">
+            <el-switch v-model="currentData.mainOverflowAuto"
+                       :active-value="1"
+                       :inactive-value="0"
+                       active-text="是"
+                       inactive-text="否"
+            />
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="12">
+          <el-form-item label="无需登录">
+            <el-switch v-model="currentData.metaNeedToken"
+                       :active-value="1"
+                       :inactive-value="0"
+                       active-text="是"
+                       inactive-text="否"
+            />
+          </el-form-item>
+        </el-col>
 
       </el-row>
     </el-form>