mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 07:57:21 +08:00
feat: 文件管理分页
This commit is contained in:
@@ -6,9 +6,11 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
commonrequests "panel/app/http/requests/common"
|
||||
|
||||
requests "panel/app/http/requests/file"
|
||||
"panel/pkg/tools"
|
||||
@@ -454,7 +456,8 @@ func (r *FileController) Search(ctx http.Context) http.Response {
|
||||
// @Tags 文件管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data query requests.Exist true "request"
|
||||
// @Param data query requests.Exist true "request"
|
||||
// @Param data query commonrequests.Paginate true "request"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Router /panel/file/list [get]
|
||||
func (r *FileController) List(ctx http.Context) http.Response {
|
||||
@@ -464,6 +467,12 @@ func (r *FileController) List(ctx http.Context) http.Response {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
var paginate commonrequests.Paginate
|
||||
paginateSanitize := Sanitize(ctx, &paginate)
|
||||
if paginateSanitize != nil {
|
||||
return paginateSanitize
|
||||
}
|
||||
|
||||
fileInfoList, err := os.ReadDir(request.Path)
|
||||
if err != nil {
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
@@ -472,17 +481,44 @@ func (r *FileController) List(ctx http.Context) http.Response {
|
||||
var paths []any
|
||||
for _, fileInfo := range fileInfoList {
|
||||
info, _ := fileInfo.Info()
|
||||
var owner, group string
|
||||
stat, ok := info.Sys().(*syscall.Stat_t)
|
||||
if ok {
|
||||
owner = tools.GetUser(stat.Uid)
|
||||
group = tools.GetGroup(stat.Gid)
|
||||
}
|
||||
|
||||
paths = append(paths, map[string]any{
|
||||
"name": info.Name(),
|
||||
"full": filepath.Join(request.Path, info.Name()),
|
||||
"size": tools.FormatBytes(float64(info.Size())),
|
||||
"mode_str": info.Mode().String(),
|
||||
"mode": fmt.Sprintf("%04o", info.Mode().Perm()),
|
||||
"owner": owner,
|
||||
"group": group,
|
||||
"dir": info.IsDir(),
|
||||
"modify": carbon.FromStdTime(info.ModTime()).ToDateTimeString(),
|
||||
})
|
||||
}
|
||||
|
||||
return Success(ctx, paths)
|
||||
start := paginate.Limit * (paginate.Page - 1)
|
||||
end := paginate.Limit * paginate.Page
|
||||
if start > len(paths) {
|
||||
start = len(paths)
|
||||
}
|
||||
if end > len(paths) {
|
||||
end = len(paths)
|
||||
}
|
||||
|
||||
paged := paths[start:end]
|
||||
if paged == nil {
|
||||
paged = []any{}
|
||||
}
|
||||
|
||||
return Success(ctx, http.Json{
|
||||
"total": len(paths),
|
||||
"items": paged,
|
||||
})
|
||||
}
|
||||
|
||||
// setPermission
|
||||
|
||||
@@ -15,7 +15,7 @@ func (r *Exist) Authorize(ctx http.Context) error {
|
||||
|
||||
func (r *Exist) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"path": "regex:^/[a-zA-Z0-9_.@#$%-]+(\\/[a-zA-Z0-9_.@#$%-]+)*$|path_exists",
|
||||
"path": "regex:^/([a-zA-Z0-9_.@#$%-]+(\\/[a-zA-Z0-9_.@#$%-]+)*)?$|path_exists",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/database/orm"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
)
|
||||
|
||||
type Cert struct {
|
||||
orm.Model
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
UserID uint `gorm:"default:null" json:"user_id"` // 关联的 ACME 用户 ID
|
||||
WebsiteID *uint `gorm:"default:null" json:"website_id"` // 关联的网站 ID
|
||||
|
||||
10
docs/docs.go
10
docs/docs.go
@@ -2339,6 +2339,16 @@ const docTemplate = `{
|
||||
"type": "string",
|
||||
"name": "path",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
||||
@@ -2332,6 +2332,16 @@
|
||||
"type": "string",
|
||||
"name": "path",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
||||
@@ -2051,6 +2051,12 @@ paths:
|
||||
- in: query
|
||||
name: path
|
||||
type: string
|
||||
- in: query
|
||||
name: limit
|
||||
type: integer
|
||||
- in: query
|
||||
name: page
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
||||
@@ -7,7 +7,9 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/goravel/framework/support"
|
||||
@@ -258,3 +260,26 @@ func TempDir(prefix string) (string, error) {
|
||||
func TempFile(prefix string) (*os.File, error) {
|
||||
return os.CreateTemp("", prefix)
|
||||
}
|
||||
|
||||
// IsSymlink 判读是否为软链接
|
||||
func IsSymlink(mode os.FileMode) bool {
|
||||
return mode&os.ModeSymlink != 0
|
||||
}
|
||||
|
||||
// GetUser 通过 uid 获取用户名
|
||||
func GetUser(uid uint32) string {
|
||||
usr, err := user.LookupId(strconv.Itoa(int(uid)))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return usr.Username
|
||||
}
|
||||
|
||||
// GetGroup 通过 gid 获取组名
|
||||
func GetGroup(gid uint32) string {
|
||||
usr, err := user.LookupGroupId(strconv.Itoa(int(gid)))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return usr.Name
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user