2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 04:22:33 +08:00

feat: 数据库管理优化2

This commit is contained in:
耗子
2024-11-27 01:45:58 +08:00
parent cd8a10d799
commit 3677d0317c
12 changed files with 90 additions and 6 deletions

View File

@@ -20,10 +20,12 @@ type Database struct {
Server string `json:"server"`
ServerID uint `json:"server_id"`
Encoding string `json:"encoding"`
Comment string `json:"comment"`
}
type DatabaseRepo interface {
List(page, limit uint) ([]*Database, int64, error)
Create(req *request.DatabaseCreate) error
Delete(serverID uint, name string) error
Comment(req *request.DatabaseComment) error
}

View File

@@ -1,6 +1,7 @@
package data
import (
"errors"
"fmt"
"slices"
@@ -53,6 +54,7 @@ func (r databaseRepo) List(page, limit uint) ([]*biz.Database, int64, error) {
Server: server.Name,
ServerID: server.ID,
Encoding: item.Encoding,
Comment: item.Comment,
})
}
}
@@ -134,3 +136,23 @@ func (r databaseRepo) Delete(serverID uint, name string) error {
return nil
}
func (r databaseRepo) Comment(req *request.DatabaseComment) error {
server, err := NewDatabaseServerRepo().Get(req.ServerID)
if err != nil {
return err
}
switch server.Type {
case biz.DatabaseTypeMysql:
return errors.New("mysql not support database comment")
case biz.DatabaseTypePostgresql:
postgres, err := db.NewPostgres(server.Username, server.Password, server.Host, server.Port)
if err != nil {
return err
}
return postgres.DatabaseComment(req.Name, req.Comment)
}
return nil
}

View File

@@ -14,3 +14,9 @@ type DatabaseDelete struct {
ServerID uint `form:"server_id" json:"server_id" validate:"required,exists=database_servers id"`
Name string `form:"name" json:"name" validate:"required"`
}
type DatabaseComment struct {
ServerID uint `form:"server_id" json:"server_id" validate:"required,exists=database_servers id"`
Name string `form:"name" json:"name" validate:"required"`
Comment string `form:"comment" json:"comment"`
}

View File

