mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-24 02:59:16 +08:00
feat: 文件增加收藏夹功能 (#2612)
Refs https://github.com/1Panel-dev/1Panel/issues/492
This commit is contained in:
parent
8715cfc343
commit
b38abf852d
@ -55,4 +55,5 @@ var (
|
||||
hostToolService = service.NewIHostToolService()
|
||||
|
||||
recycleBinService = service.NewIRecycleBinService()
|
||||
favoriteService = service.NewIFavoriteService()
|
||||
)
|
||||
|
76
backend/app/api/v1/favorite.go
Normal file
76
backend/app/api/v1/favorite.go
Normal file
@ -0,0 +1,76 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags File
|
||||
// @Summary List favorites
|
||||
// @Description 获取收藏列表
|
||||
// @Accept json
|
||||
// @Param request body dto.PageInfo true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/favorite/search [post]
|
||||
func (b *BaseApi) SearchFavorite(c *gin.Context) {
|
||||
var req dto.PageInfo
|
||||
if err := helper.CheckBind(req, c); err != nil {
|
||||
return
|
||||
}
|
||||
total, list, err := favoriteService.Page(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, dto.PageResult{
|
||||
Total: total,
|
||||
Items: list,
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
// @Summary Create favorite
|
||||
// @Description 创建收藏
|
||||
// @Accept json
|
||||
// @Param request body request.FavoriteCreate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/favorite [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"收藏文件/文件夹 [path]","formatEN":"收藏文件/文件夹 [path]"}
|
||||
func (b *BaseApi) CreateFavorite(c *gin.Context) {
|
||||
var req request.FavoriteCreate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
favorite, err := favoriteService.Create(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, favorite)
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
// @Summary Delete favorite
|
||||
// @Description 删除收藏
|
||||
// @Accept json
|
||||
// @Param request body request.FavoriteDelete true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/favorite/del [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"favorites","output_column":"path","output_value":"path"}],"formatZH":"删除收藏 [path]","formatEN":"delete avorite [path]"}
|
||||
func (b *BaseApi) DeleteFavorite(c *gin.Context) {
|
||||
var req request.FavoriteDelete
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := favoriteService.Delete(req.ID); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
@ -115,7 +115,7 @@ func GetTxAndContext() (tx *gorm.DB, ctx context.Context) {
|
||||
}
|
||||
|
||||
func CheckBindAndValidate(req interface{}, c *gin.Context) error {
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
if err := c.ShouldBindJSON(req); err != nil {
|
||||
ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return err
|
||||
}
|
||||
@ -125,3 +125,11 @@ func CheckBindAndValidate(req interface{}, c *gin.Context) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CheckBind(req interface{}, c *gin.Context) error {
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -8,14 +8,14 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags RecycleBin
|
||||
// @Tags File
|
||||
// @Summary List RecycleBin files
|
||||
// @Description 获取回收站文件列表
|
||||
// @Accept json
|
||||
// @Param request body dto.PageInfo true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /recycle/search [post]
|
||||
// @Router /files/recycle/search [post]
|
||||
func (b *BaseApi) SearchRecycleBinFile(c *gin.Context) {
|
||||
var req dto.PageInfo
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@ -32,15 +32,15 @@ func (b *BaseApi) SearchRecycleBinFile(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags RecycleBin
|
||||
// @Tags File
|
||||
// @Summary Reduce RecycleBin files
|
||||
// @Description 还原回收站文件
|
||||
// @Accept json
|
||||
// @Param request body request.RecycleBinReduce true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /recycle/reduce [post]
|
||||
// @x-panel-log {"bodyKeys":["name],"paramKeys":[],"BeforeFunctions":[],"formatZH":"还原回收站文件 [name]","formatEN":"Reduce RecycleBin file [name]"}
|
||||
// @Router /files/recycle/reduce [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"还原回收站文件 [name]","formatEN":"Reduce RecycleBin file [name]"}
|
||||
func (b *BaseApi) ReduceRecycleBinFile(c *gin.Context) {
|
||||
var req request.RecycleBinReduce
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@ -53,13 +53,13 @@ func (b *BaseApi) ReduceRecycleBinFile(c *gin.Context) {
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags RecycleBin
|
||||
// @Tags File
|
||||
// @Summary Clear RecycleBin files
|
||||
// @Description 清空回收站文件
|
||||
// @Accept json
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /recycle/clear [post]
|
||||
// @Router /files/recycle/clear [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清空回收站","formatEN":"清空回收站"}
|
||||
func (b *BaseApi) ClearRecycleBinFile(c *gin.Context) {
|
||||
if err := recycleBinService.Clear(); err != nil {
|
||||
|
9
backend/app/dto/request/favorite.go
Normal file
9
backend/app/dto/request/favorite.go
Normal file
@ -0,0 +1,9 @@
|
||||
package request
|
||||
|
||||
type FavoriteCreate struct {
|
||||
Path string `json:"path" validate:"required"`
|
||||
}
|
||||
|
||||
type FavoriteDelete struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
}
|
7
backend/app/dto/response/favorite.go
Normal file
7
backend/app/dto/response/favorite.go
Normal file
@ -0,0 +1,7 @@
|
||||
package response
|
||||
|
||||
import "github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
|
||||
type FavoriteDTO struct {
|
||||
model.Favorite
|
||||
}
|
10
backend/app/model/favorite.go
Normal file
10
backend/app/model/favorite.go
Normal file
@ -0,0 +1,10 @@
|
||||
package model
|
||||
|
||||
type Favorite struct {
|
||||
BaseModel
|
||||
Name string `gorm:"type:varchar(256);not null;" json:"name" `
|
||||
Path string `gorm:"type:varchar(256);not null;unique" json:"path"`
|
||||
Type string `gorm:"type:varchar(64);" json:"type"`
|
||||
IsDir bool `json:"isDir"`
|
||||
IsTxt bool `json:"isTxt"`
|
||||
}
|
66
backend/app/repo/favorite.go
Normal file
66
backend/app/repo/favorite.go
Normal file
@ -0,0 +1,66 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type FavoriteRepo struct{}
|
||||
|
||||
type IFavoriteRepo interface {
|
||||
Page(page, size int, opts ...DBOption) (int64, []model.Favorite, error)
|
||||
Create(group *model.Favorite) error
|
||||
Delete(opts ...DBOption) error
|
||||
GetFirst(opts ...DBOption) (model.Favorite, error)
|
||||
All() ([]model.Favorite, error)
|
||||
WithByPath(path string) DBOption
|
||||
}
|
||||
|
||||
func NewIFavoriteRepo() IFavoriteRepo {
|
||||
return &FavoriteRepo{}
|
||||
}
|
||||
|
||||
func (f *FavoriteRepo) WithByPath(path string) DBOption {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("path = ?", path)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FavoriteRepo) Page(page, size int, opts ...DBOption) (int64, []model.Favorite, error) {
|
||||
var (
|
||||
favorites []model.Favorite
|
||||
count int64
|
||||
)
|
||||
count = int64(0)
|
||||
db := getDb(opts...).Model(&model.Favorite{})
|
||||
db = db.Count(&count)
|
||||
err := db.Limit(size).Offset(size * (page - 1)).Find(&favorites).Error
|
||||
return count, favorites, err
|
||||
}
|
||||
|
||||
func (f *FavoriteRepo) Create(favorite *model.Favorite) error {
|
||||
return global.DB.Create(favorite).Error
|
||||
}
|
||||
|
||||
func (f *FavoriteRepo) GetFirst(opts ...DBOption) (model.Favorite, error) {
|
||||
var favorite model.Favorite
|
||||
db := getDb(opts...).Model(&model.Favorite{})
|
||||
if err := db.First(&favorite).Error; err != nil {
|
||||
return favorite, err
|
||||
}
|
||||
return favorite, nil
|
||||
}
|
||||
|
||||
func (f *FavoriteRepo) Delete(opts ...DBOption) error {
|
||||
db := getDb(opts...).Model(&model.Favorite{})
|
||||
return db.Delete(&model.Favorite{}).Error
|
||||
}
|
||||
|
||||
func (f *FavoriteRepo) All() ([]model.Favorite, error) {
|
||||
var favorites []model.Favorite
|
||||
if err := getDb().Find(&favorites).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return favorites, nil
|
||||
}
|
@ -37,4 +37,6 @@ var (
|
||||
snapshotRepo = repo.NewISnapshotRepo()
|
||||
|
||||
runtimeRepo = repo.NewIRunTimeRepo()
|
||||
|
||||
favoriteRepo = repo.NewIFavoriteRepo()
|
||||
)
|
||||
|
83
backend/app/service/favorite.go
Normal file
83
backend/app/service/favorite.go
Normal file
@ -0,0 +1,83 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/response"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
"github.com/spf13/afero"
|
||||
)
|
||||
|
||||
type FavoriteService struct {
|
||||
}
|
||||
|
||||
type IFavoriteService interface {
|
||||
Page(req dto.PageInfo) (int64, []response.FavoriteDTO, error)
|
||||
Create(req request.FavoriteCreate) (*model.Favorite, error)
|
||||
Delete(id uint) error
|
||||
}
|
||||
|
||||
func NewIFavoriteService() IFavoriteService {
|
||||
return &FavoriteService{}
|
||||
}
|
||||
|
||||
func (f *FavoriteService) Page(req dto.PageInfo) (int64, []response.FavoriteDTO, error) {
|
||||
total, favorites, err := favoriteRepo.Page(req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
var dtoFavorites []response.FavoriteDTO
|
||||
for _, favorite := range favorites {
|
||||
dtoFavorites = append(dtoFavorites, response.FavoriteDTO{
|
||||
Favorite: favorite,
|
||||
})
|
||||
}
|
||||
return total, dtoFavorites, nil
|
||||
}
|
||||
|
||||
func (f *FavoriteService) Create(req request.FavoriteCreate) (*model.Favorite, error) {
|
||||
exist, _ := favoriteRepo.GetFirst(favoriteRepo.WithByPath(req.Path))
|
||||
if exist.ID > 0 {
|
||||
return nil, buserr.New(constant.ErrFavoriteExist)
|
||||
}
|
||||
op := files.NewFileOp()
|
||||
if !op.Stat(req.Path) {
|
||||
return nil, buserr.New(constant.ErrLinkPathNotFound)
|
||||
}
|
||||
openFile, err := op.OpenFile(req.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fileInfo, err := openFile.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
favorite := &model.Favorite{
|
||||
Name: fileInfo.Name(),
|
||||
IsDir: fileInfo.IsDir(),
|
||||
Path: req.Path,
|
||||
}
|
||||
if fileInfo.Size() <= 10*1024*1024 {
|
||||
afs := &afero.Afero{Fs: op.Fs}
|
||||
cByte, err := afs.ReadFile(req.Path)
|
||||
if err == nil {
|
||||
if len(cByte) > 0 && !files.DetectBinary(cByte) {
|
||||
favorite.IsTxt = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := favoriteRepo.Create(favorite); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return favorite, nil
|
||||
}
|
||||
|
||||
func (f *FavoriteService) Delete(id uint) error {
|
||||
if err := favoriteRepo.Delete(commonRepo.WithByID(id)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -90,6 +90,7 @@ var (
|
||||
ErrFileUpload = "ErrFileUpload"
|
||||
ErrFileDownloadDir = "ErrFileDownloadDir"
|
||||
ErrCmdNotFound = "ErrCmdNotFound"
|
||||
ErrFavoriteExist = "ErrFavoriteExist"
|
||||
)
|
||||
|
||||
// mysql
|
||||
|
@ -64,6 +64,7 @@ ErrFileUpload: "Failed to upload file {{.name}} {{.detail}}"
|
||||
ErrFileDownloadDir: "Download folder not supported"
|
||||
ErrCmdNotFound: "{{ .name}} command does not exist, please install this command on the host first"
|
||||
ErrSourcePathNotFound: "Source directory does not exist"
|
||||
ErrFavoriteExist: "This path has been collected"
|
||||
|
||||
#website
|
||||
ErrDomainIsExist: "Domain is already exist"
|
||||
|
@ -64,6 +64,7 @@ ErrFileUpload: "{{ .name }} 上傳文件失敗 {{ .detail}}"
|
||||
ErrFileDownloadDir: "不支持下載文件夾"
|
||||
ErrCmdNotFound: "{{ .name}} 命令不存在,請先在宿主機安裝此命令"
|
||||
ErrSourcePathNotFound: "源目錄不存在"
|
||||
ErrFavoriteExist: "已收藏此路徑"
|
||||
|
||||
#website
|
||||
ErrDomainIsExist: "域名已存在"
|
||||
|
@ -64,6 +64,7 @@ ErrFileUpload: "{{ .name }} 上传文件失败 {{ .detail}}"
|
||||
ErrFileDownloadDir: "不支持下载文件夹"
|
||||
ErrCmdNotFound: "{{ .name}} 命令不存在,请先在宿主机安装此命令"
|
||||
ErrSourcePathNotFound: "源目录不存在"
|
||||
ErrFavoriteExist: "已收藏此路径"
|
||||
|
||||
#website
|
||||
ErrDomainIsExist: "域名已存在"
|
||||
|
@ -47,6 +47,7 @@ func Init() {
|
||||
migrations.AddDefaultNetwork,
|
||||
migrations.UpdateRuntime,
|
||||
migrations.UpdateTag,
|
||||
migrations.AddFavorite,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
17
backend/init/migration/migrations/v_1_8.go
Normal file
17
backend/init/migration/migrations/v_1_8.go
Normal file
@ -0,0 +1,17 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var AddFavorite = &gormigrate.Migration{
|
||||
ID: "20231020-add-favorite",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.Favorite{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
@ -41,5 +41,10 @@ func (f *FileRouter) InitFileRouter(Router *gin.RouterGroup) {
|
||||
fileRouter.POST("/recycle/search", baseApi.SearchRecycleBinFile)
|
||||
fileRouter.POST("/recycle/reduce", baseApi.ReduceRecycleBinFile)
|
||||
fileRouter.POST("/recycle/clear", baseApi.ClearRecycleBinFile)
|
||||
|
||||
fileRouter.POST("/favorite/search", baseApi.SearchFavorite)
|
||||
fileRouter.POST("/favorite", baseApi.CreateFavorite)
|
||||
fileRouter.POST("/favorite/del", baseApi.DeleteFavorite)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package files
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"io/fs"
|
||||
@ -42,6 +43,7 @@ type FileInfo struct {
|
||||
FileMode os.FileMode `json:"-"`
|
||||
Items []*FileInfo `json:"items"`
|
||||
ItemTotal int `json:"itemTotal"`
|
||||
FavoriteID uint `json:"favoriteID"`
|
||||
}
|
||||
|
||||
type FileOption struct {
|
||||
@ -88,6 +90,12 @@ func NewFileInfo(op FileOption) (*FileInfo, error) {
|
||||
Group: GetGroup(info.Sys().(*syscall.Stat_t).Gid),
|
||||
MimeType: GetMimeType(op.Path),
|
||||
}
|
||||
favoriteRepo := repo.NewIFavoriteRepo()
|
||||
favorite, _ := favoriteRepo.GetFirst(favoriteRepo.WithByPath(op.Path))
|
||||
if favorite.ID > 0 {
|
||||
file.FavoriteID = favorite.ID
|
||||
}
|
||||
|
||||
if file.IsSymlink {
|
||||
file.LinkPath = GetSymlink(op.Path)
|
||||
}
|
||||
@ -266,7 +274,11 @@ func (f *FileInfo) listChildren(option FileOption) error {
|
||||
Uid: strconv.FormatUint(uint64(df.Sys().(*syscall.Stat_t).Uid), 10),
|
||||
Gid: strconv.FormatUint(uint64(df.Sys().(*syscall.Stat_t).Gid), 10),
|
||||
}
|
||||
|
||||
favoriteRepo := repo.NewIFavoriteRepo()
|
||||
favorite, _ := favoriteRepo.GetFirst(favoriteRepo.WithByPath(fPath))
|
||||
if favorite.ID > 0 {
|
||||
file.FavoriteID = favorite.ID
|
||||
}
|
||||
if isSymlink {
|
||||
file.LinkPath = GetSymlink(fPath)
|
||||
}
|
||||
@ -305,7 +317,7 @@ func (f *FileInfo) getContent() error {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if len(cByte) > 0 && detectBinary(cByte) {
|
||||
if len(cByte) > 0 && DetectBinary(cByte) {
|
||||
return buserr.New(constant.ErrFileCanNotRead)
|
||||
}
|
||||
f.Content = string(cByte)
|
||||
@ -315,7 +327,7 @@ func (f *FileInfo) getContent() error {
|
||||
}
|
||||
}
|
||||
|
||||
func detectBinary(buf []byte) bool {
|
||||
func DetectBinary(buf []byte) bool {
|
||||
whiteByte := 0
|
||||
n := min(1024, len(buf))
|
||||
for i := 0; i < n; i++ {
|
||||
|
@ -5368,6 +5368,132 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/favorite": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "创建收藏",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "Create favorite",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.FavoriteCreate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [
|
||||
"path"
|
||||
],
|
||||
"formatEN": "收藏文件/文件夹 [path]",
|
||||
"formatZH": "收藏文件/文件夹 [path]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/favorite/del": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "删除收藏",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "Delete favorite",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.FavoriteDelete"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [
|
||||
{
|
||||
"db": "favorites",
|
||||
"input_column": "id",
|
||||
"input_value": "id",
|
||||
"isList": false,
|
||||
"output_column": "path",
|
||||
"output_value": "path"
|
||||
}
|
||||
],
|
||||
"bodyKeys": [
|
||||
"id"
|
||||
],
|
||||
"formatEN": "delete avorite [path]",
|
||||
"formatZH": "删除收藏 [path]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/favorite/search": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取收藏列表",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "List favorites",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.PageInfo"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/mode": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -5498,6 +5624,110 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/recycle/clear": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "清空回收站文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "Clear RecycleBin files",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "清空回收站",
|
||||
"formatZH": "清空回收站",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/recycle/reduce": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "还原回收站文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "Reduce RecycleBin files",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.RecycleBinReduce"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [
|
||||
"name"
|
||||
],
|
||||
"formatEN": "Reduce RecycleBin file [name]",
|
||||
"formatZH": "还原回收站文件 [name]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/recycle/search": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取回收站文件列表",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "List RecycleBin files",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.PageInfo"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/rename": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -7826,94 +8056,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/recycle/clear": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "清空回收站文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"RecycleBin"
|
||||
],
|
||||
"summary": "Clear RecycleBin files",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/recycle/reduce": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "还原回收站文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"RecycleBin"
|
||||
],
|
||||
"summary": "Reduce RecycleBin files",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.RecycleBinReduce"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/recycle/search": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取回收站文件列表",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"RecycleBin"
|
||||
],
|
||||
"summary": "List RecycleBin files",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.PageInfo"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/runtimes": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -15563,6 +15705,9 @@ const docTemplate = `{
|
||||
"extension": {
|
||||
"type": "string"
|
||||
},
|
||||
"favoriteID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"gid": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -16212,6 +16357,28 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.FavoriteCreate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.FavoriteDelete": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.FileBatchDelete": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -16938,6 +17105,9 @@ const docTemplate = `{
|
||||
"from": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"rName": {
|
||||
"type": "string"
|
||||
}
|
||||
@ -18062,6 +18232,9 @@ const docTemplate = `{
|
||||
"extension": {
|
||||
"type": "string"
|
||||
},
|
||||
"favoriteID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"gid": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -5361,6 +5361,132 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/favorite": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "创建收藏",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "Create favorite",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.FavoriteCreate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [
|
||||
"path"
|
||||
],
|
||||
"formatEN": "收藏文件/文件夹 [path]",
|
||||
"formatZH": "收藏文件/文件夹 [path]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/favorite/del": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "删除收藏",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "Delete favorite",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.FavoriteDelete"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [
|
||||
{
|
||||
"db": "favorites",
|
||||
"input_column": "id",
|
||||
"input_value": "id",
|
||||
"isList": false,
|
||||
"output_column": "path",
|
||||
"output_value": "path"
|
||||
}
|
||||
],
|
||||
"bodyKeys": [
|
||||
"id"
|
||||
],
|
||||
"formatEN": "delete avorite [path]",
|
||||
"formatZH": "删除收藏 [path]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/favorite/search": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取收藏列表",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "List favorites",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.PageInfo"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/mode": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -5491,6 +5617,110 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/recycle/clear": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "清空回收站文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "Clear RecycleBin files",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "清空回收站",
|
||||
"formatZH": "清空回收站",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/recycle/reduce": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "还原回收站文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "Reduce RecycleBin files",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.RecycleBinReduce"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [
|
||||
"name"
|
||||
],
|
||||
"formatEN": "Reduce RecycleBin file [name]",
|
||||
"formatZH": "还原回收站文件 [name]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/recycle/search": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取回收站文件列表",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "List RecycleBin files",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.PageInfo"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/rename": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -7819,94 +8049,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/recycle/clear": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "清空回收站文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"RecycleBin"
|
||||
],
|
||||
"summary": "Clear RecycleBin files",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/recycle/reduce": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "还原回收站文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"RecycleBin"
|
||||
],
|
||||
"summary": "Reduce RecycleBin files",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.RecycleBinReduce"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/recycle/search": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取回收站文件列表",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"RecycleBin"
|
||||
],
|
||||
"summary": "List RecycleBin files",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.PageInfo"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/runtimes": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -15556,6 +15698,9 @@
|
||||
"extension": {
|
||||
"type": "string"
|
||||
},
|
||||
"favoriteID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"gid": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -16205,6 +16350,28 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.FavoriteCreate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.FavoriteDelete": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.FileBatchDelete": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -16931,6 +17098,9 @@
|
||||
"from": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"rName": {
|
||||
"type": "string"
|
||||
}
|
||||
@ -18055,6 +18225,9 @@
|
||||
"extension": {
|
||||
"type": "string"
|
||||
},
|
||||
"favoriteID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"gid": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -2280,6 +2280,8 @@ definitions:
|
||||
type: string
|
||||
extension:
|
||||
type: string
|
||||
favoriteID:
|
||||
type: integer
|
||||
gid:
|
||||
type: string
|
||||
group:
|
||||
@ -2710,6 +2712,20 @@ definitions:
|
||||
required:
|
||||
- path
|
||||
type: object
|
||||
request.FavoriteCreate:
|
||||
properties:
|
||||
path:
|
||||
type: string
|
||||
required:
|
||||
- path
|
||||
type: object
|
||||
request.FavoriteDelete:
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
request.FileBatchDelete:
|
||||
properties:
|
||||
isDir:
|
||||
@ -3196,6 +3212,8 @@ definitions:
|
||||
properties:
|
||||
from:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
rName:
|
||||
type: string
|
||||
required:
|
||||
@ -3955,6 +3973,8 @@ definitions:
|
||||
type: string
|
||||
extension:
|
||||
type: string
|
||||
favoriteID:
|
||||
type: integer
|
||||
gid:
|
||||
type: string
|
||||
group:
|
||||
@ -7604,6 +7624,86 @@ paths:
|
||||
formatEN: Download file [name]
|
||||
formatZH: 下载文件 [name]
|
||||
paramKeys: []
|
||||
/files/favorite:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 创建收藏
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.FavoriteCreate'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Create favorite
|
||||
tags:
|
||||
- File
|
||||
x-panel-log:
|
||||
BeforeFunctions: []
|
||||
bodyKeys:
|
||||
- path
|
||||
formatEN: 收藏文件/文件夹 [path]
|
||||
formatZH: 收藏文件/文件夹 [path]
|
||||
paramKeys: []
|
||||
/files/favorite/del:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 删除收藏
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.FavoriteDelete'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Delete favorite
|
||||
tags:
|
||||
- File
|
||||
x-panel-log:
|
||||
BeforeFunctions:
|
||||
- db: favorites
|
||||
input_column: id
|
||||
input_value: id
|
||||
isList: false
|
||||
output_column: path
|
||||
output_value: path
|
||||
bodyKeys:
|
||||
- id
|
||||
formatEN: delete avorite [path]
|
||||
formatZH: 删除收藏 [path]
|
||||
paramKeys: []
|
||||
/files/favorite/search:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取收藏列表
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/dto.PageInfo'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: List favorites
|
||||
tags:
|
||||
- File
|
||||
/files/mode:
|
||||
post:
|
||||
consumes:
|
||||
@ -7689,6 +7789,72 @@ paths:
|
||||
formatEN: Change owner [paths] => [user]/[group]
|
||||
formatZH: 修改用户/组 [paths] => [user]/[group]
|
||||
paramKeys: []
|
||||
/files/recycle/clear:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 清空回收站文件
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Clear RecycleBin files
|
||||
tags:
|
||||
- File
|
||||
x-panel-log:
|
||||
BeforeFunctions: []
|
||||
bodyKeys: []
|
||||
formatEN: 清空回收站
|
||||
formatZH: 清空回收站
|
||||
paramKeys: []
|
||||
/files/recycle/reduce:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 还原回收站文件
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.RecycleBinReduce'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Reduce RecycleBin files
|
||||
tags:
|
||||
- File
|
||||
x-panel-log:
|
||||
BeforeFunctions: []
|
||||
bodyKeys:
|
||||
- name
|
||||
formatEN: Reduce RecycleBin file [name]
|
||||
formatZH: 还原回收站文件 [name]
|
||||
paramKeys: []
|
||||
/files/recycle/search:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取回收站文件列表
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/dto.PageInfo'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: List RecycleBin files
|
||||
tags:
|
||||
- File
|
||||
/files/rename:
|
||||
post:
|
||||
consumes:
|
||||
@ -9159,59 +9325,6 @@ paths:
|
||||
formatEN: 结束进程 [PID]
|
||||
formatZH: 结束进程 [PID]
|
||||
paramKeys: []
|
||||
/recycle/clear:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 清空回收站文件
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Clear RecycleBin files
|
||||
tags:
|
||||
- RecycleBin
|
||||
/recycle/reduce:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 还原回收站文件
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.RecycleBinReduce'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Reduce RecycleBin files
|
||||
tags:
|
||||
- RecycleBin
|
||||
/recycle/search:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取回收站文件列表
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/dto.PageInfo'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: List RecycleBin files
|
||||
tags:
|
||||
- RecycleBin
|
||||
/runtimes:
|
||||
post:
|
||||
consumes:
|
||||
|
@ -21,6 +21,7 @@ export namespace File {
|
||||
items: File[];
|
||||
extension: string;
|
||||
itemTotal: number;
|
||||
favoriteID: number;
|
||||
}
|
||||
|
||||
export interface ReqFile extends ReqPage {
|
||||
@ -162,4 +163,10 @@ export namespace File {
|
||||
from: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface Favorite extends CommonModel {
|
||||
path: string;
|
||||
isDir: boolean;
|
||||
isTxt: boolean;
|
||||
}
|
||||
}
|
||||
|
@ -100,3 +100,15 @@ export const reduceFile = (params: File.RecycleBinReduce) => {
|
||||
export const clearRecycle = () => {
|
||||
return http.post<any>('files/recycle/clear');
|
||||
};
|
||||
|
||||
export const SearchFavorite = (params: ReqPage) => {
|
||||
return http.post<ResPage<File.Favorite>>('files/favorite/search', params);
|
||||
};
|
||||
|
||||
export const AddFavorite = (path: string) => {
|
||||
return http.post<any>('files/favorite', { path: path });
|
||||
};
|
||||
|
||||
export const RemoveFavorite = (id: number) => {
|
||||
return http.post<any>('files/favorite/del', { id: id });
|
||||
};
|
||||
|
@ -122,6 +122,7 @@ const message = {
|
||||
'You can upload only files whose name contains 1 to 256 characters, including English, Chinese, digits, or periods (.-_)',
|
||||
confirmNoNull: 'Make sure the value {0} is not empty',
|
||||
errPort: 'Incorrect port information, please confirm!',
|
||||
remove: 'Remove',
|
||||
},
|
||||
login: {
|
||||
username: 'UserName',
|
||||
@ -970,7 +971,10 @@ const message = {
|
||||
reduceHelper:
|
||||
'Restore the file to its original path. If a file or directory with the same name exists at the original address of the file, it will be overwritten. Do you want to continue?',
|
||||
clearRecycleBin: 'Clear the recycle bin',
|
||||
clearRecycleBinHelper: 'Do you want to clear the recycle bin? ',
|
||||
clearRecycleBinHelper: 'Do you want to clear the recycle bin?',
|
||||
favorite: 'favorites',
|
||||
removeFavorite: 'Remove from favorites?',
|
||||
addFavorite: 'Add to favorites',
|
||||
},
|
||||
ssh: {
|
||||
autoStart: 'Auto Start',
|
||||
|
@ -123,6 +123,7 @@ const message = {
|
||||
fileNameErr: '僅支持上傳名稱包含英文、中文、數字或者 .-_ ,長度 1-256 位的文件',
|
||||
confirmNoNull: '請確認 {0} 值不為空',
|
||||
errPort: '錯誤的端口信息,請確認!',
|
||||
remove: '移出',
|
||||
},
|
||||
login: {
|
||||
username: '用戶名',
|
||||
@ -931,7 +932,10 @@ const message = {
|
||||
reduce: '還原',
|
||||
reduceHelper: '恢復檔案到原路徑,如果檔案原始位址,存在同名檔案或目錄,將會覆蓋,是否繼續? ',
|
||||
clearRecycleBin: '清空回收站',
|
||||
clearRecycleBinHelper: '是否清空回收站? ',
|
||||
clearRecycleBinHelper: '是否清空回收站?',
|
||||
favorite: '收藏夾',
|
||||
removeFavorite: '是否從收藏夾移出?',
|
||||
addFavorite: '加入收藏夾',
|
||||
},
|
||||
ssh: {
|
||||
autoStart: '開機自啟',
|
||||
|
@ -123,6 +123,7 @@ const message = {
|
||||
fileNameErr: '仅支持上传名称包含英文、中文、数字或者 .-_ ,长度 1-256 位的文件',
|
||||
confirmNoNull: '请确认 {0} 值不为空',
|
||||
errPort: '错误的端口信息,请确认!',
|
||||
remove: '移出',
|
||||
},
|
||||
login: {
|
||||
username: '用户名',
|
||||
@ -933,6 +934,9 @@ const message = {
|
||||
reduceHelper: '恢复文件到原路径,如果文件原地址,存在同名文件或目录,将会覆盖,是否继续?',
|
||||
clearRecycleBin: '清空回收站',
|
||||
clearRecycleBinHelper: '是否清空回收站?',
|
||||
favorite: '收藏夹',
|
||||
removeFavorite: '是否从收藏夹移出?',
|
||||
addFavorite: '加入收藏夹子',
|
||||
},
|
||||
ssh: {
|
||||
autoStart: '开机自启',
|
||||
|
72
frontend/src/views/host/file-management/favorite/index.vue
Normal file
72
frontend/src/views/host/file-management/favorite/index.vue
Normal file
@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<el-drawer v-model="open" :before-close="handleClose" :close-on-click-modal="false" size="50%">
|
||||
<template #header>
|
||||
<DrawerHeader :header="$t('file.favorite')" :back="handleClose" />
|
||||
</template>
|
||||
<ComplexTable :pagination-config="paginationConfig" :data="data" @search="search">
|
||||
<el-table-column :label="$t('file.path')" show-overflow-tooltip prop="path"></el-table-column>
|
||||
<fu-table-operations :buttons="buttons" :label="$t('commons.table.operate')" fix />
|
||||
</ComplexTable>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { SearchFavorite, RemoveFavorite } from '@/api/modules/files';
|
||||
import i18n from '@/lang';
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
const paginationConfig = reactive({
|
||||
cacheSizeKey: 'favorite-page-size',
|
||||
currentPage: 1,
|
||||
pageSize: 100,
|
||||
total: 0,
|
||||
});
|
||||
const req = reactive({
|
||||
page: 1,
|
||||
pageSize: 100,
|
||||
});
|
||||
const open = ref(false);
|
||||
const data = ref([]);
|
||||
const em = defineEmits(['close']);
|
||||
|
||||
const handleClose = () => {
|
||||
open.value = false;
|
||||
em('close', false);
|
||||
};
|
||||
|
||||
const acceptParams = () => {
|
||||
search();
|
||||
};
|
||||
|
||||
const search = async () => {
|
||||
try {
|
||||
const res = await SearchFavorite(req);
|
||||
data.value = res.data.items;
|
||||
paginationConfig.total = res.data.total;
|
||||
open.value = true;
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const singleDel = async (id: number) => {
|
||||
ElMessageBox.confirm(i18n.global.t('file.removeFavorite'), i18n.global.t('commons.msg.remove'), {
|
||||
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
||||
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
||||
}).then(async () => {
|
||||
try {
|
||||
await RemoveFavorite(id);
|
||||
search();
|
||||
} catch (error) {}
|
||||
});
|
||||
};
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
label: i18n.global.t('commons.button.delete'),
|
||||
click: (row: any) => {
|
||||
singleDel(row.id);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
defineExpose({ acceptParams });
|
||||
</script>
|
@ -98,6 +98,9 @@
|
||||
</div>
|
||||
|
||||
<div class="right-section">
|
||||
<el-button @click="openFavorite" :icon="Star">
|
||||
{{ $t('file.favorite') }}
|
||||
</el-button>
|
||||
<el-button class="btn" @click="openRecycleBin" :icon="Delete">
|
||||
{{ $t('file.recycleBin') }}
|
||||
</el-button>
|
||||
@ -140,11 +143,42 @@
|
||||
sortable
|
||||
prop="name"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<svg-icon v-if="row.isDir" className="table-icon" iconName="p-file-folder"></svg-icon>
|
||||
<svg-icon v-else className="table-icon" :iconName="getIconName(row.extension)"></svg-icon>
|
||||
<span class="table-link" @click="open(row)" type="primary">{{ row.name }}</span>
|
||||
<span v-if="row.isSymlink">-> {{ row.linkPath }}</span>
|
||||
<template #default="{ row, $index }">
|
||||
<div @mouseenter="showFavorite($index)" @mouseleave="hideFavorite">
|
||||
<el-row>
|
||||
<el-col :span="23">
|
||||
<svg-icon
|
||||
v-if="row.isDir"
|
||||
className="table-icon"
|
||||
iconName="p-file-folder"
|
||||
></svg-icon>
|
||||
<svg-icon
|
||||
v-else
|
||||
className="table-icon"
|
||||
:iconName="getIconName(row.extension)"
|
||||
></svg-icon>
|
||||
<span class="table-link" @click="open(row)" type="primary">{{ row.name }}</span>
|
||||
<span v-if="row.isSymlink">-> {{ row.linkPath }}</span>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<el-button
|
||||
v-if="row.favoriteID > 0"
|
||||
link
|
||||
type="warning"
|
||||
:icon="Star"
|
||||
@click="removeFavorite(row.favoriteID)"
|
||||
></el-button>
|
||||
<div v-else>
|
||||
<el-button
|
||||
v-if="hoveredRowIndex === $index"
|
||||
link
|
||||
:icon="Star"
|
||||
@click="addFavorite(row)"
|
||||
></el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('file.mode')" prop="mode" max-width="50">
|
||||
@ -213,16 +247,25 @@
|
||||
<Detail ref="detailRef" />
|
||||
<DeleteFile ref="deleteRef" @close="search" />
|
||||
<RecycleBin ref="recycleBinRef" @close="search" />
|
||||
<Favorite ref="favoriteRef" @close="search" />
|
||||
</LayoutContent>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onMounted, reactive, ref, computed } from '@vue/runtime-core';
|
||||
import { GetFilesList, GetFileContent, ComputeDirSize } from '@/api/modules/files';
|
||||
import { GetFilesList, GetFileContent, ComputeDirSize, AddFavorite, RemoveFavorite } from '@/api/modules/files';
|
||||
import { computeSize, dateFormat, downloadFile, getIcon, getRandomStr } from '@/utils/util';
|
||||
import { Delete } from '@element-plus/icons-vue';
|
||||
import { Delete, Star } from '@element-plus/icons-vue';
|
||||
import { File } from '@/api/interface/file';
|
||||
import { Mimetypes, Languages } from '@/global/mimetype';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Back, Refresh } from '@element-plus/icons-vue';
|
||||
import { MsgSuccess, MsgWarning } from '@/utils/message';
|
||||
import { useSearchable } from './hooks/searchable';
|
||||
import { ResultData } from '@/api/interface';
|
||||
import { GlobalStore } from '@/store';
|
||||
|
||||
import i18n from '@/lang';
|
||||
import CreateFile from './create/index.vue';
|
||||
import ChangeRole from './change-role/index.vue';
|
||||
@ -236,16 +279,11 @@ import Move from './move/index.vue';
|
||||
import Download from './download/index.vue';
|
||||
import Owner from './chown/index.vue';
|
||||
import DeleteFile from './delete/index.vue';
|
||||
import { Mimetypes, Languages } from '@/global/mimetype';
|
||||
import Process from './process/index.vue';
|
||||
import Detail from './detail/index.vue';
|
||||
import RecycleBin from './recycle-bin/index.vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Back, Refresh } from '@element-plus/icons-vue';
|
||||
import { MsgSuccess, MsgWarning } from '@/utils/message';
|
||||
import { useSearchable } from './hooks/searchable';
|
||||
import { ResultData } from '@/api/interface';
|
||||
import { GlobalStore } from '@/store';
|
||||
import Favorite from './favorite/index.vue';
|
||||
|
||||
const globalStore = GlobalStore();
|
||||
|
||||
interface FilePaths {
|
||||
@ -303,6 +341,8 @@ const chownRef = ref();
|
||||
const moveOpen = ref(false);
|
||||
const deleteRef = ref();
|
||||
const recycleBinRef = ref();
|
||||
const favoriteRef = ref();
|
||||
const hoveredRowIndex = ref(-1);
|
||||
|
||||
// editablePath
|
||||
const { searchableStatus, searchablePath, searchableInputRef, searchableInputBlur } = useSearchable(paths);
|
||||
@ -627,6 +667,10 @@ const openRecycleBin = () => {
|
||||
recycleBinRef.value.acceptParams();
|
||||
};
|
||||
|
||||
const openFavorite = () => {
|
||||
favoriteRef.value.acceptParams();
|
||||
};
|
||||
|
||||
const changeSort = ({ prop, order }) => {
|
||||
req.sortBy = prop;
|
||||
req.sortOrder = order;
|
||||
@ -637,6 +681,33 @@ const changeSort = ({ prop, order }) => {
|
||||
search();
|
||||
};
|
||||
|
||||
const showFavorite = (index: any) => {
|
||||
hoveredRowIndex.value = index;
|
||||
};
|
||||
|
||||
const hideFavorite = () => {
|
||||
hoveredRowIndex.value = -1;
|
||||
};
|
||||
|
||||
const addFavorite = async (row: File.File) => {
|
||||
try {
|
||||
await AddFavorite(row.path);
|
||||
search();
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const removeFavorite = async (id: number) => {
|
||||
ElMessageBox.confirm(i18n.global.t('file.removeFavorite'), i18n.global.t('commons.msg.remove'), {
|
||||
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
||||
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
||||
}).then(async () => {
|
||||
try {
|
||||
await RemoveFavorite(id);
|
||||
search();
|
||||
} catch (error) {}
|
||||
});
|
||||
};
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
label: i18n.global.t('file.open'),
|
||||
@ -759,7 +830,9 @@ onMounted(() => {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.right-section > *:not(:last-child) {
|
||||
margin-right: 10px;
|
||||
.right-section {
|
||||
.btn {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
Loading…
Reference in New Issue
Block a user