mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 06:47:20 +08:00
feat: 优化数据库删除
This commit is contained in:
@@ -17,16 +17,16 @@ const (
|
||||
)
|
||||
|
||||
type DatabaseUser struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
ServerID uint `gorm:"not null" json:"server_id"`
|
||||
Username string `gorm:"not null" json:"username"`
|
||||
Password string `gorm:"not null" json:"password"`
|
||||
Host string `gorm:"not null" json:"host"` // 仅 mysql
|
||||
Status DatabaseUserStatus `gorm:"-:all" json:"status"` // 仅显示
|
||||
Privileges map[string][]string `gorm:"-:all" json:"privileges"` // 仅显示
|
||||
Remark string `gorm:"not null" json:"remark"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
ServerID uint `gorm:"not null" json:"server_id"`
|
||||
Username string `gorm:"not null" json:"username"`
|
||||
Password string `gorm:"not null" json:"password"`
|
||||
Host string `gorm:"not null" json:"host"` // 仅 mysql
|
||||
Status DatabaseUserStatus `gorm:"-:all" json:"status"` // 仅显示
|
||||
Privileges []string `gorm:"-:all" json:"privileges"` // 仅显示
|
||||
Remark string `gorm:"not null" json:"remark"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
Server *DatabaseServer `gorm:"foreignKey:ServerID;references:ID" json:"server"`
|
||||
}
|
||||
@@ -59,5 +59,6 @@ type DatabaseUserRepo interface {
|
||||
Update(req *request.DatabaseUserUpdate) error
|
||||
UpdateRemark(req *request.DatabaseUserUpdateRemark) error
|
||||
Delete(id uint) error
|
||||
DeleteByNames(serverID uint, names []string) error
|
||||
DeleteByServerID(serverID uint) error
|
||||
}
|
||||
|
||||
@@ -78,7 +78,12 @@ func (r databaseRepo) Create(req *request.DatabaseCreate) error {
|
||||
return err
|
||||
}
|
||||
if req.CreateUser {
|
||||
if err = mysql.UserCreate(req.Username, req.Password, req.Host); err != nil {
|
||||
if err = NewDatabaseUserRepo().Create(&request.DatabaseUserCreate{
|
||||
ServerID: req.ServerID,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
Host: req.Host,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -96,7 +101,12 @@ func (r databaseRepo) Create(req *request.DatabaseCreate) error {
|
||||
return err
|
||||
}
|
||||
if req.CreateUser {
|
||||
if err = postgres.UserCreate(req.Username, req.Password); err != nil {
|
||||
if err = NewDatabaseUserRepo().Create(&request.DatabaseUserCreate{
|
||||
ServerID: req.ServerID,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
Host: req.Host,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ func (r databaseUserRepo) Create(req *request.DatabaseUserCreate) error {
|
||||
return err
|
||||
}
|
||||
|
||||
user := new(biz.DatabaseUser)
|
||||
switch server.Type {
|
||||
case biz.DatabaseTypeMysql:
|
||||
mysql, err := db.NewMySQL(server.Username, server.Password, fmt.Sprintf("%s:%d", server.Host, server.Port))
|
||||
@@ -70,6 +71,11 @@ func (r databaseUserRepo) Create(req *request.DatabaseUserCreate) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
user = &biz.DatabaseUser{
|
||||
ServerID: req.ServerID,
|
||||
Username: req.Username,
|
||||
Host: req.Host,
|
||||
}
|
||||
case biz.DatabaseTypePostgresql:
|
||||
postgres, err := db.NewPostgres(server.Username, server.Password, server.Host, server.Port)
|
||||
if err != nil {
|
||||
@@ -83,12 +89,10 @@ func (r databaseUserRepo) Create(req *request.DatabaseUserCreate) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
user := &biz.DatabaseUser{
|
||||
ServerID: req.ServerID,
|
||||
Username: req.Username,
|
||||
Host: req.Host,
|
||||
user = &biz.DatabaseUser{
|
||||
ServerID: req.ServerID,
|
||||
Username: req.Username,
|
||||
}
|
||||
}
|
||||
|
||||
if err = app.Orm.FirstOrInit(user, user).Error; err != nil {
|
||||
@@ -191,6 +195,46 @@ func (r databaseUserRepo) Delete(id uint) error {
|
||||
return app.Orm.Where("id = ?", id).Delete(&biz.DatabaseUser{}).Error
|
||||
}
|
||||
|
||||
func (r databaseUserRepo) DeleteByNames(serverID uint, names []string) error {
|
||||
server, err := NewDatabaseServerRepo().Get(serverID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch server.Type {
|
||||
case biz.DatabaseTypeMysql:
|
||||
mysql, err := db.NewMySQL(server.Username, server.Password, fmt.Sprintf("%s:%d", server.Host, server.Port))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
users := make([]*biz.DatabaseUser, 0)
|
||||
if err = app.Orm.Where("server_id = ? AND username IN ?", serverID, names).Find(&users).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
for name := range slices.Values(names) {
|
||||
host := "localhost"
|
||||
for u := range slices.Values(users) {
|
||||
if u.Username == name {
|
||||
host = u.Host
|
||||
break
|
||||
}
|
||||
}
|
||||
_ = mysql.UserDrop(name, host)
|
||||
}
|
||||
case biz.DatabaseTypePostgresql:
|
||||
postgres, err := db.NewPostgres(server.Username, server.Password, server.Host, server.Port)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for name := range slices.Values(names) {
|
||||
_ = postgres.UserDrop(name)
|
||||
}
|
||||
}
|
||||
|
||||
return app.Orm.Where("server_id = ? AND username IN ?", serverID, names).Delete(&biz.DatabaseUser{}).Error
|
||||
}
|
||||
|
||||
// DeleteByServerID 删除指定服务器的所有用户,只是删除面板记录,不会实际删除
|
||||
func (r databaseUserRepo) DeleteByServerID(serverID uint) error {
|
||||
return app.Orm.Where("server_id = ?", serverID).Delete(&biz.DatabaseUser{}).Error
|
||||
}
|
||||
@@ -225,6 +269,6 @@ func (r databaseUserRepo) fillUser(user *biz.DatabaseUser) {
|
||||
}
|
||||
// 初始化,防止 nil
|
||||
if user.Privileges == nil {
|
||||
user.Privileges = make(map[string][]string)
|
||||
user.Privileges = make([]string, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
"github.com/TheTNB/panel/pkg/acme"
|
||||
"github.com/TheTNB/panel/pkg/cert"
|
||||
"github.com/TheTNB/panel/pkg/db"
|
||||
"github.com/TheTNB/panel/pkg/io"
|
||||
"github.com/TheTNB/panel/pkg/nginx"
|
||||
"github.com/TheTNB/panel/pkg/punycode"
|
||||
@@ -507,17 +506,14 @@ func (r *websiteRepo) Delete(req *request.WebsiteDelete) error {
|
||||
_ = io.Remove(website.Path)
|
||||
}
|
||||
if req.DB {
|
||||
rootPassword, err := NewSettingRepo().Get(biz.SettingKeyMySQLRootPassword)
|
||||
if err != nil {
|
||||
return err
|
||||
repo := NewDatabaseServerRepo()
|
||||
if mysql, err := repo.GetByName("local_mysql"); err == nil {
|
||||
_ = NewDatabaseUserRepo().DeleteByNames(mysql.ID, []string{website.Name})
|
||||
_ = NewDatabaseRepo().Delete(mysql.ID, website.Name)
|
||||
}
|
||||
if mysql, err := db.NewMySQL("root", rootPassword, "/tmp/mysql.sock", "unix"); err == nil {
|
||||
_ = mysql.UserDrop(website.Name, "localhost")
|
||||
_ = mysql.DatabaseDrop(website.Name)
|
||||
}
|
||||
if postgres, err := db.NewPostgres("postgres", "", "127.0.0.1", 5432); err == nil {
|
||||
_ = postgres.UserDrop(website.Name)
|
||||
_ = postgres.DatabaseDrop(website.Name)
|
||||
if postgres, err := repo.GetByName("local_postgresql"); err == nil {
|
||||
_ = NewDatabaseUserRepo().DeleteByNames(postgres.ID, []string{website.Name})
|
||||
_ = NewDatabaseRepo().Delete(postgres.ID, website.Name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ func Http(r chi.Router) {
|
||||
server := service.NewDatabaseServerService()
|
||||
r.Get("/", server.List)
|
||||
r.Post("/", server.Create)
|
||||
r.Get("/{id}", server.Get)
|
||||
r.Put("/{id}", server.Update)
|
||||
r.Put("/{id}/remark", server.UpdateRemark)
|
||||
r.Delete("/{id}", server.Delete)
|
||||
@@ -84,6 +85,7 @@ func Http(r chi.Router) {
|
||||
user := service.NewDatabaseUserService()
|
||||
r.Get("/", user.List)
|
||||
r.Post("/", user.Create)
|
||||
r.Get("/{id}", user.Get)
|
||||
r.Put("/{id}", user.Update)
|
||||
r.Put("/{id}/remark", user.UpdateRemark)
|
||||
r.Delete("/{id}", user.Delete)
|
||||
|
||||
@@ -54,6 +54,22 @@ func (s *DatabaseServer) Create(w http.ResponseWriter, r *http.Request) {
|
||||
Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *DatabaseServer) Get(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.ID](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
server, err := s.databaseServerRepo.Get(req.ID)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
Success(w, server)
|
||||
}
|
||||
|
||||
func (s *DatabaseServer) Update(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.DatabaseServerUpdate](r)
|
||||
if err != nil {
|
||||
|
||||
@@ -54,6 +54,22 @@ func (s *DatabaseUser) Create(w http.ResponseWriter, r *http.Request) {
|
||||
Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *DatabaseUser) Get(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.ID](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := s.databaseUserRepo.Get(req.ID)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
Success(w, user)
|
||||
}
|
||||
|
||||
func (s *DatabaseUser) Update(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.DatabaseUserUpdate](r)
|
||||
if err != nil {
|
||||
|
||||
@@ -3,9 +3,9 @@ package db
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"regexp"
|
||||
"slices"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
@@ -122,52 +122,43 @@ func (r *MySQL) PrivilegesGrant(user, database, host string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *MySQL) UserPrivileges(user, host string) (map[string][]string, error) {
|
||||
func (r *MySQL) PrivilegesRevoke(user, database, host string) error {
|
||||
_, err := r.Exec(fmt.Sprintf("REVOKE ALL PRIVILEGES ON %s.* FROM '%s'@'%s'", database, user, host))
|
||||
r.flushPrivileges()
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *MySQL) UserPrivileges(user, host string) ([]string, error) {
|
||||
rows, err := r.Query(fmt.Sprintf("SHOW GRANTS FOR '%s'@'%s'", user, host))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
privileges := make(map[string][]string)
|
||||
re := regexp.MustCompile(`GRANT\s+ALL PRIVILEGES\s+ON\s+[\x60'"]?([^\s\x60'"]+)[\x60'"]?\.\*\s+TO\s+`)
|
||||
var databases []string
|
||||
for rows.Next() {
|
||||
var grant string
|
||||
if err = rows.Scan(&grant); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !strings.HasPrefix(grant, "GRANT ") {
|
||||
continue
|
||||
|
||||
// 使用正则表达式匹配
|
||||
matches := re.FindStringSubmatch(grant)
|
||||
if len(matches) == 2 {
|
||||
dbName := matches[1]
|
||||
if dbName != "*" {
|
||||
databases = append(databases, dbName)
|
||||
}
|
||||
}
|
||||
|
||||
parts := strings.Split(grant, " ON ")
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
privList := strings.TrimPrefix(parts[0], "GRANT ")
|
||||
privs := strings.Split(privList, ", ")
|
||||
|
||||
dbPart := strings.Split(parts[1], " TO")[0]
|
||||
// *.* 表示全局权限
|
||||
if dbPart == "*.*" {
|
||||
dbPart = "*"
|
||||
}
|
||||
|
||||
dbPart = strings.Trim(dbPart, "`")
|
||||
privileges[dbPart] = append(privileges[dbPart], privs...)
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return privileges, nil
|
||||
}
|
||||
|
||||
func (r *MySQL) PrivilegesRevoke(user, database, host string) error {
|
||||
_, err := r.Exec(fmt.Sprintf("REVOKE ALL PRIVILEGES ON %s.* FROM '%s'@'%s'", database, user, host))
|
||||
r.flushPrivileges()
|
||||
return err
|
||||
slices.Sort(databases)
|
||||
return slices.Compact(databases), nil
|
||||
}
|
||||
|
||||
func (r *MySQL) Users() ([]types.MySQLUser, error) {
|
||||
|
||||
@@ -3,10 +3,8 @@ package db
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
"slices"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/systemctl"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
@@ -123,14 +121,16 @@ func (r *Postgres) UserPassword(user, password string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Postgres) UserPrivileges(user string) (map[string][]string, error) {
|
||||
func (r *Postgres) UserPrivileges(user string) ([]string, error) {
|
||||
query := `
|
||||
SELECT
|
||||
table_catalog as database_name,
|
||||
string_agg(DISTINCT privilege_type, ',') as privileges
|
||||
FROM information_schema.role_database_privileges
|
||||
WHERE grantee = $1
|
||||
GROUP BY table_catalog`
|
||||
SELECT d.datname
|
||||
FROM pg_catalog.pg_database d
|
||||
JOIN pg_catalog.pg_roles r ON d.datdba = r.oid
|
||||
WHERE r.rolname = $1
|
||||
AND d.datistemplate = false
|
||||
AND d.datname NOT IN ('template0', 'template1', 'postgres')
|
||||
ORDER BY d.datname;
|
||||
`
|
||||
|
||||
rows, err := r.Query(query, user)
|
||||
if err != nil {
|
||||
@@ -138,22 +138,21 @@ func (r *Postgres) UserPrivileges(user string) (map[string][]string, error) {
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
privileges := make(map[string][]string)
|
||||
var databases []string
|
||||
|
||||
for rows.Next() {
|
||||
var db, privilegeStr string
|
||||
if err = rows.Scan(&db, &privilegeStr); err != nil {
|
||||
var dbName string
|
||||
if err = rows.Scan(&dbName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
privileges[db] = strings.Split(privilegeStr, ",")
|
||||
databases = append(databases, dbName)
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return privileges, nil
|
||||
return databases, nil
|
||||
}
|
||||
|
||||
func (r *Postgres) PrivilegesGrant(user, database string) error {
|
||||
|
||||
@@ -15,6 +15,8 @@ export default {
|
||||
http.Get('/databaseServer', { params: { page, limit } }),
|
||||
// 创建数据库服务器
|
||||
serverCreate: (data: any) => http.Post('/databaseServer', data),
|
||||
// 获取数据库服务器
|
||||
serverGet: (id: number) => http.Get(`/databaseServer/${id}`),
|
||||
// 更新数据库服务器
|
||||
serverUpdate: (id: number, data: any) => http.Put(`/databaseServer/${id}`, data),
|
||||
// 删除数据库服务器
|
||||
@@ -28,6 +30,8 @@ export default {
|
||||
userList: (page: number, limit: number) => http.Get('/databaseUser', { params: { page, limit } }),
|
||||
// 创建数据库用户
|
||||
userCreate: (data: any) => http.Post('/databaseUser', data),
|
||||
// 获取数据库用户
|
||||
userGet: (id: number) => http.Get(`/databaseUser/${id}`),
|
||||
// 更新数据库用户
|
||||
userUpdate: (id: number, data: any) => http.Put(`/databaseUser/${id}`, data),
|
||||
// 删除数据库用户
|
||||
|
||||
@@ -28,16 +28,21 @@ const handleCreate = () => {
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
database.serverList(1, 10000).then((data: any) => {
|
||||
for (const server of data.items) {
|
||||
servers.value.push({
|
||||
label: server.name,
|
||||
value: server.id
|
||||
watch(
|
||||
() => show.value,
|
||||
(value) => {
|
||||
if (value) {
|
||||
database.serverList(1, 10000).then((data: any) => {
|
||||
for (const server of data.items) {
|
||||
servers.value.push({
|
||||
label: server.name,
|
||||
value: server.id
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -28,16 +28,21 @@ const handleCreate = () => {
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
database.serverList(1, 10000).then((data: any) => {
|
||||
for (const server of data.items) {
|
||||
servers.value.push({
|
||||
label: server.name,
|
||||
value: server.id
|
||||
watch(
|
||||
() => show.value,
|
||||
(value) => {
|
||||
if (value) {
|
||||
database.serverList(1, 10000).then((data: any) => {
|
||||
for (const server of data.items) {
|
||||
servers.value.push({
|
||||
label: server.name,
|
||||
value: server.id
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -76,7 +81,7 @@ onMounted(() => {
|
||||
placeholder="输入密码"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="host-select" label="主机">
|
||||
<n-form-item path="host-select" label="主机(仅 MySQL)">
|
||||
<n-select
|
||||
v-model:value="createModel.host"
|
||||
@keydown.enter.prevent
|
||||
|
||||
71
web/src/views/database/UpdateUserModal.vue
Normal file
71
web/src/views/database/UpdateUserModal.vue
Normal file
@@ -0,0 +1,71 @@
|
||||
<script setup lang="ts">
|
||||
import database from '@/api/panel/database'
|
||||
import { NButton, NInput } from 'naive-ui'
|
||||
|
||||
const show = defineModel<boolean>('show', { type: Boolean, required: true })
|
||||
const id = defineModel<number>('id', { type: Number, required: true })
|
||||
const updateModel = ref({
|
||||
password: '',
|
||||
privileges: [],
|
||||
remark: ''
|
||||
})
|
||||
|
||||
const handleUpdate = () => {
|
||||
useRequest(() => database.userUpdate(id.value, updateModel.value)).onSuccess(() => {
|
||||
show.value = false
|
||||
window.$message.success('更新成功')
|
||||
window.$bus.emit('database-user:refresh')
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
() => show.value,
|
||||
(value) => {
|
||||
if (value && id.value) {
|
||||
database.userGet(id.value).then((data: any) => {
|
||||
updateModel.value.password = data.password
|
||||
updateModel.value.privileges = data.privileges
|
||||
updateModel.value.remark = data.remark
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-modal
|
||||
v-model:show="show"
|
||||
preset="card"
|
||||
title="更新用户"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
:segmented="false"
|
||||
@close="show = false"
|
||||
>
|
||||
<n-form :model="updateModel">
|
||||
<n-form-item path="password" label="密码">
|
||||
<n-input
|
||||
v-model:value="updateModel.password"
|
||||
type="password"
|
||||
@keydown.enter.prevent
|
||||
placeholder="输入密码"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="privileges" label="授权">
|
||||
<n-dynamic-input v-model:value="updateModel.privileges" placeholder="输入数据库名" />
|
||||
</n-form-item>
|
||||
<n-form-item path="remark" label="备注">
|
||||
<n-input
|
||||
v-model:value="updateModel.remark"
|
||||
type="textarea"
|
||||
@keydown.enter.prevent
|
||||
placeholder="输入数据库用户备注"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button type="info" block @click="handleUpdate">提交</n-button>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -1,9 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { renderIcon } from '@/utils'
|
||||
import { NButton, NInput, NInputGroup, NPopconfirm, NTag } from 'naive-ui'
|
||||
import { NButton, NFlex, NInput, NInputGroup, NPopconfirm, NTag } from 'naive-ui'
|
||||
|
||||
import database from '@/api/panel/database'
|
||||
import { formatDateTime } from '@/utils'
|
||||
import UpdateUserModal from '@/views/database/UpdateUserModal.vue'
|
||||
|
||||
const updateModal = ref(false)
|
||||
const updateID = ref(0)
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
@@ -63,7 +67,7 @@ const columns: any = [
|
||||
width: 150,
|
||||
render(row: any) {
|
||||
return h(NTag, null, {
|
||||
default: () => row.host
|
||||
default: () => row.host || '无'
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -75,6 +79,21 @@ const columns: any = [
|
||||
return row.server.name
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '授权',
|
||||
key: 'privileges',
|
||||
width: 200,
|
||||
render(row: any) {
|
||||
return h(NFlex, null, {
|
||||
default: () =>
|
||||
row.privileges.map((privilege: string) =>
|
||||
h(NTag, null, {
|
||||
default: () => privilege
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
key: 'remark',
|
||||
@@ -121,6 +140,21 @@ const columns: any = [
|
||||
hideInExcel: true,
|
||||
render(row: any) {
|
||||
return [
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
size: 'small',
|
||||
type: 'primary',
|
||||
onClick: () => {
|
||||
updateID.value = row.id
|
||||
updateModal.value = true
|
||||
}
|
||||
},
|
||||
{
|
||||
default: () => '编辑',
|
||||
icon: renderIcon('material-symbols:edit', { size: 14 })
|
||||
}
|
||||
),
|
||||
h(
|
||||
NPopconfirm,
|
||||
{
|
||||
@@ -128,7 +162,7 @@ const columns: any = [
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
return '确定删除服务器吗?'
|
||||
return '确定删除用户吗?'
|
||||
},
|
||||
trigger: () => {
|
||||
return h(
|
||||
@@ -188,7 +222,7 @@ onUnmounted(() => {
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
:scroll-x="1500"
|
||||
:scroll-x="1700"
|
||||
:loading="loading"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
@@ -205,6 +239,7 @@ onUnmounted(() => {
|
||||
pageSizes: [20, 50, 100, 200]
|
||||
}"
|
||||
/>
|
||||
<update-user-modal v-model:id="updateID" v-model:show="updateModal" />
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
||||
Reference in New Issue
Block a user