mirror of
https://github.com/fumiama/paper-manager.git
synced 2026-06-24 04:27:09 +08:00
add /api/getUserRegex
This commit is contained in:
270
backend/file.go
270
backend/file.go
@@ -1,13 +1,283 @@
|
|||||||
package backend
|
package backend
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
sql "github.com/FloatTech/sqlite"
|
||||||
"github.com/fumiama/paper-manager/backend/global"
|
"github.com/fumiama/paper-manager/backend/global"
|
||||||
"github.com/fumiama/paper-manager/backend/utils"
|
"github.com/fumiama/paper-manager/backend/utils"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errNoDeletePermission = errors.New("no delete permission")
|
||||||
|
errExtractUIDError = errors.New("extract uid error")
|
||||||
|
errParseFilePath = errors.New("parse filepath error")
|
||||||
|
errNoDownloadPermission = errors.New("no download permission")
|
||||||
|
)
|
||||||
|
|
||||||
|
type filelist struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Desc string `json:"description"`
|
||||||
|
Size float64 `json:"size"`
|
||||||
|
Ques int `json:"questions"`
|
||||||
|
Auth string `json:"author"`
|
||||||
|
Date string `json:"datetime"`
|
||||||
|
Per uint `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFileList(count int, istemp bool) ([]filelist, error) {
|
||||||
|
lst, err := global.FileDB.ListUploadedFile(istemp)
|
||||||
|
if err != nil && err != sql.ErrNullResult {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if count > 0 && len(lst) > count {
|
||||||
|
lst = lst[:count]
|
||||||
|
}
|
||||||
|
result := make([]filelist, len(lst))
|
||||||
|
for i, v := range lst {
|
||||||
|
result[i].ID = *v.ID
|
||||||
|
j := strings.LastIndex(v.Path, "/")
|
||||||
|
if j <= 0 {
|
||||||
|
result[i].Title = v.Path
|
||||||
|
} else {
|
||||||
|
result[i].Title = v.Path[j+1:]
|
||||||
|
}
|
||||||
|
result[i].Desc = v.Desc
|
||||||
|
result[i].Size = float64(v.Size) / 1024 / 1024 // MB
|
||||||
|
result[i].Ques = v.QuesC
|
||||||
|
result[i].Auth = v.UpName
|
||||||
|
result[i].Date = time.Unix(v.UpTime, 0).Format(chineseYYMMDDLayout)
|
||||||
|
if !v.HasntAnalyzed {
|
||||||
|
result[i].Per = 100
|
||||||
|
} else {
|
||||||
|
result[i].Per = analyzeper.Get(*v.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFileInfo(lstid int) (*filelist, error) {
|
||||||
|
lst, err := global.FileDB.ListFileByID(lstid)
|
||||||
|
if err != nil && err != sql.ErrNullResult {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := filelist{
|
||||||
|
ID: lstid,
|
||||||
|
Desc: lst.Desc,
|
||||||
|
Size: float64(lst.Size) / 1024 / 1024, // MB
|
||||||
|
Ques: lst.QuesC,
|
||||||
|
Auth: lst.UpName,
|
||||||
|
Date: time.Unix(lst.UpTime, 0).Format(chineseYYMMDDLayout),
|
||||||
|
}
|
||||||
|
j := strings.LastIndex(lst.Path, "/")
|
||||||
|
if j <= 0 {
|
||||||
|
result.Title = lst.Path
|
||||||
|
} else {
|
||||||
|
result.Title = lst.Path[j+1:]
|
||||||
|
}
|
||||||
|
if !lst.HasntAnalyzed {
|
||||||
|
result.Per = 100
|
||||||
|
} else {
|
||||||
|
result.Per = analyzeper.Get(lstid)
|
||||||
|
}
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func dlFile(lstid int, user *global.User) (string, error) {
|
||||||
|
lst, err := global.FileDB.ListFileByID(lstid)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(lst.Path, global.PaperFolder+"tmp/") {
|
||||||
|
uidstr := lst.Path[17:]
|
||||||
|
i := strings.Index(uidstr, "/")
|
||||||
|
if i <= 0 {
|
||||||
|
return "", errExtractUIDError
|
||||||
|
}
|
||||||
|
uid, err := strconv.Atoi(uidstr[:i])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if uid != *user.ID {
|
||||||
|
return "", errNoDownloadPermission
|
||||||
|
}
|
||||||
|
return lst.Path[6:], nil
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(lst.Path, global.PaperFolder) {
|
||||||
|
return lst.Path[6:], nil
|
||||||
|
}
|
||||||
|
return "", errParseFilePath
|
||||||
|
}
|
||||||
|
|
||||||
|
type filestatus struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Size float64 `json:"size"`
|
||||||
|
Rate float64 `json:"rate"`
|
||||||
|
Questions []question `json:"questions"`
|
||||||
|
Duplications []duplication `json:"duplications"` // Duplications length == 10
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFileStatus(lstid int, user *global.User) (*filestatus, error) {
|
||||||
|
file, sz, istemp, err := global.FileDB.GetFile(lstid, *user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
qs, ds, filerate, err := parseFileQuestions(file.Questions, istemp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &filestatus{
|
||||||
|
Name: file.Class + ".docx",
|
||||||
|
Size: float64(sz) / 1024 / 1024, // MB
|
||||||
|
Rate: filerate * 100,
|
||||||
|
Questions: qs,
|
||||||
|
Duplications: ds,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
apimap["/api/getFileList"] = &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
|
||||||
|
}
|
||||||
|
istemp := r.URL.Query().Get("permanent") != "true"
|
||||||
|
count := -1
|
||||||
|
var err error
|
||||||
|
countstr := r.URL.Query().Get("count")
|
||||||
|
if countstr != "" {
|
||||||
|
count, err = strconv.Atoi(countstr)
|
||||||
|
if err != nil {
|
||||||
|
writeresult(w, codeError, nil, err.Error(), typeError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lst, err := getFileList(count, istemp)
|
||||||
|
if err != nil {
|
||||||
|
writeresult(w, codeError, nil, err.Error(), typeError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeresult(w, codeSuccess, &lst, messageOk, typeSuccess)
|
||||||
|
}}
|
||||||
|
|
||||||
|
apimap["/api/getFileInfo"] = &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
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
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
|
||||||
|
}
|
||||||
|
inf, err := getFileInfo(id)
|
||||||
|
if err != nil {
|
||||||
|
writeresult(w, codeError, nil, err.Error(), typeError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeresult(w, codeSuccess, inf, 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
|
||||||
|
}
|
||||||
|
istemp := r.URL.Query().Get("permanent") != "true"
|
||||||
|
if !user.IsSuper() && !istemp {
|
||||||
|
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, istemp)
|
||||||
|
if err != nil {
|
||||||
|
writeresult(w, codeError, nil, err.Error(), typeError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeresult(w, codeSuccess, "删除成功", messageOk, typeSuccess)
|
||||||
|
}}
|
||||||
|
|
||||||
|
apimap["/api/dlFile"] = &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
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
type message struct {
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
u, err := dlFile(id, user)
|
||||||
|
if err != nil {
|
||||||
|
writeresult(w, codeError, nil, err.Error(), typeError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeresult(w, codeSuccess, &message{URL: u}, messageOk, typeSuccess)
|
||||||
|
}}
|
||||||
|
|
||||||
|
apimap["/api/getFileStatus"] = &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
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
fstat, err := getFileStatus(id, user)
|
||||||
|
if err != nil {
|
||||||
|
writeresult(w, codeError, nil, err.Error(), typeError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeresult(w, codeSuccess, fstat, messageOk, typeSuccess)
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
// FileHandler serves contents in global.FileFolder
|
// FileHandler serves contents in global.FileFolder
|
||||||
func FileHandler(w http.ResponseWriter, r *http.Request) {
|
func FileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if !utils.IsMethod("GET", w, r) {
|
if !utils.IsMethod("GET", w, r) {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ type Regex struct {
|
|||||||
Sub string // Sub default `(\d+)、`
|
Sub string // Sub default `(\d+)、`
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRegex() (reg Regex) {
|
func GetDefaultRegex() (reg Regex) {
|
||||||
reg.Title = `.*(\d{4})\s*-.*学年.*(\d).*([中末]).*([AB])\s*卷`
|
reg.Title = `.*(\d{4})\s*-.*学年.*(\d).*([中末]).*([AB])\s*卷`
|
||||||
reg.Class = `(考试科目|课程名称):\s*(\S+)\s*`
|
reg.Class = `(考试科目|课程名称):\s*(\S+)\s*`
|
||||||
reg.OpenCl = `考试形式:\s*(\S+)\s*`
|
reg.OpenCl = `考试形式:\s*(\S+)\s*`
|
||||||
@@ -52,7 +52,7 @@ func (u *UserDatabase) SetUserRegex(id int, name, re string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
reg := newRegex()
|
reg := GetDefaultRegex()
|
||||||
rreg := reflect.ValueOf(®).Elem()
|
rreg := reflect.ValueOf(®).Elem()
|
||||||
f := rreg.FieldByName(name)
|
f := rreg.FieldByName(name)
|
||||||
if !f.IsValid() {
|
if !f.IsValid() {
|
||||||
@@ -80,7 +80,7 @@ func (u *UserDatabase) GetUserRegex(id int) (*Regex, error) {
|
|||||||
u.mu.RUnlock()
|
u.mu.RUnlock()
|
||||||
reg.ID = *user.ID
|
reg.ID = *user.ID
|
||||||
rf := reflect.ValueOf(reg)
|
rf := reflect.ValueOf(reg)
|
||||||
defaultrf := reflect.ValueOf(newRegex())
|
defaultrf := reflect.ValueOf(GetDefaultRegex())
|
||||||
for i := 0; i < rf.NumField(); i++ {
|
for i := 0; i < rf.NumField(); i++ {
|
||||||
if rf.Field(i).IsZero() {
|
if rf.Field(i).IsZero() {
|
||||||
rf.Field(i).Set(defaultrf.Field(i))
|
rf.Field(i).Set(defaultrf.Field(i))
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ type loginResult struct {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
usertokens = ttl.NewCacheOn(time.Hour, [4]func(string, *global.User){
|
usertokens = ttl.NewCacheOn(time.Hour, [4]func(string, *global.User){
|
||||||
nil, nil, func(t string, _ *global.User) { loginstatus.Delete(t) }, nil,
|
nil, nil, func(_ string, user *global.User) { loginstatus.Delete(user.Name) }, nil,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
231
backend/paper.go
231
backend/paper.go
@@ -7,7 +7,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
sql "github.com/FloatTech/sqlite"
|
|
||||||
"github.com/FloatTech/ttl"
|
"github.com/FloatTech/ttl"
|
||||||
"github.com/fumiama/paper-manager/backend/global"
|
"github.com/fumiama/paper-manager/backend/global"
|
||||||
"github.com/fumiama/paper-manager/backend/utils"
|
"github.com/fumiama/paper-manager/backend/utils"
|
||||||
@@ -22,123 +21,10 @@ const (
|
|||||||
var analyzeper = ttl.NewCache[int, uint](time.Hour)
|
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")
|
|
||||||
errNoDownloadPermission = errors.New("no download permission")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type filelist struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Desc string `json:"description"`
|
|
||||||
Size float64 `json:"size"`
|
|
||||||
Ques int `json:"questions"`
|
|
||||||
Auth string `json:"author"`
|
|
||||||
Date string `json:"datetime"`
|
|
||||||
Per uint `json:"percent"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type filestatus struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Size float64 `json:"size"`
|
|
||||||
Rate float64 `json:"rate"`
|
|
||||||
Questions []question `json:"questions"`
|
|
||||||
Duplications []duplication `json:"duplications"` // Duplications length == 10
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
apimap["/api/getFileList"] = &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
|
|
||||||
}
|
|
||||||
istemp := r.URL.Query().Get("permanent") != "true"
|
|
||||||
count := -1
|
|
||||||
var err error
|
|
||||||
countstr := r.URL.Query().Get("count")
|
|
||||||
if countstr != "" {
|
|
||||||
count, err = strconv.Atoi(countstr)
|
|
||||||
if err != nil {
|
|
||||||
writeresult(w, codeError, nil, err.Error(), typeError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lst, err := global.FileDB.ListUploadedFile(istemp)
|
|
||||||
if err != nil && err != sql.ErrNullResult {
|
|
||||||
writeresult(w, codeError, nil, err.Error(), typeError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if count > 0 && len(lst) > count {
|
|
||||||
lst = lst[:count]
|
|
||||||
}
|
|
||||||
result := make([]filelist, len(lst))
|
|
||||||
for i, v := range lst {
|
|
||||||
result[i].ID = *v.ID
|
|
||||||
j := strings.LastIndex(v.Path, "/")
|
|
||||||
if j <= 0 {
|
|
||||||
result[i].Title = v.Path
|
|
||||||
} else {
|
|
||||||
result[i].Title = v.Path[j+1:]
|
|
||||||
}
|
|
||||||
result[i].Desc = v.Desc
|
|
||||||
result[i].Size = float64(v.Size) / 1024 / 1024 // MB
|
|
||||||
result[i].Ques = v.QuesC
|
|
||||||
result[i].Auth = v.UpName
|
|
||||||
result[i].Date = time.Unix(v.UpTime, 0).Format(chineseYYMMDDLayout)
|
|
||||||
if !v.HasntAnalyzed {
|
|
||||||
result[i].Per = 100
|
|
||||||
} else {
|
|
||||||
result[i].Per = analyzeper.Get(*v.ID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writeresult(w, codeSuccess, &result, messageOk, typeSuccess)
|
|
||||||
}}
|
|
||||||
apimap["/api/getFileInfo"] = &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
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
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
|
|
||||||
}
|
|
||||||
lst, err := global.FileDB.ListFileByID(id)
|
|
||||||
if err != nil && err != sql.ErrNullResult {
|
|
||||||
writeresult(w, codeError, nil, err.Error(), typeError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
result := filelist{
|
|
||||||
ID: id,
|
|
||||||
Desc: lst.Desc,
|
|
||||||
Size: float64(lst.Size) / 1024 / 1024, // MB
|
|
||||||
Ques: lst.QuesC,
|
|
||||||
Auth: lst.UpName,
|
|
||||||
Date: time.Unix(lst.UpTime, 0).Format(chineseYYMMDDLayout),
|
|
||||||
}
|
|
||||||
j := strings.LastIndex(lst.Path, "/")
|
|
||||||
if j <= 0 {
|
|
||||||
result.Title = lst.Path
|
|
||||||
} else {
|
|
||||||
result.Title = lst.Path[j+1:]
|
|
||||||
}
|
|
||||||
if !lst.HasntAnalyzed {
|
|
||||||
result.Per = 100
|
|
||||||
} else {
|
|
||||||
result.Per = analyzeper.Get(id)
|
|
||||||
}
|
|
||||||
writeresult(w, codeSuccess, &result, messageOk, typeSuccess)
|
|
||||||
}}
|
|
||||||
apimap["/api/getFilePercent"] = &apihandler{"GET", func(w http.ResponseWriter, r *http.Request) {
|
apimap["/api/getFilePercent"] = &apihandler{"GET", func(w http.ResponseWriter, r *http.Request) {
|
||||||
token := r.Header.Get("Authorization")
|
token := r.Header.Get("Authorization")
|
||||||
user := usertokens.Get(token)
|
user := usertokens.Get(token)
|
||||||
@@ -158,6 +44,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
writeresult(w, codeSuccess, analyzeper.Get(id), messageOk, typeSuccess)
|
writeresult(w, codeSuccess, analyzeper.Get(id), messageOk, typeSuccess)
|
||||||
}}
|
}}
|
||||||
|
|
||||||
apimap["/api/analyzeFile"] = &apihandler{"GET", func(w http.ResponseWriter, r *http.Request) {
|
apimap["/api/analyzeFile"] = &apihandler{"GET", func(w http.ResponseWriter, r *http.Request) {
|
||||||
token := r.Header.Get("Authorization")
|
token := r.Header.Get("Authorization")
|
||||||
user := usertokens.Get(token)
|
user := usertokens.Get(token)
|
||||||
@@ -211,120 +98,6 @@ 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
|
|
||||||
}
|
|
||||||
istemp := r.URL.Query().Get("permanent") != "true"
|
|
||||||
if !user.IsSuper() && !istemp {
|
|
||||||
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, istemp)
|
|
||||||
if err != nil {
|
|
||||||
writeresult(w, codeError, nil, err.Error(), typeError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
writeresult(w, codeSuccess, "删除成功", messageOk, typeSuccess)
|
|
||||||
}}
|
|
||||||
apimap["/api/dlFile"] = &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
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
lst, err := global.FileDB.ListFileByID(id)
|
|
||||||
if err != nil {
|
|
||||||
writeresult(w, codeError, nil, err.Error(), typeError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
type message struct {
|
|
||||||
URL string `json:"url"`
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(lst.Path, global.PaperFolder+"tmp/") {
|
|
||||||
uidstr := lst.Path[17:]
|
|
||||||
i := strings.Index(uidstr, "/")
|
|
||||||
if i <= 0 {
|
|
||||||
writeresult(w, codeError, nil, "extract uid error", typeError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
uid, err := strconv.Atoi(uidstr[:i])
|
|
||||||
if err != nil {
|
|
||||||
writeresult(w, codeError, nil, err.Error(), typeError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if uid != *user.ID {
|
|
||||||
writeresult(w, codeError, nil, errNoDownloadPermission.Error(), typeError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
writeresult(w, codeSuccess, &message{URL: lst.Path[6:]}, messageOk, typeSuccess)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(lst.Path, global.PaperFolder) {
|
|
||||||
writeresult(w, codeSuccess, &message{URL: lst.Path[6:]}, messageOk, typeSuccess)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
writeresult(w, codeError, nil, "parse filepath error", typeError)
|
|
||||||
}}
|
|
||||||
apimap["/api/getFileStatus"] = &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
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
file, sz, istemp, err := global.FileDB.GetFile(id, *user.ID)
|
|
||||||
if err != nil {
|
|
||||||
writeresult(w, codeError, nil, err.Error(), typeError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
qs, ds, filerate, err := parseFileQuestions(file.Questions, istemp)
|
|
||||||
if err != nil {
|
|
||||||
writeresult(w, codeError, nil, err.Error(), typeError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
writeresult(w, codeSuccess, &filestatus{
|
|
||||||
Name: file.Class + ".docx",
|
|
||||||
Size: float64(sz) / 1024 / 1024, // MB
|
|
||||||
Rate: filerate * 100,
|
|
||||||
Questions: qs,
|
|
||||||
Duplications: ds,
|
|
||||||
}, messageOk, typeSuccess)
|
|
||||||
}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PaperHandler serves protected contents in global.PaperFolder
|
// PaperHandler serves protected contents in global.PaperFolder
|
||||||
|
|||||||
26
backend/regex.go
Normal file
26
backend/regex.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package backend
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/fumiama/paper-manager/backend/global"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getUserRegex(token string) (*global.Regex, error) {
|
||||||
|
user := usertokens.Get(token)
|
||||||
|
if user == nil {
|
||||||
|
return nil, errInvalidToken
|
||||||
|
}
|
||||||
|
return global.UserDB.GetUserRegex(*user.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
apimap["/api/getUserRegex"] = &apihandler{"GET", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
reg, err := getUserRegex(r.Header.Get("Authorization"))
|
||||||
|
if err != nil {
|
||||||
|
writeresult(w, codeError, nil, err.Error(), typeError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeresult(w, codeSuccess, reg, messageOk, typeSuccess)
|
||||||
|
}}
|
||||||
|
}
|
||||||
@@ -4,4 +4,5 @@ export default {
|
|||||||
workbench: '工作台',
|
workbench: '工作台',
|
||||||
analysis: '分析页',
|
analysis: '分析页',
|
||||||
account: '用户管理',
|
account: '用户管理',
|
||||||
|
regex: '试卷解析配置',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ const menu: MenuModule = {
|
|||||||
path: 'account',
|
path: 'account',
|
||||||
name: t('routes.dashboard.account'),
|
name: t('routes.dashboard.account'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'regex',
|
||||||
|
name: t('routes.dashboard.regex'),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,15 @@ const dashboard: AppRouteModule = {
|
|||||||
roles: [RoleEnum.SUPER],
|
roles: [RoleEnum.SUPER],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'regex',
|
||||||
|
name: 'Regex',
|
||||||
|
component: () => import('/@/views/dashboard/regex/index.vue'),
|
||||||
|
meta: {
|
||||||
|
// affix: true,
|
||||||
|
title: t('routes.dashboard.regex'),
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { FormSchema } from '/@/components/Form'
|
import { FormSchema } from '/@/components/Form'
|
||||||
const colProps = {
|
const colProps = {
|
||||||
span: 8,
|
span: 24,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const schemas: FormSchema[] = [
|
export const schemas: FormSchema[] = [
|
||||||
@@ -8,80 +8,56 @@ export const schemas: FormSchema[] = [
|
|||||||
field: 'title',
|
field: 'title',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
colProps,
|
colProps,
|
||||||
label: '标题',
|
label: '试卷标题',
|
||||||
helpMessage: '目标的服务对象',
|
defaultValue: 'more 吗',
|
||||||
componentProps: {
|
|
||||||
placeholder: '请描述你服务的客户,内部客户直接 @姓名/工号',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'class',
|
field: 'class',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
colProps,
|
colProps,
|
||||||
label: '客户',
|
label: '课程名称',
|
||||||
helpMessage: '目标的服务对象',
|
defaultValue: 'more 吗',
|
||||||
componentProps: {
|
|
||||||
placeholder: '请描述你服务的客户,内部客户直接 @姓名/工号',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'opencl',
|
field: 'opencl',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
colProps,
|
colProps,
|
||||||
label: '客户',
|
label: '开/闭卷',
|
||||||
helpMessage: '目标的服务对象',
|
defaultValue: 'more 吗',
|
||||||
componentProps: {
|
|
||||||
placeholder: '请描述你服务的客户,内部客户直接 @姓名/工号',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'date',
|
field: 'date',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
colProps,
|
colProps,
|
||||||
label: '客户',
|
label: '考试日期',
|
||||||
helpMessage: '目标的服务对象',
|
defaultValue: 'more 吗',
|
||||||
componentProps: {
|
|
||||||
placeholder: '请描述你服务的客户,内部客户直接 @姓名/工号',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'time',
|
field: 'time',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
colProps,
|
colProps,
|
||||||
label: '客户',
|
label: '考试时长',
|
||||||
helpMessage: '目标的服务对象',
|
defaultValue: 'more 吗',
|
||||||
componentProps: {
|
|
||||||
placeholder: '请描述你服务的客户,内部客户直接 @姓名/工号',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'rate',
|
field: 'rate',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
colProps,
|
colProps,
|
||||||
label: '客户',
|
label: '成绩占比',
|
||||||
helpMessage: '目标的服务对象',
|
defaultValue: 'more 吗',
|
||||||
componentProps: {
|
|
||||||
placeholder: '请描述你服务的客户,内部客户直接 @姓名/工号',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'major',
|
field: 'major',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
colProps,
|
colProps,
|
||||||
label: '客户',
|
label: '大题题号',
|
||||||
helpMessage: '目标的服务对象',
|
defaultValue: 'more 吗',
|
||||||
componentProps: {
|
|
||||||
placeholder: '请描述你服务的客户,内部客户直接 @姓名/工号',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'sub',
|
field: 'sub',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
colProps,
|
colProps,
|
||||||
label: '客户',
|
label: '小题题号',
|
||||||
helpMessage: '目标的服务对象',
|
defaultValue: 'more 吗',
|
||||||
componentProps: {
|
|
||||||
placeholder: '请描述你服务的客户,内部客户直接 @姓名/工号',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<PageWrapper
|
<PageWrapper
|
||||||
title="基础表单"
|
:title="t('routes.dashboard.regex')"
|
||||||
contentBackground
|
contentBackground
|
||||||
content=" 表单页用于向用户收集或验证信息,基础表单常见于数据项较少的表单场景。"
|
content=" 表单页用于向用户收集或验证信息,基础表单常见于数据项较少的表单场景。"
|
||||||
contentClass="p-4"
|
contentClass="p-4"
|
||||||
@@ -14,11 +14,13 @@
|
|||||||
import { schemas } from './data'
|
import { schemas } from './data'
|
||||||
import { useMessage } from '/@/hooks/web/useMessage'
|
import { useMessage } from '/@/hooks/web/useMessage'
|
||||||
import { PageWrapper } from '/@/components/Page'
|
import { PageWrapper } from '/@/components/Page'
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'FormBasicPage',
|
name: 'FormBasicPage',
|
||||||
components: { BasicForm, PageWrapper },
|
components: { BasicForm, PageWrapper },
|
||||||
setup() {
|
setup() {
|
||||||
|
const { t } = useI18n()
|
||||||
const { createMessage } = useMessage()
|
const { createMessage } = useMessage()
|
||||||
const [register, { validate, setProps }] = useForm({
|
const [register, { validate, setProps }] = useForm({
|
||||||
labelCol: {
|
labelCol: {
|
||||||
@@ -57,7 +59,7 @@
|
|||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { register }
|
return { t, register }
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user