mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 03:07:20 +08:00
feat: 数据库管理优化1
This commit is contained in:
@@ -56,6 +56,7 @@ type DatabaseServerRepo interface {
|
||||
Get(id uint) (*DatabaseServer, error)
|
||||
Create(req *request.DatabaseServerCreate) error
|
||||
Update(req *request.DatabaseServerUpdate) error
|
||||
UpdateRemark(req *request.DatabaseServerUpdateRemark) error
|
||||
Delete(id uint) error
|
||||
Sync(id uint) error
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ type DatabaseUserRepo interface {
|
||||
Get(id uint) (*DatabaseUser, error)
|
||||
Create(req *request.DatabaseUserCreate) error
|
||||
Update(req *request.DatabaseUserUpdate) error
|
||||
UpdateRemark(req *request.DatabaseUserUpdateRemark) error
|
||||
Delete(id uint) error
|
||||
DeleteByServerID(serverID uint) error
|
||||
}
|
||||
|
||||
@@ -89,6 +89,10 @@ func (r databaseServerRepo) Update(req *request.DatabaseServerUpdate) error {
|
||||
return app.Orm.Save(server).Error
|
||||
}
|
||||
|
||||
func (r databaseServerRepo) UpdateRemark(req *request.DatabaseServerUpdateRemark) error {
|
||||
return app.Orm.Model(&biz.DatabaseServer{}).Where("id = ?", req.ID).Update("remark", req.Remark).Error
|
||||
}
|
||||
|
||||
func (r databaseServerRepo) Delete(id uint) error {
|
||||
// 删除服务器下的所有用户
|
||||
if err := NewDatabaseUserRepo().DeleteByServerID(id); err != nil {
|
||||
|
||||
@@ -88,12 +88,17 @@ func (r databaseUserRepo) Create(req *request.DatabaseUserCreate) error {
|
||||
user := &biz.DatabaseUser{
|
||||
ServerID: req.ServerID,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
Host: req.Host,
|
||||
Remark: req.Remark,
|
||||
}
|
||||
|
||||
return app.Orm.Create(user).Error
|
||||
if err = app.Orm.FirstOrInit(user, user).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user.Password = req.Password
|
||||
user.Remark = req.Remark
|
||||
|
||||
return app.Orm.Save(user).Error
|
||||
}
|
||||
|
||||
func (r databaseUserRepo) Update(req *request.DatabaseUserUpdate) error {
|
||||
@@ -146,6 +151,17 @@ func (r databaseUserRepo) Update(req *request.DatabaseUserUpdate) error {
|
||||
return app.Orm.Save(user).Error
|
||||
}
|
||||
|
||||
func (r databaseUserRepo) UpdateRemark(req *request.DatabaseUserUpdateRemark) error {
|
||||
user, err := r.Get(req.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user.Remark = req.Remark
|
||||
|
||||
return app.Orm.Save(user).Error
|
||||
}
|
||||
|
||||
func (r databaseUserRepo) Delete(id uint) error {
|
||||
user, err := r.Get(id)
|
||||
if err != nil {
|
||||
|
||||
@@ -19,3 +19,8 @@ type DatabaseServerUpdate struct {
|
||||
Password string `form:"password" json:"password"`
|
||||
Remark string `form:"remark" json:"remark"`
|
||||
}
|
||||
|
||||
type DatabaseServerUpdateRemark struct {
|
||||
ID uint `form:"id" json:"id" validate:"required,exists=database_servers id"`
|
||||
Remark string `form:"remark" json:"remark"`
|
||||
}
|
||||
|
||||
@@ -15,3 +15,8 @@ type DatabaseUserUpdate struct {
|
||||
Privileges []string `form:"privileges" json:"privileges"`
|
||||
Remark string `form:"remark" json:"remark"`
|
||||
}
|
||||
|
||||
type DatabaseUserUpdateRemark struct {
|
||||
ID uint `form:"id" json:"id" validate:"required,exists=database_users id"`
|
||||
Remark string `form:"remark" json:"remark"`
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ func Http(r chi.Router) {
|
||||
r.Get("/", server.List)
|
||||
r.Post("/", server.Create)
|
||||
r.Put("/{id}", server.Update)
|
||||
r.Put("/{id}/remark", server.UpdateRemark)
|
||||
r.Delete("/{id}", server.Delete)
|
||||
r.Post("/{id}/sync", server.Sync)
|
||||
})
|
||||
@@ -83,6 +84,7 @@ func Http(r chi.Router) {
|
||||
r.Get("/", user.List)
|
||||
r.Post("/", user.Create)
|
||||
r.Put("/{id}", user.Update)
|
||||
r.Put("/{id}/remark", user.UpdateRemark)
|
||||
r.Delete("/{id}", user.Delete)
|
||||
})
|
||||
|
||||
|
||||
@@ -69,6 +69,21 @@ func (s *DatabaseServer) Update(w http.ResponseWriter, r *http.Request) {
|
||||
Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *DatabaseServer) UpdateRemark(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.DatabaseServerUpdateRemark](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = s.databaseServerRepo.UpdateRemark(req); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *DatabaseServer) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.ID](r)
|
||||
if err != nil {
|
||||
|
||||
@@ -69,6 +69,21 @@ func (s *DatabaseUser) Update(w http.ResponseWriter, r *http.Request) {
|
||||
Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *DatabaseUser) UpdateRemark(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.DatabaseUserUpdateRemark](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = s.databaseUserRepo.UpdateRemark(req); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *DatabaseUser) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.ID](r)
|
||||
if err != nil {
|
||||
|
||||
@@ -18,6 +18,9 @@ export default {
|
||||
serverDelete: (id: number) => http.Delete(`/databaseServer/${id}`),
|
||||
// 同步数据库
|
||||
serverSync: (id: number) => http.Post(`/databaseServer/${id}/sync`),
|
||||
// 更新服务器备注
|
||||
serverRemark: (id: number, remark: string) =>
|
||||
http.Put(`/databaseServer/${id}/remark`, { remark }),
|
||||
// 获取数据库用户列表
|
||||
userList: (page: number, limit: number) => http.Get('/databaseUser', { params: { page, limit } }),
|
||||
// 创建数据库用户
|
||||
@@ -25,5 +28,7 @@ export default {
|
||||
// 更新数据库用户
|
||||
userUpdate: (id: number, data: any) => http.Put(`/databaseUser/${id}`, data),
|
||||
// 删除数据库用户
|
||||
userDelete: (id: number) => http.Delete(`/databaseUser/${id}`)
|
||||
userDelete: (id: number) => http.Delete(`/databaseUser/${id}`),
|
||||
// 更新用户备注
|
||||
userRemark: (id: number, remark: string) => http.Put(`/databaseUser/${id}/remark`, { remark })
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"title": "应用",
|
||||
"alerts": {
|
||||
"cache": "缓存更新成功",
|
||||
"warning": "更新应用前强烈建议先备份/快照,以免出现问题时无法回滚!",
|
||||
"warning": "更新应用前强烈建议先备份/快照,以免出现问题时无法第一时间回滚!",
|
||||
"setup": "设置成功",
|
||||
"install": "任务已提交,请前往后台任务查看任务进度",
|
||||
"update": "任务已提交,请前往后台任务查看任务进度",
|
||||
|
||||
@@ -76,7 +76,7 @@ onMounted(() => {
|
||||
v-model:value="createModel.username"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="输入授权用户名"
|
||||
placeholder="输入授权用户名(留空不授权)"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item v-if="createModel.create_user" path="username" label="用户名">
|
||||
|
||||
@@ -18,6 +18,17 @@ const databaseType = [
|
||||
{ label: 'PostgreSQL', value: 'postgresql' }
|
||||
]
|
||||
|
||||
watch(
|
||||
() => createModel.value.type,
|
||||
(value) => {
|
||||
if (value === 'mysql') {
|
||||
createModel.value.port = 3306
|
||||
} else if (value === 'postgresql') {
|
||||
createModel.value.port = 5432
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const handleCreate = () => {
|
||||
useRequest(() => database.serverCreate(createModel.value)).onSuccess(() => {
|
||||
show.value = false
|
||||
@@ -31,7 +42,7 @@ const handleCreate = () => {
|
||||
<n-modal
|
||||
v-model:show="show"
|
||||
preset="card"
|
||||
title="添加数据库服务器"
|
||||
title="添加服务器"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
|
||||
@@ -4,34 +4,47 @@ import { NButton, NInput } from 'naive-ui'
|
||||
|
||||
const show = defineModel<boolean>('show', { type: Boolean, required: true })
|
||||
const createModel = ref({
|
||||
name: '',
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
port: 3306,
|
||||
server_id: null,
|
||||
username: '',
|
||||
password: '',
|
||||
host: 'localhost',
|
||||
privileges: [],
|
||||
remark: ''
|
||||
})
|
||||
|
||||
const databaseType = [
|
||||
{ label: 'MySQL', value: 'mysql' },
|
||||
{ label: 'PostgreSQL', value: 'postgresql' }
|
||||
const servers = ref<{ label: string; value: string }[]>([])
|
||||
|
||||
const hostType = [
|
||||
{ label: '本地(localhost)', value: 'localhost' },
|
||||
{ label: '所有(%)', value: '%' },
|
||||
{ label: '指定', value: '' }
|
||||
]
|
||||
|
||||
const handleCreate = () => {
|
||||
useRequest(() => database.serverCreate(createModel.value)).onSuccess(() => {
|
||||
useRequest(() => database.userCreate(createModel.value)).onSuccess(() => {
|
||||
show.value = false
|
||||
window.$message.success('添加成功')
|
||||
window.$bus.emit('database:refresh')
|
||||
window.$message.success('创建成功')
|
||||
window.$bus.emit('database-user:refresh')
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
database.serverList(1, 10000).then((data: any) => {
|
||||
for (const server of data.items) {
|
||||
servers.value.push({
|
||||
label: server.name,
|
||||
value: server.id
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-modal
|
||||
v-model:show="show"
|
||||
preset="card"
|
||||
title="添加数据库服务器"
|
||||
title="创建用户"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
@@ -39,51 +52,20 @@ const handleCreate = () => {
|
||||
@close="show = false"
|
||||
>
|
||||
<n-form :model="createModel">
|
||||
<n-form-item path="name" label="名称">
|
||||
<n-input
|
||||
v-model:value="createModel.name"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="输入数据库服务器名称"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="type" label="类型">
|
||||
<n-form-item path="server_id" label="服务器">
|
||||
<n-select
|
||||
v-model:value="createModel.type"
|
||||
v-model:value="createModel.server_id"
|
||||
@keydown.enter.prevent
|
||||
placeholder="选择数据库类型"
|
||||
:options="databaseType"
|
||||
placeholder="选择服务器"
|
||||
:options="servers"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-row :gutter="[0, 24]">
|
||||
<n-col :span="15">
|
||||
<n-form-item path="host" label="主机">
|
||||
<n-input
|
||||
v-model:value="createModel.host"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="输入数据库服务器主机"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-col>
|
||||
<n-col :span="2"></n-col>
|
||||
<n-col :span="7">
|
||||
<n-form-item path="port" label="端口">
|
||||
<n-input-number
|
||||
w-full
|
||||
v-model:value="createModel.port"
|
||||
@keydown.enter.prevent
|
||||
placeholder="输入数据库服务器端口"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-col>
|
||||
</n-row>
|
||||
<n-form-item path="username" label="用户名">
|
||||
<n-input
|
||||
v-model:value="createModel.username"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="输入数据库服务器用户名"
|
||||
placeholder="输入用户名"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="password" label="密码">
|
||||
@@ -91,15 +73,34 @@ const handleCreate = () => {
|
||||
v-model:value="createModel.password"
|
||||
type="password"
|
||||
@keydown.enter.prevent
|
||||
placeholder="输入数据库服务器密码"
|
||||
placeholder="输入密码"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="host-select" label="主机">
|
||||
<n-select
|
||||
v-model:value="createModel.host"
|
||||
@keydown.enter.prevent
|
||||
placeholder="选择主机"
|
||||
:options="hostType"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item v-if="createModel.host === ''" path="host" label="指定主机">
|
||||
<n-input
|
||||
v-model:value="createModel.host"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="输入受支持的主机地址"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="privileges" label="授权">
|
||||
<n-dynamic-input v-model:value="createModel.privileges" placeholder="输入数据库名" />
|
||||
</n-form-item>
|
||||
<n-form-item path="remark" label="备注">
|
||||
<n-input
|
||||
v-model:value="createModel.remark"
|
||||
type="textarea"
|
||||
@keydown.enter.prevent
|
||||
placeholder="输入数据库服务器备注"
|
||||
placeholder="输入数据库用户备注"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
|
||||
@@ -29,10 +29,10 @@ const createServerModalShow = ref(false)
|
||||
<TheIcon :size="18" icon="material-symbols:add" />
|
||||
创建数据库
|
||||
</n-button>
|
||||
<!--<n-button v-if="currentTab === 'user'" type="primary" @click="createUserModalShow = true">
|
||||
<n-button v-if="currentTab === 'user'" type="primary" @click="createUserModalShow = true">
|
||||
<TheIcon :size="18" icon="material-symbols:add" />
|
||||
创建用户
|
||||
</n-button>-->
|
||||
</n-button>
|
||||
<n-button v-if="currentTab === 'server'" type="primary" @click="createServerModalShow = true">
|
||||
<TheIcon :size="18" icon="material-symbols:add" />
|
||||
添加服务器
|
||||
|
||||
@@ -73,6 +73,35 @@ const columns: any = [
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
key: 'remark',
|
||||
minWidth: 250,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true },
|
||||
render(row: any) {
|
||||
return h(NInput, {
|
||||
size: 'small',
|
||||
value: row.remark,
|
||||
onBlur: () => handleRemark(row),
|
||||
onUpdateValue(v) {
|
||||
row.remark = v
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
width: 100,
|
||||
render(row: any) {
|
||||
return h(
|
||||
NTag,
|
||||
{ type: row.status === 'valid' ? 'success' : 'error' },
|
||||
{ default: () => (row.status === 'valid' ? '有效' : '无效') }
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '更新日期',
|
||||
key: 'updated_at',
|
||||
@@ -165,6 +194,12 @@ const handleDelete = async (id: number) => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleRemark = (row: any) => {
|
||||
database.serverRemark(row.id, row.remark).then(() => {
|
||||
window.$message.success('修改成功')
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.$bus.on('database-server:refresh', () => {
|
||||
refresh()
|
||||
|
||||
@@ -84,14 +84,26 @@ const columns: any = [
|
||||
render(row: any) {
|
||||
return h(NInput, {
|
||||
size: 'small',
|
||||
value: row.remark
|
||||
/*onBlur: () => handleRemark(row),
|
||||
value: row.remark,
|
||||
onBlur: () => handleRemark(row),
|
||||
onUpdateValue(v) {
|
||||
row.remark = v
|
||||
}*/
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
width: 100,
|
||||
render(row: any) {
|
||||
return h(
|
||||
NTag,
|
||||
{ type: row.status === 'valid' ? 'success' : 'error' },
|
||||
{ default: () => (row.status === 'valid' ? '有效' : '无效') }
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '更新日期',
|
||||
key: 'updated_at',
|
||||
@@ -155,6 +167,12 @@ const handleDelete = async (id: number) => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleRemark = (row: any) => {
|
||||
database.userRemark(row.id, row.remark).then(() => {
|
||||
window.$message.success('修改成功')
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.$bus.on('database-user:refresh', () => {
|
||||
refresh()
|
||||
|
||||
@@ -393,7 +393,7 @@ onMounted(() => {
|
||||
striped
|
||||
remote
|
||||
:loading="false"
|
||||
:scroll-x="1000"
|
||||
:scroll-x="1200"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
:row-key="(row: any) => row.id"
|
||||
|
||||
Reference in New Issue
Block a user