This commit is contained in:
2025-07-07 20:11:59 +08:00
parent ab0fdbc447
commit 06e3aa2eb3
2009 changed files with 193082 additions and 0 deletions

View File

@ -0,0 +1,573 @@
// ==========================================================================
// GFast自动生成logic操作代码。
// 生成日期2023-09-16 10:32:04
// 生成路径: internal/app/system/logic/document.go
// 生成人gfast
// desc:母板
// company:云南奇讯科技有限公司
// ==========================================================================
package logic
import (
"context"
"errors"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/tiger1103/gfast/v3/api/v1/common/coryCommon"
"github.com/tiger1103/gfast/v3/api/v1/system"
"github.com/tiger1103/gfast/v3/internal/app/system/consts"
"github.com/tiger1103/gfast/v3/internal/app/system/dao"
"github.com/tiger1103/gfast/v3/internal/app/system/model"
"github.com/tiger1103/gfast/v3/internal/app/system/model/do"
"github.com/tiger1103/gfast/v3/internal/app/system/service"
"github.com/tiger1103/gfast/v3/library/liberr"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
)
func init() {
service.RegisterDocument(New())
}
func New() *sDocument {
return &sDocument{}
}
type sDocument struct{}
func (s *sDocument) TemplateRecycleBinFunc(ctx context.Context, req *system.TemplateRecycleBinReq) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
if req.Type == "1" {
_, err = dao.Document.Ctx(ctx).Unscoped().Where(dao.DocumentData.Columns().Id+" in (?)", req.Ids).Update(g.Map{"deleted_at": nil})
} else {
var pathArr []string
//删除还需要删除下面的所有子数据
var idArr []int64
for i := range req.Ids {
idList := RecursiveDeletion(ctx, req.Ids[i])
if idList != nil {
idArr = append(idArr, idList...)
}
data, _ := dao.Document.Ctx(ctx).Unscoped().Where("id", req.Ids[i]).Fields("filen_path").Value()
pathArr = append(pathArr, data.String())
}
idArr = append(idArr, req.Ids...)
_, err = dao.Document.Ctx(ctx).Unscoped().Delete(dao.Document.Columns().Id+" in (?)", idArr)
//如果删除成功,那么删除文件/文件夹
for _, data := range pathArr {
os.RemoveAll(coryCommon.FileToFunc(data, 2))
}
}
liberr.ErrIsNil(ctx, err, "删除失败")
})
return
}
func RecursiveDeletion(ctx context.Context, id int64) (ids []int64) {
//1、获取某个文件的字符串id_str
value, _ := dao.Document.Ctx(ctx).Unscoped().Where("id", id).Fields("id_str").Value()
if value.String() == "" {
return nil
}
//2、查看当前需要删除的数据下面是否有子数据
var dlr []*model.DocumentListRes
dao.Document.Ctx(ctx).Unscoped().Where("pid", value.String()).Fields("id,id_str").Scan(&dlr)
for i := range dlr {
ids = append(ids, dlr[i].Id)
deletion := RecursiveDeletion(ctx, dlr[i].Id)
ids = append(ids, deletion...)
}
return ids
}
func (s *sDocument) AllList(ctx context.Context, req *system.AllDocumentSearchReq) (res *system.AllDocumentSearchRes, err error) {
err = g.Try(ctx, func(ctx context.Context) {
res = new(system.AllDocumentSearchRes)
var dataList []*model.DocumentInfoRes
m := dao.Document.Ctx(ctx)
if req.Type == "2" {
m = m.Unscoped().WhereNotNull("deleted_at")
} else if req.Type == "3" {
m = m.Unscoped()
}
err = m.Scan(&dataList)
res.List = dataList
liberr.ErrIsNil(ctx, err, "获取数据失败!")
})
return
}
func RecursiveQueryFunc(dr []*model.DocumentInfoRes, idStr string) (idStrs []string) {
for _, data := range dr {
if data.Pid == idStr {
idStrs = append(idStrs, data.IdStr)
strs := RecursiveQueryFunc(dr, data.IdStr)
if len(strs) > 0 {
idStrs = append(idStrs, strs...)
}
}
}
return
}
func (s *sDocument) TreeStructureFunc(ctx context.Context, req *system.TreeStructureReq) (res *system.TreeStructureRes, err error) {
err = g.Try(ctx, func(ctx context.Context) {
res = new(system.TreeStructureRes)
var entity []*model.TreeStructureRes
err = dao.Document.Ctx(ctx).Where("pid = '0'").WithAll().Scan(&entity)
res.List = entity
liberr.ErrIsNil(ctx, err, "获取数据失败!")
})
return
}
func (s *sDocument) List(ctx context.Context, req *system.DocumentSearchReq) (listRes *system.DocumentSearchRes, err error) {
listRes = new(system.DocumentSearchRes)
err = g.Try(ctx, func(ctx context.Context) {
m := dao.Document.Ctx(ctx).Where(dao.Document.Columns().Type, "1")
//如果查询全部那么就先递归获取到所有的pid然后去查询,否则就只查询前端传递过来的数据
if req.Switch == "1" {
var dr []*model.DocumentInfoRes
err = dao.Document.Ctx(ctx).Where("type = 2").Scan(&dr)
strs := RecursiveQueryFunc(dr, req.IdStr)
strs = append(strs, req.IdStr)
m = m.Where(dao.Document.Columns().Pid+" in (?)", strs)
} else {
m = m.Where(dao.Document.Columns().Pid, req.IdStr)
}
if req.Name != "" {
m = m.Where(dao.Document.Columns().Name+" like ?", "%"+req.Name+"%")
}
if len(req.DateRange) != 0 {
m = m.Where(dao.Document.Columns().CreatedAt+" >=? AND "+dao.Document.Columns().CreatedAt+" <=?", req.DateRange[0], req.DateRange[1])
}
if !strings.EqualFold(req.IsPaging, "YES") {
listRes.Total, err = m.Count()
liberr.ErrIsNil(ctx, err, "获取总行数失败")
if req.PageNum == 0 {
req.PageNum = 1
}
listRes.CurrentPage = req.PageNum
if req.PageSize == 0 {
req.PageSize = consts.PageSize
}
m = m.Fields(system.DocumentSearchRes{}).Page(req.PageNum, req.PageSize)
}
order := "id desc"
if req.OrderBy != "" {
order = req.OrderBy
}
var res []*model.DocumentInfoRes
err = m.Order(order).Scan(&res)
liberr.ErrIsNil(ctx, err, "获取数据失败")
listRes.List = make([]*model.DocumentListRes, len(res))
for k, v := range res {
// 对 URL 进行编码
//split := strings.Split(v.FilenPath, "/")
//s2 := split[len(split)-1]
//encodedPath := url.QueryEscape(s2)
s2 := v.FilenPath[6 : len(v.FilenPath)-1]
encodedPath := url.QueryEscape(s2)
listRes.List[k] = &model.DocumentListRes{
Id: v.Id,
Name: v.Name,
FilenPath: v.FilenPath,
FilenPathCoding: strings.ReplaceAll(v.FilenPath, s2, encodedPath),
Suffix: v.Suffix,
CreatedAt: v.CreatedAt,
}
}
})
return
}
func (s *sDocument) GetById(ctx context.Context, id int) (res *model.DocumentInfoRes, err error) {
err = g.Try(ctx, func(ctx context.Context) {
err = dao.Document.Ctx(ctx).WithAll().Where(dao.Document.Columns().Id, id).Scan(&res)
liberr.ErrIsNil(ctx, err, "获取信息失败")
})
return
}
func (s *sDocument) Add(ctx context.Context, req *system.DocumentAddReq) (err error) {
//大文件上传
req.FilePath.Url = strings.ReplaceAll(req.FilePath.Url, "/resource/public/", "/file/")
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
err = g.Try(ctx, func(ctx context.Context) {
if req.FileType == "1" { //1、压缩文件夹导入
filenPath := ""
if req.Pid != "" {
value, _ := dao.Document.Ctx(ctx).Where("id_str", req.Pid).Fields("filen_path").Value()
filenPath = value.String()
}
newPath := strings.ReplaceAll(req.FilePath.Url, "/file", coryCommon.GetCWD()+"/resource/public")
path, err := coryCommon.FileZipFunc(newPath, filenPath, coryCommon.Template) //解压相对路径,并删除压缩文件,返回解压后的相对路径
if err != nil {
liberr.ErrIsNil(ctx, err)
return
}
one, err := coryCommon.Traversal(ctx, path, req.Pid, dao.Document.Table(), coryCommon.Template, 0, "1") //遍历解压后的文件,插入数据
//err = Traversal(ctx, path, req.Pid) //遍历解压后的文件,插入数据
liberr.ErrIsNil(ctx, err)
_, err = g.DB().Model(dao.Document.Table()).Ctx(ctx).Insert(one)
liberr.ErrIsNil(ctx, err, "新增失败!")
return
} else if req.FileType == "2" { //2、文件导入
wornPath := filepath.ToSlash(strings.ReplaceAll(req.FilePath.Url, "/file/", coryCommon.GetCWD()+"/resource/public/"))
value, _ := dao.Document.Ctx(ctx).Where("id_str", req.Pid).Fields("filen_path").Value()
newPath := strings.Replace(value.String(), "/file/", coryCommon.GetCWD()+"/resource/public/", 1)
//2、文件存在就随机给一个文件名
_, err = os.Stat(newPath + "/" + req.FilePath.Name)
if err == nil {
name := coryCommon.FileName("mb") + "." + strings.Split(req.FilePath.Name, ".")[1]
newPath = newPath + "/" + name
req.FilePath.Name = name
} else {
newPath = newPath + "/" + req.FilePath.Name
}
//3、文件移动
err = os.Rename(wornPath, newPath)
//4、数据库记录文件
_, err = dao.Document.Ctx(ctx).Insert(model.DocumentListRes{
Pid: req.Pid,
Name: strings.Split(req.FilePath.Name, ".")[0],
Suffix: req.FilePath.FileType,
FilenPath: filepath.ToSlash(strings.Replace(newPath, coryCommon.GetCWD()+"/resource/public/", "/file/", 1)),
Type: "1",
})
liberr.ErrIsNil(ctx, err, "新增失败!")
return
}
})
return err
})
return
}
func (s *sDocument) NewFolderFunc(ctx context.Context, req *system.NewFolderReq) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
//1、组装数据
resEntity := model.DocumentListRes{
Name: req.FileName,
Suffix: "",
Type: "2",
}
path := ""
if req.Pid != "" {
value, _ := dao.Document.Ctx(ctx).Where("id_str", req.Pid).Fields("filen_path").Value()
path = value.String() + "/" + req.FileName
resEntity.Pid = req.Pid
} else {
template := strings.Replace(coryCommon.Template, "/resource/public/", "/file/", 1)
path = template + "/" + req.FileName
resEntity.Pid = "0"
}
//2、判断是否重名不重复就新增
count, _ := dao.Document.Ctx(ctx).Unscoped().Where("filen_path", path).Count()
if count > 0 {
err = errors.New("文件夹已重复!")
liberr.ErrIsNil(ctx, err)
return
} else {
resEntity.IdStr = coryCommon.SHA256(path)
resEntity.FilenPath = path
_, insertDataErr := dao.Document.Ctx(ctx).Insert(resEntity)
if insertDataErr != nil {
err = errors.New("新增文件夹失败!")
liberr.ErrIsNil(ctx, err)
return
}
err = coryCommon.CreateDirectory(strings.Replace(path, "/file/", coryCommon.GetCWD()+"/resource/public/", 1))
if err != nil {
err = errors.New("新增文件夹失败!")
liberr.ErrIsNil(ctx, err)
return
}
}
liberr.ErrIsNil(ctx, err, "新增文件夹失败!")
})
return
}
//// Traversal 遍历文件夹
//func Traversal(ctx context.Context, root string, pidstr string) (err error) {
//
// var dataOne []*model.DocumentListRes
//
// template := strings.Replace(coryCommon.Template, "/resource/public", "/file", 1)
// err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
// if err != nil {
// return err
// }
// // 获取相对路径
// relativePath, err := filepath.Rel(root, path)
// if err != nil {
// return err
// }
// // 根目录下创建,还是指定文件夹下面创建?
// p := ""
// if pidstr != "" {
// value, _ := dao.Document.Ctx(ctx).Where("id_str", pidstr).Fields("filen_path").Value()
// split := strings.Split(root, "/")
// p = value.String() + "/" + split[len(split)-1] + "/" + relativePath
// } else {
// p = template + "/" + relativePath
// }
// p = strings.ReplaceAll(p, "\\", "/")
// // 获取当前项的深度
// depth := strings.Count(relativePath, string(filepath.Separator))
// // 判断父子关系并打印结果
// if depth == 0 && info.IsDir() {
// if relativePath == "." {
// split := strings.Split(root, "/")
// n := split[len(split)-1]
// // 根目录下创建,还是指定文件夹下面创建?
// p := ""
// if pidstr != "" {
// value, _ := dao.Document.Ctx(ctx).Where("id_str", pidstr).Fields("filen_path").Value()
// p = value.String() + "/" + n
// } else {
// p = template + "/" + n
// }
// p = strings.ReplaceAll(p, "\\", "/")
// template = template + "/" + n
// var dataTwo = new(model.DocumentListRes)
// dataTwo.IdStr = SHA256(p)
// if pidstr != "" {
// dataTwo.Pid = pidstr
// } else {
// dataTwo.Pid = "0"
// }
// dataTwo.Name = n
// dataTwo.FilenPath = p
// ////如果文件夹路径重复,就提示 解压文件夹的时候就已经判断了,这里就不需要了
// //err := IsFolderExist(ctx, p)
// //if err != nil {
// // return err
// //}
// dataTwo.Type = "2"
// dataOne = append(dataOne, dataTwo)
// } else {
// dir, n := filepath.Split(p)
// dir = strings.TrimSuffix(dir, "/")
// var dataTwo = new(model.DocumentListRes)
// dataTwo.IdStr = SHA256(p)
// dataTwo.Pid = SHA256(dir)
// dataTwo.Name = n
// dataTwo.FilenPath = p
// ////如果文件夹路径重复,就提示
// //err := IsFolderExist(ctx, p)
// //if err != nil {
// // return err
// //}
// dataTwo.Type = "2"
// dataOne = append(dataOne, dataTwo)
// }
// } else if info.IsDir() {
// // 子文件夹
// dir, n := filepath.Split(p)
// dir = strings.TrimSuffix(dir, "/")
// var dataTwo = new(model.DocumentListRes)
// dataTwo.IdStr = SHA256(p)
// dataTwo.Pid = SHA256(dir)
// dataTwo.Name = n
// dataTwo.FilenPath = p
// dataTwo.Type = "2"
// dataOne = append(dataOne, dataTwo)
// } else {
// dir, n := filepath.Split(p)
// dir = strings.TrimSuffix(dir, "/")
// var dataTwo = new(model.DocumentListRes)
// dataTwo.Pid = SHA256(dir)
// lastDotIndex := strings.LastIndex(n, ".")
// if lastDotIndex == -1 || lastDotIndex == 0 {
// dataTwo.Name = strings.Split(n, ".")[0]
// } else {
// dataTwo.Name = n[:lastDotIndex]
// }
// dataTwo.Suffix = n[lastDotIndex:]
// dataTwo.FilenPath = p
// dataTwo.Type = "1"
// //文件只能是这三种类型,其他类型进不来
// s := n[lastDotIndex:]
// if strings.EqualFold(s, ".xlsx") || strings.EqualFold(s, ".docx") || strings.EqualFold(s, ".doc") || strings.EqualFold(s, ".ppt") {
// dataOne = append(dataOne, dataTwo)
// }
// }
// return err
// })
//
// if err != nil {
// //fmt.Println("遍历文件夹时发生错误:", err)
// return
// }
// dao.Document.Ctx(ctx).Insert(dataOne)
// return err
//}
//
//func IsFolderExist(ctx context.Context, path string) (err error) {
// count, _ := dao.Document.Ctx(ctx).Where("filen_path", path).Count()
// if count > 0 {
// err = errors.New("文件夹已存在!")
// return
// }
// return nil
//}
//
//func SHA256(str string) (hx string) {
// // 创建 SHA-256 哈希对象
// hash := sha256.New()
// // 将字符串转换为字节数组并进行哈希计算
// hash.Write([]byte(str))
// // 计算 SHA-256 哈希值
// hashedBytes := hash.Sum(nil)
// // 将哈希值转换为十六进制字符串
// hashStr := hex.EncodeToString(hashedBytes)
// return hashStr
//}
func (s *sDocument) Edit(ctx context.Context, req *system.DocumentEditReq) (err error) {
if req.Type == "1" {
err = updateFile(ctx, req)
} else if req.Type == "2" {
err = updateFolder(ctx, req)
}
liberr.ErrIsNil(ctx, err)
return
}
func RecursiveQueryEntityFunc(ctx context.Context, entity []*model.TreeStructureResTwo) (idStrs []int64) {
for i := range entity {
idStrs = append(idStrs, entity[i].Id)
if len(entity[i].TreeStructureResTwo) > 0 {
strs := RecursiveQueryEntityFunc(ctx, entity[i].TreeStructureResTwo)
idStrs = append(idStrs, strs...)
}
}
return
}
// 修改文件夹
func updateFolder(ctx context.Context, req *system.DocumentEditReq) (err error) {
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
err = g.Try(ctx, func(ctx context.Context) {
//1、判断修改后的文件夹是否有重复如果有就提示当前文件夹已存在
var dif *model.DocumentInfoRes
dao.Document.Ctx(ctx).WherePri(req.Id).Scan(&dif)
replace := strings.Replace(dif.FilenPath, dif.Name, req.Name, 1)
s2 := coryCommon.FileToFunc(replace, 2)
if _, err = os.Stat(s2); err == nil {
err = errors.New("当前文件夹已存在!")
liberr.ErrIsNil(ctx, err)
return
} else {
count := strings.Count(dif.FilenPath, dif.Name)
hx := coryCommon.SHA256(strings.ReplaceAll(dif.FilenPath, dif.FilenPath, replace))
//2、如果不存在那么就修改文件夹的同时还得修改路径以及及其子文件/文件夹下的所有路径
var entity []*model.TreeStructureResTwo
err = dao.Document.Ctx(ctx).Unscoped().Where("pid", dif.IdStr).WithAll().Scan(&entity)
strs := RecursiveQueryEntityFunc(ctx, entity)
_, err = dao.Document.Ctx(ctx).Unscoped().Where("id in (?)", strs).Update(g.Map{"filen_path": gdb.Raw("CONCAT(" +
"SUBSTRING_INDEX(filen_path, '" + dif.Name + "', " + strconv.Itoa(count) + ")," +
"'" + req.Name + "'," +
"SUBSTRING_INDEX(filen_path, '" + dif.Name + "', -1)" +
")")})
if err != nil {
err = errors.New("修改失败!")
liberr.ErrIsNil(ctx, err)
return
}
//3、重新生成并修改文件夹的id_str等信息
_, err = dao.Document.Ctx(ctx).Where("id", dif.Id).Update(g.Map{
"id_str": hx,
"name": req.Name,
"filen_path": gdb.Raw("CONCAT(" +
"SUBSTRING_INDEX(filen_path, '" + dif.Name + "', " + strconv.Itoa(count) + ")," +
"'" + req.Name + "'," +
"SUBSTRING_INDEX(filen_path, '" + dif.Name + "', -1)" +
")"),
})
_, err = dao.Document.Ctx(ctx).Unscoped().Where("pid", dif.IdStr).Update(g.Map{"pid": hx})
//4、修改文件夹
oldPath := filepath.Join(coryCommon.FileToFunc(dif.FilenPath, 2))
newPath := filepath.Join(filepath.Dir(oldPath), req.Name)
err = os.Rename(oldPath, newPath)
}
liberr.ErrIsNil(ctx, err, "修改失败")
return
})
return err
})
return
}
// 修改文件
func updateFile(ctx context.Context, req *system.DocumentEditReq) (err error) {
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
err = g.Try(ctx, func(ctx context.Context) {
var dif *model.DocumentInfoRes
dao.Document.Ctx(ctx).WherePri(req.Id).Scan(&dif)
//1、判断修改后的名字是否有重复如果有就提示当前文件名已存在
replace := strings.Replace(dif.FilenPath, dif.Name, req.Name, 1)
s2 := coryCommon.FileToFunc(replace, 2)
if _, err = os.Stat(s2); err == nil {
err = errors.New("当前文件名已存在!")
liberr.ErrIsNil(ctx, err)
return
}
//2、如果不存在那么就修改文件名的同时还得修改路径
_, err = dao.Document.Ctx(ctx).WherePri(req.Id).Update(do.Document{
Name: req.Name,
FilenPath: replace,
})
//3、修改具体文件的文件名
if err == nil {
oldPath := coryCommon.FileToFunc(dif.FilenPath, 2)
newPath := filepath.Join(filepath.Dir(oldPath), req.Name+dif.Suffix)
err = os.Rename(oldPath, newPath)
if err != nil {
err = errors.New("修改失败")
liberr.ErrIsNil(ctx, err)
return
}
}
liberr.ErrIsNil(ctx, err, "修改失败")
})
return err
})
return
}
func (s *sDocument) Delete(ctx context.Context, ids []int) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
//1、先判断删除的是文件还是文件夹,然后进行修改需要删除的文件或文件夹名称
var dataList []*model.DocumentInfoRes
err = dao.Document.Ctx(ctx).Where(dao.Document.Columns().Id+" in (?)", ids).Scan(&dataList)
liberr.ErrIsNil(ctx, err, "删除失败")
if len(dataList) > 0 {
for i := range dataList {
t := dataList[i].Type
upEntity := system.DocumentEditReq{
Id: dataList[i].Id,
Name: dataList[i].Name + coryCommon.FileName("delete"),
Type: t,
}
if t == "1" {
err = updateFile(ctx, &upEntity)
liberr.ErrIsNil(ctx, err, "删除失败")
} else {
err = updateFolder(ctx, &upEntity)
liberr.ErrIsNil(ctx, err, "删除失败")
}
}
//1、删除文件夹
_, err = dao.Document.Ctx(ctx).Delete(dao.Document.Columns().Id+" in (?)", ids)
liberr.ErrIsNil(ctx, err, "删除失败")
}
})
return
}