@@ -67,6 +67,7 @@ func Http(r chi.Router) {
r.Get("/", database.List)
r.Post("/", database.Create)
r.Delete("/", database.Delete)
r.Post("/comment", database.Comment)
})
r.Route("/databaseServer", func(r chi.Router) {

View File

@@ -39,6 +39,7 @@ func Success(w http.ResponseWriter, data any) {
func Error(w http.ResponseWriter, code int, format string, args ...any) {
render := chix.NewRender(w)
defer render.Release()
render.Header(chix.HeaderContentType, chix.MIMEApplicationJSONCharsetUTF8) // must before Status()
render.Status(code)
render.JSON(&ErrorResponse{
Message: fmt.Sprintf(format, args...),
@@ -49,6 +50,7 @@ func Error(w http.ResponseWriter, code int, format string, args ...any) {
func ErrorSystem(w http.ResponseWriter) {
render := chix.NewRender(w)
defer render.Release()
render.Header(chix.HeaderContentType, chix.MIMEApplicationJSONCharsetUTF8) // must before Status()
render.Status(http.StatusInternalServerError)
render.JSON(&ErrorResponse{
Message: "系统内部错误",

View File

@@ -68,3 +68,18 @@ func (s *Database) Delete(w http.ResponseWriter, r *http.Request) {
Success(w, nil)
}
func (s *Database) Comment(w http.ResponseWriter, r *http.Request) {
req, err := Bind[request.DatabaseComment](r)
if err != nil {
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if err = s.databaseRepo.Comment(req); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
Success(w, nil)
}

View File

@@ -95,6 +95,11 @@ func (r *Postgres) DatabaseSize(name string) (int64, error) {
return size, nil
}
func (r *Postgres) DatabaseComment(name, comment string) error {
_, err := r.Exec(fmt.Sprintf("COMMENT ON DATABASE %s IS '%s'", name, comment))
return err
}
func (r *Postgres) UserCreate(user, password string) error {
_, err := r.Exec(fmt.Sprintf("CREATE USER %s WITH PASSWORD '%s'", user, password))
if err != nil {
@@ -221,7 +226,11 @@ func (r *Postgres) Users() ([]types.PostgresUser, error) {
func (r *Postgres) Databases() ([]types.PostgresDatabase, error) {
query := `
SELECT d.datname, pg_catalog.pg_get_userbyid(d.datdba), pg_catalog.pg_encoding_to_char(d.encoding)
SELECT
d.datname,
pg_catalog.pg_get_userbyid(d.datdba),
pg_catalog.pg_encoding_to_char(d.encoding),
COALESCE(pg_catalog.shobj_description(d.oid, 'pg_database'), '')
FROM pg_catalog.pg_database d
WHERE datistemplate = false;
`
@@ -234,7 +243,7 @@ func (r *Postgres) Databases() ([]types.PostgresDatabase, error) {
var databases []types.PostgresDatabase
for rows.Next() {
var db types.PostgresDatabase
if err := rows.Scan(&db.Name, &db.Owner, &db.Encoding); err != nil {
if err := rows.Scan(&db.Name, &db.Owner, &db.Encoding, &db.Comment); err != nil {
return nil, err
}
if slices.Contains([]string{"template0", "template1", "postgres"}, db.Name) {

View File

@@ -9,4 +9,5 @@ type PostgresDatabase struct {
Name string `json:"name"`
Owner string `json:"owner"`
Encoding string `json:"encoding"`
Comment string `json:"comment"`
}

View File

@@ -7,6 +7,9 @@ export default {
create: (data: any) => http.Post(`/database`, data),
// 删除数据库
delete: (server_id: number, name: string) => http.Delete(`/database`, { server_id, name }),
// 更新评论
comment: (server_id: number, name: string, comment: string) =>
http.Post(`/database/comment`, { server_id, name, comment }),
// 获取数据库服务器列表
serverList: (page: number, limit: number) =>
http.Get('/databaseServer', { params: { page, limit } }),

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import { renderIcon } from '@/utils'
import { NButton, NPopconfirm, NTag } from 'naive-ui'
import { NButton, NInput, NPopconfirm, NTag } from 'naive-ui'
import database from '@/api/panel/database'
@@ -50,6 +50,23 @@ const columns: any = [
})
}
},
{
title: '备注',
key: 'comment',
minWidth: 250,
resizable: true,
ellipsis: { tooltip: true },
render(row: any) {
return h(NInput, {
size: 'small',
value: row.comment,
onBlur: () => handleComment(row),
onUpdateValue(v) {
row.comment = v
}
})
}
},
{
title: '操作',
key: 'actions',
@@ -104,6 +121,12 @@ const handleDelete = async (serverID: number, name: string) => {
})
}
const handleComment = (row: any) => {
database.comment(row.server_id, row.name, row.comment).then(() => {
window.$message.success('修改成功')
})
}
onMounted(() => {
window.$bus.on('database:refresh', () => {
refresh()
@@ -119,7 +142,7 @@ onUnmounted(() => {
<n-data-table
striped
remote
:scroll-x="800"
:scroll-x="1000"
:loading="loading"
:columns="columns"
:data="data"

View File

@@ -215,7 +215,7 @@ onUnmounted(() => {
<n-data-table
striped
remote
:scroll-x="1200"
:scroll-x="1500"
:loading="loading"
:columns="columns"
:data="data"

View File

@@ -188,7 +188,7 @@ onUnmounted(() => {
<n-data-table
striped
remote
:scroll-x="1400"
:scroll-x="1500"
:loading="loading"
:columns="columns"
:data="data"