mirror of
https://github.com/fumiama/paper-manager.git
synced 2026-06-24 04:27:09 +08:00
implement delfile
This commit is contained in:
@@ -490,7 +490,7 @@ func (f *FileDatabase) AddFile(lstid int, reg *Regex, istemp bool, progress func
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DelFile by listid
|
// DelFile by listid
|
||||||
func (f *FileDatabase) DelFile(fileid, uid int, istemp bool) error {
|
func (f *FileDatabase) DelFile(lstid, uid int, istemp bool) error {
|
||||||
user, err := UserDB.GetUserByID(uid)
|
user, err := UserDB.GetUserByID(uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -498,19 +498,14 @@ func (f *FileDatabase) DelFile(fileid, uid int, istemp bool) error {
|
|||||||
if !user.IsSuper() {
|
if !user.IsSuper() {
|
||||||
return ErrInvalidRole
|
return ErrInvalidRole
|
||||||
}
|
}
|
||||||
var file File
|
ftable := ""
|
||||||
f.mu.RLock()
|
|
||||||
if istemp {
|
if istemp {
|
||||||
file, err = sql.Find[File](&f.db, FileTableTempFile, "WHERE ID="+strconv.Itoa(fileid))
|
ftable = FileTableTempFile
|
||||||
} else {
|
} else {
|
||||||
file, err = sql.Find[File](&f.db, FileTableFile, "WHERE ID="+strconv.Itoa(fileid))
|
ftable = FileTableFile
|
||||||
}
|
|
||||||
f.mu.RUnlock()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
f.mu.RLock()
|
f.mu.RLock()
|
||||||
lst, err := sql.Find[List](&f.db, FileTableList, "WHERE ID="+strconv.Itoa(file.ListID))
|
lst, err := sql.Find[List](&f.db, FileTableList, "WHERE ID="+strconv.Itoa(lstid))
|
||||||
f.mu.RUnlock()
|
f.mu.RUnlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -518,21 +513,33 @@ func (f *FileDatabase) DelFile(fileid, uid int, istemp bool) error {
|
|||||||
if lst.Path == "" || strings.Contains(lst.Path, "..") {
|
if lst.Path == "" || strings.Contains(lst.Path, "..") {
|
||||||
return os.ErrNotExist
|
return os.ErrNotExist
|
||||||
}
|
}
|
||||||
ques := make([]QuestionJSON, 0, 64)
|
i := strings.LastIndex(lst.Path, "/")
|
||||||
err = json.Unmarshal(file.Questions, &ques)
|
if i <= 0 {
|
||||||
if err != nil {
|
return os.ErrNotExist
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
for _, q := range ques {
|
parentfolder := lst.Path[:i]
|
||||||
q.Delete(f, istemp)
|
if utils.IsNotExist(parentfolder) {
|
||||||
|
return os.ErrNotExist
|
||||||
}
|
}
|
||||||
if istemp {
|
if !lst.HasntAnalyzed {
|
||||||
err = f.db.Del(FileTableTempFile, "WHERE ID="+strconv.Itoa(fileid))
|
f.mu.RLock()
|
||||||
} else {
|
file, err := sql.Find[File](&f.db, ftable, "WHERE ListID="+strconv.Itoa(lstid))
|
||||||
err = f.db.Del(FileTableFile, "WHERE ID="+strconv.Itoa(fileid))
|
f.mu.RUnlock()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = f.db.Del(ftable, "WHERE ListID="+strconv.Itoa(lstid))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ques := make([]QuestionJSON, 0, 64)
|
||||||
|
err = json.Unmarshal(file.Questions, &ques)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, q := range ques {
|
||||||
|
q.Delete(f, istemp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
return os.RemoveAll(parentfolder)
|
||||||
logrus.Warnln("[global.DelFile] err:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
sql "github.com/FloatTech/sqlite"
|
||||||
"github.com/corona10/goimagehash"
|
"github.com/corona10/goimagehash"
|
||||||
|
base14 "github.com/fumiama/go-base16384"
|
||||||
"github.com/fumiama/paper-manager/backend/utils"
|
"github.com/fumiama/paper-manager/backend/utils"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@@ -19,7 +21,7 @@ type QuestionJSON struct {
|
|||||||
Sub []QuestionJSON `json:"sub,omitempty"`
|
Sub []QuestionJSON `json:"sub,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete me and all subs
|
// Delete me and all subs, ignore errors
|
||||||
func (q *QuestionJSON) Delete(f *FileDatabase, istemp bool) {
|
func (q *QuestionJSON) Delete(f *FileDatabase, istemp bool) {
|
||||||
if b, err := hex.DecodeString(q.Name); err == nil {
|
if b, err := hex.DecodeString(q.Name); err == nil {
|
||||||
err = f.DelQuestion(int64(binary.LittleEndian.Uint64(b)), istemp)
|
err = f.DelQuestion(int64(binary.LittleEndian.Uint64(b)), istemp)
|
||||||
@@ -32,14 +34,49 @@ func (q *QuestionJSON) Delete(f *FileDatabase, istemp bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DelQuestion 删除问题, 其它问题的 dup 可能会残留有 id, 使用时需要排除
|
// DelQuestion 删除问题, 与其它问题的 dup
|
||||||
func (f *FileDatabase) DelQuestion(id int64, istemp bool) error {
|
func (f *FileDatabase) DelQuestion(id int64, istemp bool) error {
|
||||||
|
qtable := ""
|
||||||
|
if istemp {
|
||||||
|
qtable = FileTableTempQuestion
|
||||||
|
} else {
|
||||||
|
qtable = FileTableQuestion
|
||||||
|
}
|
||||||
f.mu.Lock()
|
f.mu.Lock()
|
||||||
defer f.mu.Unlock()
|
defer f.mu.Unlock()
|
||||||
if istemp {
|
q, err := sql.Find[Question](&f.db, qtable, "WHERE ID="+strconv.FormatInt(id, 10))
|
||||||
return f.db.Del(FileTableTempQuestion, "WHERE ID="+strconv.FormatInt(id, 10))
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return f.db.Del(FileTableQuestion, "WHERE ID="+strconv.FormatInt(id, 10))
|
if len(q.Dup) > 2 {
|
||||||
|
dupmap := make(map[string]float64, 64)
|
||||||
|
err = json.Unmarshal(q.Dup, &dupmap)
|
||||||
|
if err == nil {
|
||||||
|
var buf [8]byte
|
||||||
|
for k := range dupmap {
|
||||||
|
_, err = hex.Decode(buf[:], base14.StringToBytes(k))
|
||||||
|
if err == nil {
|
||||||
|
qid := int64(binary.LittleEndian.Uint64(buf[:]))
|
||||||
|
qq, err := sql.Find[Question](&f.db, qtable, "WHERE ID="+strconv.FormatInt(qid, 10))
|
||||||
|
if err == nil && len(qq.Dup) > 2 {
|
||||||
|
dupmap2 := make(map[string]float64, 64)
|
||||||
|
err = json.Unmarshal(qq.Dup, &dupmap2)
|
||||||
|
if err == nil {
|
||||||
|
delete(dupmap2, k)
|
||||||
|
qq.Dup, err = json.Marshal(dupmap2)
|
||||||
|
if err == nil {
|
||||||
|
err = f.db.Insert(qtable, &qq)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Warnln("[global.DelQuestion] insert modified dup to id", k, "table", qtable, "err:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return f.db.Del(qtable, "WHERE ID="+strconv.FormatInt(id, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
type Question struct {
|
type Question struct {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ var analyzeper = ttl.NewCache[int, uint](time.Hour)
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
errNoAnalyzePermission = errors.New("no analyze permission")
|
errNoAnalyzePermission = errors.New("no analyze permission")
|
||||||
|
errNoDeletePermission = errors.New("no delete permission")
|
||||||
)
|
)
|
||||||
|
|
||||||
type filelist struct {
|
type filelist struct {
|
||||||
@@ -200,6 +201,34 @@ func init() {
|
|||||||
writeresult(w, codeSuccess, &message{C: 0, M: "分析完成"}, messageOk, typeSuccess)
|
writeresult(w, codeSuccess, &message{C: 0, M: "分析完成"}, messageOk, typeSuccess)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
apimap["/api/delFile"] = &apihandler{"GET", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
token := r.Header.Get("Authorization")
|
||||||
|
user := usertokens.Get(token)
|
||||||
|
if user == nil {
|
||||||
|
writeresult(w, codeError, nil, errInvalidToken.Error(), typeError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !user.IsSuper() {
|
||||||
|
writeresult(w, codeError, nil, errNoDeletePermission.Error(), typeError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
idstr := r.URL.Query().Get("id")
|
||||||
|
if idstr == "" {
|
||||||
|
writeresult(w, codeError, nil, "empty id", typeError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id, err := strconv.Atoi(idstr)
|
||||||
|
if err != nil {
|
||||||
|
writeresult(w, codeError, nil, err.Error(), typeError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = global.FileDB.DelFile(id, *user.ID, false)
|
||||||
|
if err != nil {
|
||||||
|
writeresult(w, codeError, nil, err.Error(), typeError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeresult(w, codeSuccess, "删除成功", messageOk, typeSuccess)
|
||||||
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PaperHandler serves protected contents in global.FileFolder
|
// PaperHandler serves protected contents in global.FileFolder
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export default [
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
},*/
|
},*/
|
||||||
{
|
/*{
|
||||||
url: '/api/delFile',
|
url: '/api/delFile',
|
||||||
timeout: 200,
|
timeout: 200,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
@@ -84,7 +84,7 @@ export default [
|
|||||||
msg: '已成功删除文件' + id + '.',
|
msg: '已成功删除文件' + id + '.',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},*/
|
||||||
/*{
|
/*{
|
||||||
url: '/api/analyzeFile',
|
url: '/api/analyzeFile',
|
||||||
timeout: 1000,
|
timeout: 1000,
|
||||||
|
|||||||
@@ -29,7 +29,6 @@
|
|||||||
"test:gzip": "npx http-server dist --cors --gzip -c-1",
|
"test:gzip": "npx http-server dist --cors --gzip -c-1",
|
||||||
"test:br": "npx http-server dist --cors --brotli -c-1",
|
"test:br": "npx http-server dist --cors --brotli -c-1",
|
||||||
"reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && pnpm run bootstrap",
|
"reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && pnpm run bootstrap",
|
||||||
"prepare": "husky install",
|
|
||||||
"gen:icon": "esno ./build/generate/icon/index.ts"
|
"gen:icon": "esno ./build/generate/icon/index.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -108,7 +107,6 @@
|
|||||||
"eslint-plugin-vue": "^8.6.0",
|
"eslint-plugin-vue": "^8.6.0",
|
||||||
"esno": "^0.14.1",
|
"esno": "^0.14.1",
|
||||||
"fs-extra": "^10.1.0",
|
"fs-extra": "^10.1.0",
|
||||||
"husky": "^7.0.4",
|
|
||||||
"inquirer": "^8.2.2",
|
"inquirer": "^8.2.2",
|
||||||
"less": "^4.1.2",
|
"less": "^4.1.2",
|
||||||
"lint-staged": "12.3.7",
|
"lint-staged": "12.3.7",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { defHttp } from '/@/utils/http/axios'
|
import { defHttp } from '/@/utils/http/axios'
|
||||||
import { getFileListModel, DelFile, AnalyzeFile, FileListGroupItem } from './model/fileListModel'
|
import { getFileListModel, AnalyzeFile, FileListGroupItem } from './model/fileListModel'
|
||||||
import { DownloadFile, FileStatus } from './model/fileModel'
|
import { DownloadFile, FileStatus } from './model/fileModel'
|
||||||
|
|
||||||
enum Api {
|
enum Api {
|
||||||
@@ -37,7 +37,7 @@ export const getFilePercent = (id: number) => {
|
|||||||
* @description: Get file percent
|
* @description: Get file percent
|
||||||
*/
|
*/
|
||||||
export const delFile = (id: number) => {
|
export const delFile = (id: number) => {
|
||||||
return defHttp.get<DelFile>({ url: Api.DelFile, params: { id: id } })
|
return defHttp.get<string>({ url: Api.DelFile, params: { id: id } })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -14,10 +14,6 @@ export interface FileListGroupItem {
|
|||||||
*/
|
*/
|
||||||
export type getFileListModel = FileListGroupItem[]
|
export type getFileListModel = FileListGroupItem[]
|
||||||
|
|
||||||
export interface DelFile {
|
|
||||||
msg: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AnalyzeFile {
|
export interface AnalyzeFile {
|
||||||
code: number
|
code: number
|
||||||
msg: string
|
msg: string
|
||||||
|
|||||||
@@ -130,7 +130,7 @@
|
|||||||
item.delloading = true
|
item.delloading = true
|
||||||
const msg = await delFile(item.id)
|
const msg = await delFile(item.id)
|
||||||
if (msg) {
|
if (msg) {
|
||||||
createMessage.success(msg.msg)
|
createMessage.success(msg)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
deleteFileByID(item.id)
|
deleteFileByID(item.id)
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|||||||
@@ -5174,11 +5174,6 @@
|
|||||||
"resolved" "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz"
|
"resolved" "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz"
|
||||||
"version" "2.1.0"
|
"version" "2.1.0"
|
||||||
|
|
||||||
"husky@^7.0.4":
|
|
||||||
"integrity" "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ=="
|
|
||||||
"resolved" "https://registry.npmmirror.com/husky/-/husky-7.0.4.tgz"
|
|
||||||
"version" "7.0.4"
|
|
||||||
|
|
||||||
"iconv-lite@^0.4.24":
|
"iconv-lite@^0.4.24":
|
||||||
"integrity" "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="
|
"integrity" "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="
|
||||||
"resolved" "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz"
|
"resolved" "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz"
|
||||||
|
|||||||
Reference in New Issue
Block a user