Browse Source

feat: 菜单表单

Gaokun Wang 4 weeks ago
parent
commit
2f0c6008ea

+ 5 - 1
src/router/modules/dynamicRouter.ts

@@ -5,7 +5,11 @@ import { useOptionsStore } from '@/stores/modules/options'
 import type { RouteRecordRaw } from 'vue-router'
 
 // 引入 views 文件夹下所有 vue 文件
-const modules = import.meta.glob('@/views/**/*.vue')
+export const modules = import.meta.glob('@/views/**/*.vue')
+
+export const buildComponentPaths = () => {
+  return Object.keys(modules).map(key => key.replace('/src/views', ''))
+}
 
 /**
  * @description 初始化动态路由

+ 2 - 0
src/types/auto-components.d.ts

@@ -45,12 +45,14 @@ declare module 'vue' {
     ElMain: typeof import('element-plus/es')['ElMain']
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
+    ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
     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']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
+    ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSpace: typeof import('element-plus/es')['ElSpace']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']

+ 3 - 1
src/views/login/index.vue

@@ -22,7 +22,7 @@
 
 <script lang="ts" setup>
 import { ElMessage, type FormInstance } from 'element-plus'
-import { useUserStore } from '@/stores'
+import { useAuthStore, useUserStore } from '@/stores'
 import router from '@/router'
 import { LocationQuery } from 'vue-router'
 import { initDynamicRouter } from '@/router/modules/dynamicRouter'
@@ -30,6 +30,7 @@ const loginFormRef = ref<FormInstance>()
 const loading = ref(false)
 const route = useRoute()
 const userStore = useUserStore()
+const authStore = useAuthStore()
 const loginForm = reactive({
   account: 'superadmin',
   password: 'admin123',
@@ -54,6 +55,7 @@ const submitForm = (formEl: FormInstance | undefined) => {
     if (valid) {
       userStore.userLogin({ ...loginForm }).then(async res => {
         if (res.code === 200) {
+          authStore.clear()
           await initDynamicRouter()
           const { path, queryParams } = parseRedirect()
           router.push({ path: path, query: queryParams })

+ 1 - 1
src/views/system/dict/index.vue

@@ -60,7 +60,7 @@ const changeTree = (val: string) => {
 // 刷新树表
 const refreshTree = () => {
   treeFilterRef.value?.refresh()
-  // reset()
+  reset()
 }
 
 // 表格配置项

+ 102 - 54
src/views/system/menu/components/MenuDrawer.vue

@@ -11,60 +11,102 @@
     </template>
 
     <el-form ref="ruleFormRef" label-width="100px" label-suffix=" :" :rules="rules" :model="drawerProps.row" @submit.enter.prevent="handleConfirm">
-      <el-form-item label="上级" prop="parentId">
-        <el-tree-select
-          v-model="drawerProps.row.parentId"
-          :data="treeData"
-          check-strictly
-          placeholder="请选择上级"
-          :render-after-expand="false"
-          clearable
-          :default-expand-all="true"
-          :props="treeProps" />
-      </el-form-item>
-      <el-form-item label="菜单名称" prop="title">
-        <el-input v-model="drawerProps.row.title" placeholder="请填写名称" clearable />
-      </el-form-item>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="上级" prop="parentId">
+            <el-tree-select
+              v-model="drawerProps.row.parentId"
+              :data="treeData"
+              check-strictly
+              placeholder="请选择上级"
+              :render-after-expand="false"
+              clearable
+              :default-expand-all="true"
+              :props="treeProps" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="菜单名称" prop="title">
+            <el-input v-model="drawerProps.row.title" placeholder="请填写名称" clearable />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="路由名称" prop="name">
+            <el-input v-model="drawerProps.row.name" placeholder="请填写路由名称" clearable>
+              <template #prepend>setup name=</template>
+            </el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item :label="drawerProps.row.menuType === 'L' ? '外联地址' : '路由地址'" prop="path">
+            <el-input v-model="drawerProps.row.path" placeholder="请填写路由地址" clearable />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <!-- <el-form-item label="路由参数" prop="queryParam">
+        <el-input v-model="drawerProps.row.queryParam" placeholder="请填写路由参数" clearable />
+      </el-form-item> -->
       <el-form-item label="菜单类型" prop="menuType">
-        <el-input v-model="drawerProps.row.menuType" placeholder="请填写名称" clearable />
-      </el-form-item>
-      <el-form-item label="图标" prop="icon">
-        <el-input v-model="drawerProps.row.icon" placeholder="请选择图标" clearable />
-      </el-form-item>
-      <el-form-item label="路由名称" prop="name">
-        <el-input v-model="drawerProps.row.name" placeholder="请填写路由名称" clearable />
-      </el-form-item>
-      <el-form-item label="路由地址" prop="path">
-        <el-input v-model="drawerProps.row.path" placeholder="请填写路由地址" clearable />
-      </el-form-item>
-      <el-form-item label="组件路径" prop="component">
-        <el-input v-model="drawerProps.row.component" placeholder="请填写组件路径" clearable />
-      </el-form-item>
-      <el-form-item label="显示状态" prop="visible">
-        <el-radio-group v-model="drawerProps.row.visible">
-          <el-radio-button :value="item.dictValue" v-for="(item, index) in commonStatus" :key="index" :label="item.dictLabel" />
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="是否全屏" prop="displayLayout">
-        <el-radio-group v-model="drawerProps.row.displayLayout">
-          <el-radio-button :value="item.dictValue" v-for="(item, index) in commonStatus" :key="index" :label="item.dictLabel" />
+        <el-radio-group v-model="drawerProps.row.menuType">
+          <el-radio-button :value="item.dictValue" v-for="(item, index) in menuTypes" :key="index" :label="item.dictLabel" />
         </el-radio-group>
       </el-form-item>
-      <el-form-item label="固定标签页" prop="affix">
-        <el-radio-group v-model="drawerProps.row.affix">
-          <el-radio-button :value="item.dictValue" v-for="(item, index) in commonStatus" :key="index" :label="item.dictLabel" />
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="是否缓存" prop="keepLive">
-        <el-radio-group v-model="drawerProps.row.keepLive">
-          <el-radio-button :value="item.dictValue" v-for="(item, index) in commonStatus" :key="index" :label="item.dictLabel" />
-        </el-radio-group>
+      <el-form-item label="图标" prop="icon">
+        <IconChoose v-model="icon" placeholder="请填写图标" clearable />
       </el-form-item>
-      <el-form-item label="状态" prop="status">
-        <el-radio-group v-model="drawerProps.row.status">
-          <el-radio-button :value="item.dictValue" v-for="(item, index) in commonStatus" :key="index" :label="item.dictLabel" />
-        </el-radio-group>
+      <el-form-item v-if="drawerProps.row.menuType === 'M'" label="组件路径" prop="component">
+        <el-select v-model="drawerProps.row.component" filterable allow-create placeholder="请选择或填写组件路径">
+          <el-option v-for="item in componentPaths" :key="item" :label="item" :value="item" />
+        </el-select>
       </el-form-item>
+      <el-row :gutter="20">
+        <el-col :span="8">
+          <el-form-item label="显示状态" prop="visible">
+            <el-radio-group v-model="drawerProps.row.visible">
+              <el-radio-button :value="item.dictValue" v-for="(item, index) in showStatus" :key="index" :label="item.dictLabel" />
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="状态" prop="status">
+            <el-radio-group v-model="drawerProps.row.status">
+              <el-radio-button :value="item.dictValue" v-for="(item, index) in commonStatus" :key="index" :label="item.dictLabel" />
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="排序" prop="orderNum">
+            <el-input-number v-model="drawerProps.row.orderNum" :precision="0" :min="0" :max="999999" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="20" v-if="drawerProps.row.menuType === 'M'">
+        <el-col :span="8">
+          <el-form-item label="是否缓存" prop="keepLive">
+            <el-radio-group v-model="drawerProps.row.keepLive">
+              <el-radio-button :value="item.dictValue" v-for="(item, index) in YES_NO" :key="index" :label="item.dictLabel" />
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="是否Layout" prop="displayLayout">
+            <el-radio-group v-model="drawerProps.row.displayLayout">
+              <el-radio-button :value="item.dictValue" v-for="(item, index) in YES_NO" :key="index" :label="item.dictLabel" />
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="固定标签页" prop="affix">
+            <el-radio-group v-model="drawerProps.row.affix">
+              <el-radio-button :value="item.dictValue" v-for="(item, index) in YES_NO" :key="index" :label="item.dictLabel" />
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+      </el-row>
+
       <el-form-item label="备注" prop="remark">
         <el-input v-model="drawerProps.row.remark" placeholder="请填写备注" clearable />
       </el-form-item>
@@ -80,14 +122,19 @@
 </template>
 
 <script setup lang="ts" name="MenuForm">
-import { MenuBO } from '@/api/interface/system/menu'
 import MenuApi from '@/api/module/system/menu'
 import { ResultEnum } from '@/enums/HttpEnum'
 import { FormInstance } from 'element-plus'
 import { useDictOptions } from '@/hooks'
-import { MenuTreeVO } from '@/api/interface/system/menu'
-
+import { MenuBO, MenuTreeVO } from '@/api/interface/system/menu'
+import { buildComponentPaths } from '@/router/modules/dynamicRouter'
+const componentPaths = buildComponentPaths()
 const commonStatus = useDictOptions('COMMON_STATUS')
+const YES_NO = useDictOptions('YES_NO')
+const showStatus = useDictOptions('SHOW_STATUS')
+const menuTypes = useDictOptions('MENU_TYPE')
+const icon = ref('')
+
 const rules = reactive({
   account: [{ required: true, message: '请填写账号' }],
   menuName: [{ required: true, message: '请填写姓名' }],
@@ -124,6 +171,8 @@ const acceptParams = (params: EcoDrawerProps) => {
   drawerVisible.value = true
   loadTree()
   drawerProps.value.row.status = drawerProps.value.row.status || '1'
+  drawerProps.value.row.orderNum = drawerProps.value.row.orderNum || 0
+  icon.value = drawerProps.value.row.icon || ''
 }
 
 const loadTree = () => {
@@ -145,8 +194,7 @@ const handleConfirm = () => {
   ruleFormRef.value!.validate(async valid => {
     if (!valid) return
     try {
-      console.log(drawerProps.value.row)
-
+      drawerProps.value.row.icon = icon.value
       const { code } = await drawerProps.value.api!(drawerProps.value.row)
       if (code == ResultEnum.SUCCESS) {
         ElMessage.success({ message: `${drawerProps.value.title}成功!` })

+ 1 - 2
src/views/system/menu/index.vue

@@ -6,7 +6,6 @@
       row-key="menuId"
       :pagination="false"
       :indent="20"
-      stripe
       :columns="columns"
       :request-api="getTableList"
       :default-expand-all="defaultExpandAllKey">
@@ -28,7 +27,7 @@
         <el-button v-if="row.isLock !== '1'" type="primary" link icon="Delete" @click="deleteRow(row)"> 删除 </el-button>
       </template>
     </ProTable>
-    <MenuDrawer ref="drawerRef" size="40%" />
+    <MenuDrawer ref="drawerRef" size="50%" />
   </div>
 </template>
 <script lang="tsx" setup name="MenuManage">