浏览代码

feat: 系统配置页面

wanggaokun 1 年之前
父节点
当前提交
988e0bc6ab

+ 3 - 11
src/api/modules/system/config.ts

@@ -62,19 +62,11 @@ export const delConfigApi = (configId: any) => {
 }
 
 /**
- * @name 下载模板
+ * @name 刷新参数缓存
  * @returns returns
  */
-export const importTemplateApi = () => {
-  return http.downloadPost('/system/config/importTemplate', {})
-}
-
-/**
- * @name 导入数据
- * @returns returns
- */
-export const importConfigDataApi = (data: any) => {
-  return http.post('/system/config/importData', data)
+export const refreshCacheApi = () => {
+  return http.delete<any>(`/system/config/refreshCache`)
 }
 
 /**

+ 1 - 1
src/components/ErrorMessage/403.vue

@@ -15,5 +15,5 @@ const router = useRouter()
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/components/ErrorMessage/404.vue

@@ -14,5 +14,5 @@ const router = useRouter()
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/components/ErrorMessage/500.vue

@@ -14,5 +14,5 @@ const router = useRouter()
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/components/Highlight/index.vue

@@ -27,5 +27,5 @@ onMounted(() => {
 })
 </script>
 <style lang="scss" scoped>
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/components/ImportExcel/index.vue

@@ -163,5 +163,5 @@ defineExpose({
 })
 </script>
 <style lang="scss" scoped>
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/components/Loading/index.vue

@@ -9,5 +9,5 @@
 <script setup lang="ts" name="Loading"></script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/components/ProForm/index.vue

@@ -201,5 +201,5 @@ defineExpose({
 })
 </script>
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/components/SelectFilter/index.vue

@@ -102,5 +102,5 @@ const select = (item: SelectDataProps, option: OptionsProps) => {
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/components/SelectIcon/index.vue

@@ -96,5 +96,5 @@ const iconsList = computed((): { [key: string]: any } => {
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 2 - 1
src/components/SvgIcon/index.vue

@@ -45,7 +45,8 @@ const svgClass = computed(() => {
   position: relative;
   width: 1em;
   height: 1em;
-  margin-right: 5px;
+
+  // margin-right: 5px;
   color: var(--color);
   fill: currentColor;
 }

+ 1 - 1
src/components/TreeFilter/index.vue

@@ -141,5 +141,5 @@ defineExpose({ treeData, treeAllData, treeRef })
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/components/Upload/File.vue

@@ -16,7 +16,7 @@
       :accept="fileType.join(',')"
       :headers="headers"
     >
-      <el-button icon="icon" type="primary">{{ text }}</el-button>
+      <el-button icon="Upload" type="primary">{{ text }}</el-button>
     </el-upload>
     <!-- 上传提示 -->
     <div class="el-upload__tip" v-if="showTip">

+ 1 - 1
src/components/Upload/FileS3.vue

@@ -16,7 +16,7 @@
       :accept="fileType.join(',')"
       :headers="headers"
     >
-      <el-button icon="icon" type="primary">{{ text }}</el-button>
+      <el-button icon="Upload" type="primary">{{ text }}</el-button>
     </el-upload>
     <!-- 上传提示 -->
     <div class="el-upload__tip" v-if="showTip">

+ 1 - 1
src/components/WangEditor/index.vue

@@ -153,5 +153,5 @@ defineExpose({
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/layouts/LayoutClassic/index.vue

@@ -50,5 +50,5 @@ const activeMenu = computed(() => (route.meta.activeMenu ? route.meta.activeMenu
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/layouts/LayoutColumns/index.vue

@@ -89,5 +89,5 @@ const changeSubMenu = (item: Menu.MenuOptions) => {
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/layouts/LayoutTransverse/index.scss

@@ -15,8 +15,8 @@
       margin-right: 30px;
       .logo-img {
         width: 28px;
-        object-fit: contain;
         margin-right: 6px;
+        object-fit: contain;
       }
       .logo-text {
         font-size: 21.5px;

+ 1 - 1
src/layouts/LayoutTransverse/index.vue

@@ -51,5 +51,5 @@ const handleClickMenu = (subItem: Menu.MenuOptions) => {
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/layouts/LayoutVertical/index.vue

@@ -45,5 +45,5 @@ const activeMenu = computed(() => (route.meta.activeMenu ? route.meta.activeMenu
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/layouts/components/Footer/index.vue

@@ -5,5 +5,5 @@
 </template>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/layouts/components/Main/index.vue

@@ -69,5 +69,5 @@ onBeforeUnmount(() => {
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/layouts/components/Tabs/index.vue

@@ -105,5 +105,5 @@ const tabRemove = (fullPath: TabPaneName) => {
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/layouts/components/ThemeDrawer/index.vue

@@ -156,5 +156,5 @@ mittBus.on('openThemeDrawer', () => (drawerVisible.value = true))
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/routers/index.ts

@@ -45,7 +45,7 @@ const router = createRouter({
 
 /**
  * @description 路由拦截 beforeEach
- * */
+ **/
 router.beforeEach(async (to, from, next) => {
   // 1.NProgress 开始
   NProgress.start()

+ 1 - 3
src/routers/modules/dynamicRouter.ts

@@ -20,7 +20,6 @@ export const initDynamicRouter = async () => {
   try {
     // 1.获取菜单列表 && 按钮权限列表
     await authStore.getAuthMenuList()
-
     // 2.判断当前用户有没有菜单权限
     if (!authStore.authMenuListGet.length) {
       ElNotification({
@@ -35,12 +34,10 @@ export const initDynamicRouter = async () => {
     }
 
     // 3.添加动态路由
-
     authStore.flatMenuListGet.forEach(item => {
       if (item.component === 'Layout' || item.component === 'ParentView') {
         delete item.component
       }
-
       item.children && delete item.children
       if (item.component && typeof item.component == 'string') {
         item.component = loadView(item.component)
@@ -51,6 +48,7 @@ export const initDynamicRouter = async () => {
         router.addRoute('layout', item as unknown as RouteRecordRaw)
       }
     })
+    console.log('router', router.getRoutes())
   } catch (error) {
     // 当按钮 || 菜单请求出错时,重定向到登陆页
     removeToken()

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

@@ -22,5 +22,5 @@ import SwitchDark from '@/components/SwitchDark/index.vue'
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 194 - 0
src/views/system/config/index.vue

@@ -0,0 +1,194 @@
+<template>
+  <div class="table-box">
+    <ProTable ref="proTable" :columns="columns" row-key="configId" :request-api="listConfigApi">
+      <!-- 表格 header 按钮 -->
+      <template #tableHeader="scope">
+        <el-button type="primary" v-auth="['system:config:add']" icon="CirclePlus" @click="openDialog(1, '参数配置新增')"> 新增 </el-button>
+        <el-button type="primary" v-auth="['system:config:export']" icon="Download" plain @click="downloadFile"> 导出 </el-button>
+        <el-button type="danger" v-auth="['system:config:remove']" icon="Refresh" plain @click="handleRefreshCache"> 刷新缓存 </el-button>
+        <el-button
+          type="danger"
+          v-auth="['system:config:remove']"
+          icon="Delete"
+          plain
+          :disabled="!scope.isSelected"
+          @click="batchDelete(scope.selectedListIds)"
+        >
+          批量删除
+        </el-button>
+      </template>
+      <!-- 表格操作 -->
+      <template #operation="scope">
+        <el-button type="primary" link icon="View" v-auth="['system:config:query']" @click="openDialog(3, '参数配置查看', scope.row)">
+          查看
+        </el-button>
+        <el-button type="primary" link icon="EditPen" v-auth="['system:config:edit']" @click="openDialog(2, '参数配置编辑', scope.row)">
+          编辑
+        </el-button>
+        <el-button type="primary" link icon="Delete" v-auth="['system:config:remove']" @click="deleteConfig(scope.row)"> 删除 </el-button>
+      </template>
+    </ProTable>
+    <FormDialog ref="formDialogRef" :items-options="itemsOptions" :model="model" />
+  </div>
+</template>
+
+<script setup lang="tsx" name="Config">
+import { useHandleData } from '@/hooks/useHandleData'
+import { useDownload } from '@/hooks/useDownload'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import FormDialog from '@/components/FormDialog/index.vue'
+import { ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
+import {
+  listConfigApi,
+  delConfigApi,
+  addConfigApi,
+  updateConfigApi,
+  exportConfigApi,
+  getConfigApi,
+  refreshCacheApi
+} from '@/api/modules/system/config'
+const { proxy } = getCurrentInstance() as ComponentInternalInstance
+const { sys_yes_no } = toRefs<any>(proxy?.useDict('sys_yes_no'))
+
+// ProTable 实例
+const proTable = ref<ProTableInstance>()
+// 表单model
+const model = ref({})
+// 删除参数配置信息
+const deleteConfig = async (params: any) => {
+  await useHandleData(delConfigApi, params.configId, '删除【' + params.configId + '】参数配置')
+  proTable.value?.getTableList()
+}
+
+// 批量删除参数配置信息
+const batchDelete = async (ids: string[]) => {
+  await useHandleData(delConfigApi, ids, '删除所选参数配置信息')
+  proTable.value?.clearSelection()
+  proTable.value?.getTableList()
+}
+
+// 导出参数配置列表
+const downloadFile = async () => {
+  ElMessageBox.confirm('确认导出参数配置数据?', '温馨提示', { type: 'warning' }).then(() =>
+    useDownload(exportConfigApi, '参数配置列表', proTable.value?.searchParam)
+  )
+}
+
+const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
+// 打开弹框的功能
+const openDialog = async (type: number, title: string, row?: any) => {
+  let res = { data: {} }
+  if (row?.configId) {
+    res = await getConfigApi(row?.configId || null)
+  }
+  model.value = type == 1 ? {} : res.data
+  // 重置表单
+  setItemsOptions()
+  const params = {
+    title,
+    width: 580,
+    isEdit: type !== 3,
+    api: type == 1 ? addConfigApi : updateConfigApi,
+    getTableList: proTable.value?.getTableList
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+/** 刷新缓存按钮操作 */
+const handleRefreshCache = async () => {
+  await refreshCacheApi()
+  ElMessage.success('刷新成功')
+}
+
+// 表格配置项
+const columns = reactive<ColumnProps<any>[]>([
+  { type: 'selection', fixed: 'left', width: 70 },
+  {
+    prop: 'configName',
+    label: '参数名称',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'configKey',
+    label: '参数键名',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'configValue',
+    label: '参数键值'
+  },
+  {
+    prop: 'configType',
+    label: '系统内置',
+    tag: true,
+    search: {
+      el: 'select'
+    },
+    enum: sys_yes_no
+  },
+  {
+    prop: 'remark',
+    label: '备注',
+    width: 120
+  },
+  { prop: 'operation', label: '操作', width: 230 }
+])
+// 表单配置项
+let itemsOptions = reactive<ProForm.ItemsOptions[]>([])
+const setItemsOptions = () => {
+  itemsOptions = [
+    {
+      label: '参数主键',
+      prop: 'configId',
+      rules: [{ required: true, message: '参数主键不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入参数主键'
+      }
+    },
+    {
+      label: '参数名称',
+      prop: 'configName',
+      rules: [{ required: true, message: '参数名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入参数名称'
+      }
+    },
+    {
+      label: '参数键名',
+      prop: 'configKey',
+      rules: [{ required: true, message: '参数键名不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入参数键名'
+      }
+    },
+    {
+      label: '参数键值',
+      prop: 'configValue',
+      rules: [{ required: true, message: '参数键值不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入参数键值'
+      }
+    },
+    {
+      label: '系统内置',
+      prop: 'configType',
+      rules: [{ required: true, message: '系统内置不能为空', trigger: 'change' }],
+      compOptions: {
+        elTagName: 'radio-button',
+        enum: sys_yes_no.value
+      }
+    },
+    {
+      label: '备注',
+      prop: 'remark',
+      compOptions: {
+        placeholder: '请输入备注'
+      }
+    }
+  ]
+}
+</script>

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

@@ -251,7 +251,7 @@ const setItemsOptions = () => {
       show: val => {
         return val?.menuType !== 'F'
       },
-      tooltip: '访问的路由地址,如:`user`,如外网地址需内链访问则以`http(s)://`开头',
+      tooltip: '访问的路由地址,如:`/system/user`,如外网地址需内链访问则以`http(s)://`开头',
       compOptions: {
         elTagName: 'input',
         placeholder: '请输入路由地址'
@@ -273,7 +273,7 @@ const setItemsOptions = () => {
       label: '组件路径',
       rules: [{ required: true, message: '组件路径不能为空', trigger: 'blur' }],
       prop: 'component',
-      tooltip: '访问的组件路径,如:`system/user/index`,默认在`views`目录下',
+      tooltip: '访问的组件路径,如:`/system/user/index`,默认在`views`目录下',
       span: 12,
       show: val => {
         return val?.menuType == 'C'

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

@@ -530,5 +530,5 @@ const setPerDataItemsOptions = () => {
 }
 </script>
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 1 - 1
src/views/system/user/profile/index.vue

@@ -215,5 +215,5 @@ onMounted(() => {
 </script>
 
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>