feat: 初始化配置中心项目
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>配置中心</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Generated
+1555
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "kenaito-conf-web",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^2.7.16",
|
||||
"vue-router": "^3.6.5",
|
||||
"vuex": "^3.6.2",
|
||||
"element-ui": "^2.15.14",
|
||||
"axios": "^1.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.0.0",
|
||||
"@vitejs/plugin-vue2": "^2.3.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'App'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
#app {
|
||||
height: 100%;
|
||||
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,53 @@
|
||||
import request from './request'
|
||||
|
||||
export function getAppList(params) {
|
||||
return request({
|
||||
url: '/admin/app/list',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function getAppTree() {
|
||||
return request({
|
||||
url: '/admin/app/tree',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function getApp(id) {
|
||||
return request({
|
||||
url: `/admin/app/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function addApp(data) {
|
||||
return request({
|
||||
url: '/admin/app/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateApp(data) {
|
||||
return request({
|
||||
url: '/admin/app/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteApp(id) {
|
||||
return request({
|
||||
url: `/admin/app/delete/${id}`,
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function getAppOptions() {
|
||||
return request({
|
||||
url: '/admin/app/options',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import request from './request'
|
||||
|
||||
export function login(data) {
|
||||
return request({
|
||||
url: '/user/login',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function getUserInfo() {
|
||||
return request({
|
||||
url: '/user/loginUserInfo',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
return request({
|
||||
url: '/user/logout',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function getMenus() {
|
||||
return request({
|
||||
url: '/admin/menus',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import request from './request'
|
||||
|
||||
export function getConfigList(params) {
|
||||
return request({
|
||||
url: '/admin/config/list',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function getConfig(id) {
|
||||
return request({
|
||||
url: `/admin/config/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function addConfig(data) {
|
||||
return request({
|
||||
url: '/admin/config/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateConfig(data) {
|
||||
return request({
|
||||
url: '/admin/config/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteConfig(id) {
|
||||
return request({
|
||||
url: `/admin/config/delete/${id}`,
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function getConfigHistory(id) {
|
||||
return request({
|
||||
url: `/admin/config/configHistories/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function rollbackConfig(id) {
|
||||
return request({
|
||||
url: `/admin/config/rollback/${id}`,
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import axios from 'axios'
|
||||
import { Message } from 'element-ui'
|
||||
|
||||
const request = axios.create({
|
||||
baseURL: '',
|
||||
timeout: 10000
|
||||
})
|
||||
|
||||
request.interceptors.request.use(
|
||||
config => {
|
||||
const token = localStorage.getItem('token')
|
||||
if (token) {
|
||||
config.headers['Authorization'] = `Bearer ${token}`
|
||||
}
|
||||
return config
|
||||
},
|
||||
error => {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
request.interceptors.response.use(
|
||||
response => {
|
||||
const res = response.data
|
||||
if (res.code && res.code !== 0) {
|
||||
Message.error(res.msg || '请求失败')
|
||||
if (res.code === 401) {
|
||||
localStorage.removeItem('token')
|
||||
window.location.href = '/login'
|
||||
}
|
||||
return Promise.reject(new Error(res.msg))
|
||||
}
|
||||
return res
|
||||
},
|
||||
error => {
|
||||
if (error.response && error.response.status === 401) {
|
||||
localStorage.removeItem('token')
|
||||
window.location.href = '/login'
|
||||
}
|
||||
Message.error(error.message || '网络错误')
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
export default request
|
||||
@@ -0,0 +1,14 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import ElementUI from 'element-ui'
|
||||
import 'element-ui/lib/theme-chalk/index.css'
|
||||
|
||||
Vue.use(ElementUI)
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
@@ -0,0 +1,70 @@
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import store from '../store'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
component: () => import('../views/Login.vue')
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
component: () => import('../views/Layout.vue'),
|
||||
redirect: '/config/list',
|
||||
children: [
|
||||
{
|
||||
path: '/config/list',
|
||||
name: 'ConfigList',
|
||||
component: () => import('../views/config/ConfigList.vue')
|
||||
},
|
||||
{
|
||||
path: '/config/add',
|
||||
name: 'ConfigAdd',
|
||||
component: () => import('../views/config/ConfigAdd.vue')
|
||||
},
|
||||
{
|
||||
path: '/config/edit/:id',
|
||||
name: 'ConfigEdit',
|
||||
component: () => import('../views/config/ConfigEdit.vue')
|
||||
},
|
||||
{
|
||||
path: '/app/list',
|
||||
name: 'AppList',
|
||||
component: () => import('../views/app/AppList.vue')
|
||||
},
|
||||
{
|
||||
path: '/user/list',
|
||||
name: 'UserList',
|
||||
component: () => import('../views/user/UserList.vue')
|
||||
},
|
||||
{
|
||||
path: '/group/list',
|
||||
name: 'GroupList',
|
||||
component: () => import('../views/group/GroupList.vue')
|
||||
},
|
||||
{
|
||||
path: '/profile/list',
|
||||
name: 'ProfileList',
|
||||
component: () => import('../views/profile/ProfileList.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
const router = new VueRouter({
|
||||
routes
|
||||
})
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
const token = localStorage.getItem('token')
|
||||
if (to.path !== '/login' && !token) {
|
||||
next('/login')
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
||||
@@ -0,0 +1,27 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: {
|
||||
userInfo: null,
|
||||
menus: []
|
||||
},
|
||||
mutations: {
|
||||
SET_USER_INFO(state, userInfo) {
|
||||
state.userInfo = userInfo
|
||||
},
|
||||
SET_MENUS(state, menus) {
|
||||
state.menus = menus
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setUserInfo({ commit }, userInfo) {
|
||||
commit('SET_USER_INFO', userInfo)
|
||||
},
|
||||
setMenus({ commit }, menus) {
|
||||
commit('SET_MENUS', menus)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<el-container style="height: 100vh">
|
||||
<el-aside width="200px" style="background: #304156">
|
||||
<div class="logo">配置中心</div>
|
||||
<el-menu
|
||||
:default-active="activeMenu"
|
||||
background-color="#304156"
|
||||
text-color="#bfcbd9"
|
||||
active-text-color="#409EFF"
|
||||
router
|
||||
>
|
||||
<template v-for="menu in menus">
|
||||
<el-submenu v-if="menu.children && menu.children.length > 1" :index="menu.title" :key="menu.title">
|
||||
<template slot="title">
|
||||
<i :class="menu.icon"></i>
|
||||
<span>{{ menu.title }}</span>
|
||||
</template>
|
||||
<el-menu-item v-for="child in menu.children" :key="child.url" :index="child.url">
|
||||
{{ child.title }}
|
||||
</el-menu-item>
|
||||
</el-submenu>
|
||||
<el-menu-item v-else-if="menu.children && menu.children.length === 1" :index="menu.children[0].url" :key="menu.children[0].url">
|
||||
<i :class="menu.icon"></i>
|
||||
<span>{{ menu.children[0].title }}</span>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<el-header style="background: #fff; display: flex; align-items: center; justify-content: space-between; box-shadow: 0 1px 4px rgba(0,21,41,.08)">
|
||||
<span style="font-size: 16px; font-weight: bold">欢迎使用配置中心</span>
|
||||
<div>
|
||||
<span style="margin-right: 15px">{{ userInfo ? userInfo.name : '' }}</span>
|
||||
<el-button type="text" @click="handleLogout">退出</el-button>
|
||||
</div>
|
||||
</el-header>
|
||||
<el-main style="background: #f0f2f5; padding: 20px">
|
||||
<router-view />
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getMenus, getUserInfo, logout } from '../api/auth'
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
...mapState(['userInfo', 'menus']),
|
||||
activeMenu() {
|
||||
return this.$route.path
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadMenus()
|
||||
},
|
||||
methods: {
|
||||
async loadMenus() {
|
||||
if (this.menus.length === 0) {
|
||||
try {
|
||||
const res = await getMenus()
|
||||
this.$store.dispatch('setMenus', res.data)
|
||||
} catch (e) {}
|
||||
}
|
||||
if (!this.userInfo) {
|
||||
try {
|
||||
const res = await getUserInfo()
|
||||
this.$store.dispatch('setUserInfo', res.data)
|
||||
} catch (e) {}
|
||||
}
|
||||
},
|
||||
async handleLogout() {
|
||||
try {
|
||||
await logout()
|
||||
} catch (e) {}
|
||||
localStorage.removeItem('token')
|
||||
this.$store.dispatch('setUserInfo', null)
|
||||
this.$store.dispatch('setMenus', [])
|
||||
this.$router.push('/login')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.logo {
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
background: #263445;
|
||||
}
|
||||
.el-menu {
|
||||
border-right: none;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<div class="login-container">
|
||||
<el-card class="login-card">
|
||||
<h2 class="login-title">配置中心</h2>
|
||||
<el-form :model="form" :rules="rules" ref="form" label-width="0">
|
||||
<el-form-item prop="userName">
|
||||
<el-input v-model="form.userName" placeholder="用户名" prefix-icon="el-icon-user"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input v-model="form.password" type="password" placeholder="密码" prefix-icon="el-icon-lock" @keyup.enter.native="handleLogin"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleLogin" :loading="loading" style="width: 100%">登录</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { login, getUserInfo, getMenus } from '../api/auth'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
userName: '',
|
||||
password: ''
|
||||
},
|
||||
rules: {
|
||||
userName: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
||||
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
|
||||
},
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async handleLogin() {
|
||||
this.$refs.form.validate(async (valid) => {
|
||||
if (!valid) return
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await login(this.form)
|
||||
localStorage.setItem('token', res.data.token)
|
||||
this.$store.dispatch('setUserInfo', res.data.userInfo)
|
||||
const menuRes = await getMenus()
|
||||
this.$store.dispatch('setMenus', menuRes.data)
|
||||
this.$router.push('/')
|
||||
} catch (e) {
|
||||
// error handled by interceptor
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.login-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background: #2d3a4b;
|
||||
}
|
||||
.login-card {
|
||||
width: 400px;
|
||||
padding: 20px;
|
||||
}
|
||||
.login-title {
|
||||
text-align: center;
|
||||
color: #303133;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,157 @@
|
||||
<template>
|
||||
<el-card>
|
||||
<div slot="header" style="display: flex; justify-content: space-between; align-items: center">
|
||||
<span>应用管理</span>
|
||||
<el-button type="primary" @click="showAdd">新建应用</el-button>
|
||||
</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="code" label="应用编码"></el-table-column>
|
||||
<el-table-column prop="groupName" label="所属业务组" width="120"></el-table-column>
|
||||
<el-table-column prop="ownerName" label="负责人" width="100"></el-table-column>
|
||||
<el-table-column prop="enabled" label="状态" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.enabled" @change="handleSwitch(scope.row)"></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="showEdit(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="dialogTitle" :visible.sync="dialogVisible" width="500px">
|
||||
<el-form :model="form" :rules="rules" ref="form" label-width="100px">
|
||||
<el-form-item label="应用名称" prop="name">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="应用编码" prop="code">
|
||||
<el-input v-model="form.code" :disabled="!!form.id"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属业务组">
|
||||
<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="负责人">
|
||||
<el-select v-model="form.ownerId" placeholder="请选择">
|
||||
<el-option v-for="u in users" :key="u.value" :label="u.label" :value="parseInt(u.value)"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.remarks" type="textarea"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getAppList, addApp, updateApp, deleteApp } from '../../api/app'
|
||||
import request from '../../api/request'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
loading: false,
|
||||
total: 0,
|
||||
query: { pageNo: 1, pageSize: 20 },
|
||||
dialogVisible: false,
|
||||
dialogTitle: '',
|
||||
form: {},
|
||||
rules: {
|
||||
name: [{ required: true, message: '请输入应用名称', trigger: 'blur' }],
|
||||
code: [{ required: true, message: '请输入应用编码', trigger: 'blur' }]
|
||||
},
|
||||
groups: [],
|
||||
users: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadData()
|
||||
this.loadOptions()
|
||||
},
|
||||
methods: {
|
||||
async loadData() {
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await getAppList(this.query)
|
||||
this.list = res.data || []
|
||||
this.total = res.total || 0
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async loadOptions() {
|
||||
try {
|
||||
const [groupRes, userRes] = await Promise.all([
|
||||
request({ url: '/admin/group/options', method: 'get' }),
|
||||
request({ url: '/admin/user/options', method: 'get' })
|
||||
])
|
||||
this.groups = groupRes.data || []
|
||||
this.users = userRes.data || []
|
||||
} catch (e) {}
|
||||
},
|
||||
showAdd() {
|
||||
this.dialogTitle = '新建应用'
|
||||
this.form = { name: '', code: '', groupId: null, ownerId: null, remarks: '' }
|
||||
this.dialogVisible = true
|
||||
},
|
||||
showEdit(row) {
|
||||
this.dialogTitle = '编辑应用'
|
||||
this.form = { ...row }
|
||||
this.dialogVisible = true
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate(async (valid) => {
|
||||
if (!valid) return
|
||||
try {
|
||||
if (this.form.id) {
|
||||
await updateApp(this.form)
|
||||
} else {
|
||||
await addApp(this.form)
|
||||
}
|
||||
this.$message.success('保存成功')
|
||||
this.dialogVisible = false
|
||||
this.loadData()
|
||||
} catch (e) {}
|
||||
})
|
||||
},
|
||||
async handleDelete(row) {
|
||||
try {
|
||||
await this.$confirm('确定删除此应用?')
|
||||
await deleteApp(row.id)
|
||||
this.$message.success('删除成功')
|
||||
this.loadData()
|
||||
} catch (e) {}
|
||||
},
|
||||
async handleSwitch(row) {
|
||||
try {
|
||||
await request({ url: `/admin/app/switch/${row.id}`, method: 'post' })
|
||||
} catch (e) {
|
||||
row.enabled = !row.enabled
|
||||
}
|
||||
},
|
||||
handlePageChange(page) {
|
||||
this.query.pageNo = page
|
||||
this.loadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<el-card>
|
||||
<div slot="header" style="display: flex; justify-content: space-between; align-items: center">
|
||||
<span>业务组管理</span>
|
||||
<el-button type="primary" @click="showAdd">新建业务组</el-button>
|
||||
</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="master" label="负责人"></el-table-column>
|
||||
<el-table-column prop="remarks" label="备注"></el-table-column>
|
||||
<el-table-column prop="enabled" label="状态" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.enabled ? 'success' : 'info'">{{ scope.row.enabled ? '启用' : '禁用' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="showEdit(scope.row)">编辑</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="500px">
|
||||
<el-form :model="form" :rules="rules" ref="form" label-width="80px">
|
||||
<el-form-item label="组名称" prop="name">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="负责人" prop="masterUid">
|
||||
<el-select v-model="form.masterUid" placeholder="请选择">
|
||||
<el-option v-for="u in users" :key="u.value" :label="u.label" :value="parseInt(u.value)"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.remarks" type="textarea"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from '../../api/request'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
loading: false,
|
||||
dialogVisible: false,
|
||||
dialogTitle: '',
|
||||
form: {},
|
||||
rules: {
|
||||
name: [{ required: true, message: '请输入组名称', trigger: 'blur' }],
|
||||
masterUid: [{ required: true, message: '请选择负责人', trigger: 'change' }]
|
||||
},
|
||||
users: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadData()
|
||||
this.loadUsers()
|
||||
},
|
||||
methods: {
|
||||
async loadData() {
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await request({ url: '/admin/group/list', method: 'get' })
|
||||
this.list = res.data || []
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async loadUsers() {
|
||||
try {
|
||||
const res = await request({ url: '/admin/user/options', method: 'get' })
|
||||
this.users = res.data || []
|
||||
} catch (e) {}
|
||||
},
|
||||
showAdd() {
|
||||
this.dialogTitle = '新建业务组'
|
||||
this.form = { name: '', masterUid: null, remarks: '' }
|
||||
this.dialogVisible = true
|
||||
},
|
||||
showEdit(row) {
|
||||
this.dialogTitle = '编辑业务组'
|
||||
this.form = { ...row }
|
||||
this.dialogVisible = true
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate(async (valid) => {
|
||||
if (!valid) return
|
||||
try {
|
||||
const url = this.form.id ? '/admin/group/update' : '/admin/group/add'
|
||||
await request({ url, method: 'post', data: this.form })
|
||||
this.$message.success('保存成功')
|
||||
this.dialogVisible = false
|
||||
this.loadData()
|
||||
} catch (e) {}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<el-card>
|
||||
<div slot="header" style="display: flex; justify-content: space-between; align-items: center">
|
||||
<span>环境管理</span>
|
||||
<el-button type="primary" @click="showAdd">新建环境</el-button>
|
||||
</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="alias" label="环境名称"></el-table-column>
|
||||
<el-table-column prop="isDefault" label="默认" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.isDefault" type="success">是</el-tag>
|
||||
<span v-else>否</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="enabled" label="状态" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.enabled" @change="handleSwitch(scope.row)"></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="showEdit(scope.row)">编辑</el-button>
|
||||
<el-button type="text" style="color: #F56C6C" @click="handleDelete(scope.row)" v-if="!scope.row.isDefault">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="500px">
|
||||
<el-form :model="form" :rules="rules" ref="form" label-width="80px">
|
||||
<el-form-item label="环境标识" prop="name">
|
||||
<el-input v-model="form.name" placeholder="如: daily, stage, online" :disabled="!!form.id"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="环境名称">
|
||||
<el-input v-model="form.alias" placeholder="如: 测试环境"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from '../../api/request'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
loading: false,
|
||||
dialogVisible: false,
|
||||
dialogTitle: '',
|
||||
form: {},
|
||||
rules: {
|
||||
name: [{ required: true, message: '请输入环境标识', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
async loadData() {
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await request({ url: '/admin/profile/list', method: 'get' })
|
||||
this.list = res.data || []
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
showAdd() {
|
||||
this.dialogTitle = '新建环境'
|
||||
this.form = { name: '', alias: '' }
|
||||
this.dialogVisible = true
|
||||
},
|
||||
showEdit(row) {
|
||||
this.dialogTitle = '编辑环境'
|
||||
this.form = { id: row.id, name: row.name, alias: row.alias }
|
||||
this.dialogVisible = true
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate(async (valid) => {
|
||||
if (!valid) return
|
||||
try {
|
||||
const url = this.form.id ? '/admin/profile/update' : '/admin/profile/add'
|
||||
await request({ url, method: 'post', data: this.form })
|
||||
this.$message.success('保存成功')
|
||||
this.dialogVisible = false
|
||||
this.loadData()
|
||||
} catch (e) {}
|
||||
})
|
||||
},
|
||||
async handleSwitch(row) {
|
||||
try {
|
||||
await request({ url: `/admin/profile/switch/${row.id}`, method: 'post' })
|
||||
} catch (e) {
|
||||
row.enabled = !row.enabled
|
||||
}
|
||||
},
|
||||
async handleDelete(row) {
|
||||
try {
|
||||
await this.$confirm('确定删除此环境?')
|
||||
await request({ url: `/admin/profile/delete/${row.id}`, method: 'post' })
|
||||
this.$message.success('删除成功')
|
||||
this.loadData()
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,157 @@
|
||||
<template>
|
||||
<el-card>
|
||||
<div slot="header" style="display: flex; justify-content: space-between; align-items: center">
|
||||
<span>用户管理</span>
|
||||
<el-button type="primary" @click="showAdd">新建用户</el-button>
|
||||
</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="mobile" label="手机号"></el-table-column>
|
||||
<el-table-column prop="email" label="邮箱"></el-table-column>
|
||||
<el-table-column prop="type" label="类型" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.type === 'superAdmin'" type="danger">超级管理员</el-tag>
|
||||
<el-tag v-else-if="scope.row.type === 'groupAdmin'" type="warning">组管理员</el-tag>
|
||||
<el-tag v-else>普通用户</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="groupName" label="所属组"></el-table-column>
|
||||
<el-table-column prop="enabled" label="状态" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.enabled"
|
||||
@change="handleSwitch(scope.row)"
|
||||
:disabled="scope.row.name === 'admin'">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="showEdit(scope.row)">编辑</el-button>
|
||||
<el-button type="text" @click="handleResetPwd(scope.row)">重置密码</el-button>
|
||||
<el-button type="text" style="color: #F56C6C" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="500px">
|
||||
<el-form :model="form" :rules="rules" ref="form" label-width="80px">
|
||||
<el-form-item label="用户名" prop="name">
|
||||
<el-input v-model="form.name" :disabled="!!form.id"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号" prop="mobile">
|
||||
<el-input v-model="form.mobile"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱">
|
||||
<el-input v-model="form.email"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select v-model="form.type" :disabled="form.id && form.type === 'superAdmin'">
|
||||
<el-option value="user" label="普通用户"></el-option>
|
||||
<el-option value="groupAdmin" label="组管理员"></el-option>
|
||||
<el-option value="superAdmin" label="超级管理员"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属组" v-if="form.type !== 'superAdmin'">
|
||||
<el-input v-model="form.groupName" placeholder="输入组名(不存在会自动创建)" :disabled="form.id && form.isSuperAdmin"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from '../../api/request'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
loading: false,
|
||||
dialogVisible: false,
|
||||
dialogTitle: '',
|
||||
form: {},
|
||||
rules: {
|
||||
name: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
||||
mobile: [{ required: true, message: '请输入手机号', trigger: 'blur' }],
|
||||
type: [{ required: true, message: '请选择类型', trigger: 'change' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
async loadData() {
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await request({ url: '/admin/user/list', method: 'get' })
|
||||
this.list = res.data || []
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
showAdd() {
|
||||
this.dialogTitle = '新建用户'
|
||||
this.form = { name: '', mobile: '', email: '', type: 'user', groupName: '' }
|
||||
this.dialogVisible = true
|
||||
},
|
||||
showEdit(row) {
|
||||
this.dialogTitle = '编辑用户'
|
||||
this.form = {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
mobile: row.mobile,
|
||||
email: row.email,
|
||||
type: row.type,
|
||||
groupName: row.groupName || '',
|
||||
isSuperAdmin: row.type === 'superAdmin'
|
||||
}
|
||||
this.dialogVisible = true
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate(async (valid) => {
|
||||
if (!valid) return
|
||||
try {
|
||||
const url = this.form.id ? '/admin/user/update' : '/admin/user/add'
|
||||
await request({ url, method: 'post', data: this.form })
|
||||
if (this.form.id) {
|
||||
this.$message.success('编辑成功')
|
||||
} else {
|
||||
this.$message.success('创建成功,默认密码:admin123')
|
||||
}
|
||||
this.dialogVisible = false
|
||||
this.loadData()
|
||||
} catch (e) {}
|
||||
})
|
||||
},
|
||||
async handleSwitch(row) {
|
||||
try {
|
||||
await request({ url: `/admin/user/switch/${row.id}`, method: 'post' })
|
||||
this.$message.success('操作成功')
|
||||
this.loadData()
|
||||
} catch (e) {}
|
||||
},
|
||||
async handleResetPwd(row) {
|
||||
try {
|
||||
await this.$confirm('确定重置密码?')
|
||||
const res = await request({ url: `/admin/user/resetPassword/${row.id}`, method: 'post' })
|
||||
this.$message.success(`新密码: ${res.data}`)
|
||||
} catch (e) {}
|
||||
},
|
||||
async handleDelete(row) {
|
||||
try {
|
||||
await this.$confirm('确定删除此用户?')
|
||||
await request({ url: `/admin/user/delete/${row.id}`, method: 'post' })
|
||||
this.$message.success('删除成功')
|
||||
this.loadData()
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import vue2 from '@vitejs/plugin-vue2'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue2()],
|
||||
server: {
|
||||
port: 3000,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:8080',
|
||||
changeOrigin: true
|
||||
},
|
||||
'/admin': {
|
||||
target: 'http://localhost:8080',
|
||||
changeOrigin: true
|
||||
},
|
||||
'/user': {
|
||||
target: 'http://localhost:8080',
|
||||
changeOrigin: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user