Parcourir la source

feat(admin): 添加系统配置和插件配置管理功能

- 新增 PluginConfig.vue 和 SystemConfig.vue 页面组件
- 创建 PluginConfigForm.vue 通用配置表单组件
- 集成 getPluginConfigApi 和 savePluginConfigApi 接口调用
- 实现动态路由参数监听和插件ID切换功能
- 添加表单提交、数据加载和错误处理逻辑
- 配置系统管理模块路由和菜单项
runphp il y a 3 semaines
Parent
commit
be27b34ea2

+ 49 - 0
frontend/admin/index.js

@@ -0,0 +1,49 @@
+export default {
+    routes: {
+        path: '/system',
+        name: 'SystemModule',
+        component: () => import('@/layout/index.vue'),
+        meta: {
+            title: '系统管理',
+            icon: 'Setting',
+            permission: 'system'
+        },
+        children: [
+            {
+                path: 'config',
+                name: 'SystemConfig',
+                component: () => import('./views/SystemConfig.vue'),
+                meta: {
+                    title: '系统配置',
+                    icon: 'Tools'
+                }
+            },
+            {
+                path: 'plugin-config',
+                name: 'PluginConfig',
+                component: () => import('./views/PluginConfig.vue'),
+                meta: {
+                    title: '插件配置',
+                    icon: 'Connection',
+                    hidden: true
+                }
+            }
+        ]
+    },
+
+    menus: [
+        {
+            path: '/system',
+            title: '系统管理',
+            icon: 'Setting',
+            permission: 'system',
+            children: [
+                {
+                    path: '/system/config',
+                    title: '系统配置',
+                    icon: 'Tools'
+                }
+            ]
+        }
+    ]
+}

+ 24 - 0
frontend/admin/views/PluginConfig.vue

@@ -0,0 +1,24 @@
+<script setup lang="ts">
+import {ref} from 'vue'
+import {useRoute} from 'vue-router'
+import PluginConfigForm from './PluginConfigForm.vue';
+
+const route = useRoute()
+const pluginId = ref('system') // 默认值为 system
+
+// 立即获取路由参数,而不是在 onMounted 中获取
+if (route.query.plugin_id) {
+  pluginId.value = route.query.plugin_id as string
+}
+
+// 监听路由参数变化,确保参数变化时更新插件ID
+const unwatch = () => {
+} // placeholder
+</script>
+
+<template>
+  <plugin-config-form :plugin-id="pluginId"/>
+</template>
+
+<style scoped lang="scss">
+</style>

+ 106 - 0
frontend/admin/views/PluginConfigForm.vue

@@ -0,0 +1,106 @@
+<template>
+  <el-card shadow="never" class="settings-card">
+    <template #header>
+      <div class="card-header">
+        <slot name="header">
+          <span>插件配置</span>
+        </slot>
+      </div>
+    </template>
+
+    <formCreate
+      :rule="configRule"
+      :option="configOptions"
+      v-if="configRule.length > 0"
+    />
+    <el-empty v-else description="暂无配置项" />
+  </el-card>
+</template>
+
+<script setup>
+import { ref, watch } from 'vue'
+import { ElMessage } from 'element-plus'
+import { getPluginConfigApi, savePluginConfigApi } from '@/api/plugin'
+import {useUserStore} from "@/store/user.js";
+
+const userStore = useUserStore()
+const props = defineProps({
+  pluginId: {
+    type: String,
+    required: true
+  },
+  setting: {
+    type: String,
+    default: null
+  }
+})
+
+const configRule = ref([])
+const loading = ref(false)
+
+const configOptions = ref({
+  form: {
+    labelPosition: 'right',
+  },
+  submitBtn: {
+    innerText: '保存配置',
+    loading: loading
+  },
+  resetBtn: true,
+  onSubmit: async (formData) => {
+    try {
+      loading.value = true
+      await savePluginConfigApi(props.pluginId, formData)
+      ElMessage.success('配置保存成功')
+    } finally {
+      loading.value = false
+    }
+  },
+  beforeFetch: (options) => {
+    options.headers = {
+      Authorization: `Bearer ${userStore.token}`
+    };
+  }
+})
+
+const loadConfig = async () => {
+  try {
+    let { data } = await getPluginConfigApi(props.pluginId)
+
+    if (!Array.isArray(data)) {
+      console.warn('Expected configRule to be an array, but got:', typeof data)
+      data = []
+    }
+
+    if (props.setting) {
+      const findSetting = (items, target) => {
+        for (const item of items) {
+          if (item.field === target) return item
+          if (item.children) {
+            const found = findSetting(item.children, target)
+            if (found) return found
+          }
+        }
+        return null
+      }
+      const setting = findSetting(data, props.setting)
+      configRule.value = setting ? [setting] : []
+    } else {
+      configRule.value = data
+    }
+  } catch (e) {
+    console.error('加载配置失败:', e)
+    ElMessage.error('配置加载失败')
+  }
+}
+
+// 监听参数变化自动加载
+watch(() => props.pluginId, loadConfig, { immediate: true })
+watch(() => props.setting, loadConfig)
+</script>
+
+<style scoped>
+.settings-card {
+  margin-bottom: 20px;
+}
+</style>

+ 24 - 0
frontend/admin/views/SystemConfig.vue

@@ -0,0 +1,24 @@
+<script setup lang="ts">
+import {ref} from 'vue'
+import {useRoute} from 'vue-router'
+import PluginConfigForm from './PluginConfigForm.vue';
+
+const route = useRoute()
+const pluginId = ref('system') // 默认值为 system
+
+// 立即获取路由参数,而不是在 onMounted 中获取
+if (route.query.plugin_id) {
+  pluginId.value = route.query.plugin_id as string
+}
+
+// 监听路由参数变化,确保参数变化时更新插件ID
+const unwatch = () => {
+} // placeholder
+</script>
+
+<template>
+  <plugin-config-form :plugin-id="pluginId"/>
+</template>
+
+<style scoped lang="scss">
+</style>