feat: 初始化配置中心项目

This commit is contained in:
2026-01-14 21:02:13 +08:00
commit 4436d3ee88
95 changed files with 8736 additions and 0 deletions
+104
View File
@@ -0,0 +1,104 @@
<template>
<el-card>
<div slot="header">新建配置</div>
<el-form :model="form" :rules="rules" ref="form" label-width="100px">
<el-form-item label="配置类型">
<el-radio-group v-model="form.global">
<el-radio :label="true">全局配置</el-radio>
<el-radio :label="false">应用配置</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="所属业务组" v-if="form.global" prop="groupId">
<el-select v-model="form.groupId" placeholder="请选择">
<el-option v-for="g in groups" :key="g.value" :label="g.label" :value="parseInt(g.value)"></el-option>
</el-select>
</el-form-item>
<el-form-item label="所属应用" v-if="!form.global" prop="appId">
<el-select v-model="form.appId" placeholder="请选择">
<el-option v-for="a in apps" :key="a.value" :label="a.label" :value="parseInt(a.value)"></el-option>
</el-select>
</el-form-item>
<el-form-item label="环境" prop="env">
<el-select v-model="form.env" placeholder="请选择">
<el-option v-for="p in profiles" :key="p.value" :label="p.label" :value="p.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="版本">
<el-input v-model="form.version" placeholder="latest"></el-input>
</el-form-item>
<el-form-item label="配置格式">
<el-select v-model="form.type" placeholder="请选择">
<el-option :value="2" label="配置项 (key=value)"></el-option>
<el-option :value="1" label="文件 (properties/xml/yaml)"></el-option>
<el-option :value="3" label="JSON"></el-option>
</el-select>
</el-form-item>
<el-form-item label="配置名称" v-if="form.type === 2 || form.type === 1" prop="name">
<el-input v-model="form.name" :placeholder="form.type === 2 ? '如: db.host' : '如: application.properties'"></el-input>
</el-form-item>
<el-form-item label="配置内容" prop="contents">
<el-input v-model="form.contents" type="textarea" :rows="15" placeholder="请输入配置内容"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit">保存</el-button>
<el-button @click="$router.back()">取消</el-button>
</el-form-item>
</el-form>
</el-card>
</template>
<script>
import { addConfig } from '../../api/config'
import request from '../../api/request'
export default {
data() {
return {
form: {
global: false,
groupId: null,
appId: null,
env: '',
version: 'latest',
type: 2,
name: '',
contents: ''
},
rules: {
env: [{ required: true, message: '请选择环境', trigger: 'change' }],
contents: [{ required: true, message: '请输入配置内容', trigger: 'blur' }]
},
groups: [],
apps: [],
profiles: []
}
},
created() {
this.loadOptions()
},
methods: {
async loadOptions() {
try {
const [groupRes, appRes, profileRes] = await Promise.all([
request({ url: '/admin/group/options', method: 'get' }),
request({ url: '/admin/app/options', method: 'get' }),
request({ url: '/admin/profile/options', method: 'get' })
])
this.groups = groupRes.data || []
this.apps = appRes.data || []
this.profiles = profileRes.data || []
} catch (e) {}
},
handleSubmit() {
this.$refs.form.validate(async (valid) => {
if (!valid) return
try {
await addConfig(this.form)
this.$message.success('保存成功')
this.$router.push('/config/list')
} catch (e) {}
})
}
}
}
</script>
+60
View File
@@ -0,0 +1,60 @@
<template>
<el-card>
<div slot="header">编辑配置</div>
<el-form :model="form" ref="form" label-width="100px" v-loading="loading">
<el-form-item label="配置名称">
<el-input v-model="form.name" disabled></el-input>
</el-form-item>
<el-form-item label="环境">
<el-input v-model="form.env" disabled></el-input>
</el-form-item>
<el-form-item label="所属应用">
<el-input :value="form.appNames" disabled></el-input>
</el-form-item>
<el-form-item label="版本">
<el-input v-model="form.version"></el-input>
</el-form-item>
<el-form-item label="配置内容">
<el-input v-model="form.contents" type="textarea" :rows="20"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit">保存</el-button>
<el-button @click="$router.back()">取消</el-button>
</el-form-item>
</el-form>
</el-card>
</template>
<script>
import { getConfig, updateConfig } from '../../api/config'
export default {
data() {
return {
form: {},
loading: false
}
},
created() {
this.loadConfig()
},
methods: {
async loadConfig() {
this.loading = true
try {
const res = await getConfig(this.$route.params.id)
this.form = res.data
} finally {
this.loading = false
}
},
async handleSubmit() {
try {
await updateConfig(this.form)
this.$message.success('保存成功')
this.$router.push('/config/list')
} catch (e) {}
}
}
}
</script>
+126
View File
@@ -0,0 +1,126 @@
<template>
<el-card>
<div slot="header" style="display: flex; justify-content: space-between; align-items: center">
<span>配置列表</span>
<div>
<el-select v-model="query.env" placeholder="环境" clearable style="width: 120px; margin-right: 10px" @change="loadData">
<el-option v-for="p in profiles" :key="p.value" :label="p.label" :value="p.value"></el-option>
</el-select>
<el-button type="primary" @click="$router.push('/config/add')">新建配置</el-button>
</div>
</div>
<el-table :data="list" v-loading="loading" border stripe>
<el-table-column prop="id" label="ID" width="60"></el-table-column>
<el-table-column prop="name" label="配置名"></el-table-column>
<el-table-column prop="env" label="环境" width="80"></el-table-column>
<el-table-column prop="appNames" label="所属应用"></el-table-column>
<el-table-column prop="type" label="类型" width="80">
<template slot-scope="scope">
<span v-if="scope.row.type === 1">文件</span>
<span v-else-if="scope.row.type === 2">配置项</span>
<span v-else-if="scope.row.type === 3">JSON</span>
</template>
</el-table-column>
<el-table-column prop="version" label="版本" width="100"></el-table-column>
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<el-button type="text" @click="$router.push(`/config/edit/${scope.row.id}`)">编辑</el-button>
<el-button type="text" @click="showHistory(scope.row)">历史</el-button>
<el-button type="text" style="color: #F56C6C" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top: 15px; text-align: right"
@current-change="handlePageChange"
:current-page="query.pageNo"
:page-size="query.pageSize"
:total="total"
layout="total, prev, pager, next"
></el-pagination>
<el-dialog title="配置历史" :visible.sync="historyVisible" width="700px">
<el-table :data="historyList" border stripe>
<el-table-column prop="id" label="ID" width="60"></el-table-column>
<el-table-column prop="createdBy" label="操作人" width="100"></el-table-column>
<el-table-column prop="createdAt" label="操作时间" width="180"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="text" @click="handleRollback(scope.row)">回滚到此版本</el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
</el-card>
</template>
<script>
import { getConfigList, deleteConfig, getConfigHistory, rollbackConfig } from '../../api/config'
import request from '../../api/request'
export default {
data() {
return {
list: [],
loading: false,
total: 0,
query: { pageNo: 1, pageSize: 20, env: '' },
profiles: [],
historyVisible: false,
historyList: [],
currentConfig: null
}
},
created() {
this.loadData()
this.loadProfiles()
},
methods: {
async loadData() {
this.loading = true
try {
const res = await getConfigList(this.query)
this.list = res.data || []
this.total = res.total || 0
} finally {
this.loading = false
}
},
async loadProfiles() {
try {
const res = await request({ url: '/admin/profile/options', method: 'get' })
this.profiles = res.data || []
} catch (e) {}
},
handlePageChange(page) {
this.query.pageNo = page
this.loadData()
},
async handleDelete(row) {
try {
await this.$confirm('确定删除此配置?')
await deleteConfig(row.id)
this.$message.success('删除成功')
this.loadData()
} catch (e) {}
},
async showHistory(row) {
this.currentConfig = row
try {
const res = await getConfigHistory(row.id)
this.historyList = res.data || []
this.historyVisible = true
} catch (e) {}
},
async handleRollback(row) {
try {
await this.$confirm('确定回滚到此版本?')
await rollbackConfig(row.id)
this.$message.success('回滚成功')
this.historyVisible = false
this.loadData()
} catch (e) {}
}
}
}
</script>