├── .gitignore ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── proj-review ├── .idea │ ├── .gitignore │ ├── modules.xml │ ├── proj-review.iml │ └── vcs.xml ├── auth │ ├── access.go │ └── jwt.go ├── conf │ ├── app.conf │ ├── file.conf │ ├── log.conf │ └── mongo.conf ├── constant │ ├── code.go │ ├── message.go │ └── msg.go ├── controllers │ ├── assignment.go │ ├── default.go │ ├── file.go │ ├── project.go │ └── user.go ├── database │ └── mongo.go ├── go.mod ├── go.sum ├── log │ └── log.go ├── main.go ├── models │ ├── assignment.go │ ├── file.go │ ├── project.go │ ├── reference.go │ ├── step.go │ ├── task.go │ └── user.go ├── request │ ├── assignment.go │ ├── default.go │ ├── file.go │ ├── project.go │ └── user.go ├── response │ ├── assignment.go │ ├── default.go │ ├── file.go │ ├── project.go │ └── user.go ├── routers │ ├── access.go │ ├── auth.go │ ├── default.go │ ├── file.go │ ├── project.go │ └── user.go ├── static │ └── js │ │ └── reload.min.js ├── tests │ ├── api-test.http │ ├── default_test.go │ ├── file-api-test.http │ ├── proj-api-test.http │ └── user-api-test.http ├── utils │ ├── gendoc.go │ ├── hash.go │ ├── mkdir.go │ └── uuid.go └── views │ ├── api.html │ ├── api.md │ └── index.tpl ├── review ├── .idea │ ├── httpRequests │ │ ├── 2021-08-19T170925.200.json │ │ ├── 2021-08-19T170954.200.json │ │ ├── 2021-08-19T171040.200.json │ │ ├── 2021-08-19T171401.200.json │ │ ├── 2021-08-19T171454.200.json │ │ ├── 2021-08-19T171716.200.json │ │ ├── 2021-08-19T171810.404.html │ │ ├── 2021-08-19T171820.400.json │ │ ├── 2021-08-19T171855.200.json │ │ ├── 2021-08-19T171944.200.json │ │ ├── 2021-08-19T171957.200.json │ │ ├── 2021-08-19T172053.200.json │ │ ├── 2021-08-19T172234.200.json │ │ ├── 2021-08-19T172324.200.json │ │ ├── 2021-08-19T172352.200.json │ │ ├── 2021-08-19T172607.200.html │ │ ├── 2021-08-19T172629.200.html │ │ ├── 2021-08-19T172636.200.html │ │ ├── 2021-08-19T172647.200.json │ │ ├── 2021-08-19T172709.200.json │ │ ├── 2021-08-19T172827.200.json │ │ ├── 2021-08-19T173234.200.json │ │ ├── 2021-08-19T173351.200.json │ │ ├── 2021-08-19T173453.200.json │ │ ├── 2021-08-19T173531.200.json │ │ ├── 2021-08-19T173650.200.json │ │ ├── 2021-08-19T173745.200.json │ │ ├── 2021-08-20T173424.200.json │ │ ├── 2021-08-20T173441.200.json │ │ ├── 2021-08-20T173509.200.json │ │ ├── 2021-08-20T173526.200.json │ │ ├── 2021-08-20T173545.200.json │ │ ├── 2021-08-20T173556.200.json │ │ ├── 2021-08-20T173717.200.json │ │ ├── 2021-08-20T185844.200.json │ │ ├── 2021-08-20T185859.200.json │ │ ├── 2021-08-23T111250.200.json │ │ ├── 2021-08-24T085435.200.json │ │ ├── 2021-08-24T085452.200.json │ │ ├── 2021-08-24T085502.200.json │ │ ├── 2021-08-24T085511.200.json │ │ ├── 2021-08-24T085520.200.json │ │ ├── 2021-08-24T085529.200.json │ │ ├── 2021-08-24T085550.200.json │ │ ├── 2021-08-24T085559.200.json │ │ ├── 2021-08-24T085607.200.json │ │ ├── 2021-08-24T085622.200.json │ │ ├── 2021-08-24T092901.200.json │ │ ├── 2021-08-24T175026.200.json │ │ ├── http-client.cookies │ │ └── http-requests-log.http │ ├── modules.xml │ ├── review.iml │ ├── vcs.xml │ └── workspace.xml ├── access │ ├── check.go │ ├── cros.go │ ├── filter.go │ └── jwt.go ├── conf │ ├── app.conf │ ├── file.conf │ ├── log.conf │ ├── mail.conf │ └── mongo.conf ├── controllers │ ├── assignment.go │ ├── audit.go │ ├── default.go │ ├── file.go │ ├── noticer.go │ ├── project.go │ ├── query.go │ ├── step.go │ ├── submit.go │ └── user.go ├── database │ └── mongo.go ├── go.mod ├── go.sum ├── logger │ └── log.go ├── main.go ├── models │ ├── assignment.go │ ├── audit.go │ ├── file.go │ ├── project.go │ ├── step.go │ ├── submit.go │ ├── user.go │ └── versionItem.go ├── noticer │ ├── mail.go │ └── message.go ├── query │ └── query.go ├── request │ ├── file.go │ ├── project.go │ └── user.go ├── response │ ├── code.go │ ├── default.go │ └── listquery.go ├── routers │ ├── commentsRouter_controllers.go │ └── router.go ├── swagger.zip ├── swagger │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── index.html │ ├── oauth2-redirect.html │ ├── swagger-ui-bundle.js │ ├── swagger-ui-bundle.js.map │ ├── swagger-ui-standalone-preset.js │ ├── swagger-ui-standalone-preset.js.map │ ├── swagger-ui.css │ ├── swagger-ui.css.map │ ├── swagger-ui.js │ ├── swagger-ui.js.map │ ├── swagger.json │ └── swagger.yml ├── tests │ ├── default_test.go │ ├── file-test.http │ └── user-test.http └── utils │ ├── crypto.go │ ├── json.go │ ├── mkdir.go │ └── uuid.go ├── warehouse ├── .idea │ ├── .gitignore │ ├── modules.xml │ ├── vcs.xml │ └── warehouse.iml ├── conf │ ├── app.conf │ ├── log.conf │ └── mongo.conf ├── controllers │ ├── default.go │ ├── query.go │ ├── question.go │ ├── testpaper.go │ └── user.go ├── database │ └── mongo.go ├── go.mod ├── go.sum ├── logger │ └── logger.go ├── main.go ├── models │ ├── actions.go │ ├── query.go │ ├── question.go │ ├── request.go │ ├── testpaper.go │ └── user.go ├── routers │ ├── commentsRouter_controllers.go │ └── router.go ├── swagger.zip ├── swagger │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── index.html │ ├── oauth2-redirect.html │ ├── swagger-ui-bundle.js │ ├── swagger-ui-bundle.js.map │ ├── swagger-ui-standalone-preset.js │ ├── swagger-ui-standalone-preset.js.map │ ├── swagger-ui.css │ ├── swagger-ui.css.map │ ├── swagger-ui.js │ ├── swagger-ui.js.map │ ├── swagger.json │ └── swagger.yml ├── tests │ └── default_test.go └── utils │ └── uuid.go └── web ├── .gitignore ├── README.md ├── build ├── asset-manifest.json ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json ├── robots.txt └── static │ ├── css │ ├── 2.e4902758.chunk.css │ ├── 2.e4902758.chunk.css.map │ ├── main.28dd778d.chunk.css │ └── main.28dd778d.chunk.css.map │ ├── js │ ├── 2.75a36cd2.chunk.js │ ├── 2.75a36cd2.chunk.js.LICENSE.txt │ ├── 2.75a36cd2.chunk.js.map │ ├── main.f8299ca7.chunk.js │ ├── main.f8299ca7.chunk.js.map │ ├── runtime-main.3b3646ce.js │ └── runtime-main.3b3646ce.js.map │ └── media │ ├── Rockets.bcd94bd9.png │ ├── login_background.d1cc80fb.png │ └── proposition-paper-icon.2d177c41.png ├── config-overrides.js ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── src ├── App.jsx ├── App.less ├── asset │ └── images │ │ ├── Cloud.png │ │ ├── Crying_face.png │ │ ├── Flu_expression.png │ │ ├── Rockets.png │ │ ├── Unhapply.png │ │ ├── login_background.png │ │ ├── openct_logo_1082x328.png │ │ └── proposition-paper-icon.png ├── components │ ├── BuildTeam │ │ ├── index.jsx │ │ └── index.less │ ├── CalendarButton │ │ ├── index.jsx │ │ └── index.less │ ├── ChangeTags │ │ ├── index.jsx │ │ └── index.less │ ├── ChoiceQuestionEditer │ │ ├── index.jsx │ │ └── index.less │ ├── CompletionStatus │ │ ├── index.jsx │ │ └── index.less │ ├── DataTable │ │ ├── index.jsx │ │ └── index.less │ ├── DifficultyBox │ │ ├── index.jsx │ │ └── index.less │ ├── HistoryQuestion │ │ ├── index.jsx │ │ └── index.less │ ├── MaterialWarehouse │ │ ├── index.jsx │ │ └── index.less │ ├── ModifyRecordModal │ │ ├── index.jsx │ │ └── index.less │ ├── ModulaCard │ │ ├── index.jsx │ │ └── index.less │ ├── Step │ │ ├── index.jsx │ │ └── index.less │ ├── TaskRequirements │ │ ├── index.jsx │ │ └── index.less │ ├── UpLoadModal │ │ ├── index.jsx │ │ └── index.less │ └── UpLoadQuestionModal │ │ ├── index.jsx │ │ └── index.less ├── conf │ └── index.js ├── index.js ├── index.less ├── logo.svg ├── setupProxy.js ├── store │ ├── action.js │ ├── constants.js │ ├── index.js │ └── reducer.js ├── utils │ ├── cookies.js │ ├── request.js │ └── storage.js └── views │ ├── Home │ ├── index.jsx │ └── index.less │ ├── Login │ ├── index.jsx │ └── index.less │ ├── PendingTasks │ ├── index.jsx │ └── index.less │ ├── ProjectManagement │ ├── index.jsx │ └── index.less │ ├── PropositionPaper │ ├── index.jsx │ └── views │ │ ├── CreatePaper │ │ ├── index.jsx │ │ └── index.less │ │ ├── Home │ │ ├── home.jsx │ │ └── index.less │ │ └── UploadQuestions │ │ ├── index.jsx │ │ └── index.less │ └── errors │ ├── 402.jsx │ ├── 404.jsx │ └── index.less └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | 17 | # Goalng mod packs: 18 | vendor 19 | 20 | # ignore the log file 21 | *.log 22 | 23 | # compile temp file 24 | *.tmp 25 | 26 | # temp upload file & exec file 27 | proj-review/static/files/* 28 | proj-review/proj-review 29 | review/static/files/* 30 | 31 | 32 | /node_modules 33 | package-lock.json 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenItem 2 | Online proposition and question bank system. 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "cz-conventional-changelog": "^3.3.0" 4 | }, 5 | "config": { 6 | "commitizen": { 7 | "path": "./node_modules/cz-conventional-changelog" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /proj-review/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /proj-review/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /proj-review/.idea/proj-review.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /proj-review/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /proj-review/auth/access.go: -------------------------------------------------------------------------------- 1 | package auth 2 | -------------------------------------------------------------------------------- /proj-review/conf/app.conf: -------------------------------------------------------------------------------- 1 | ; Basic config 2 | appname = PQBS_review_module 3 | httpaddr = localhost 4 | httpport = 9001 5 | runmode = dev 6 | copyrequestbody = true 7 | 8 | # iclude "mysql.conf" 9 | include "mongo.conf" 10 | include "file.conf" 11 | include "log.conf" -------------------------------------------------------------------------------- /proj-review/conf/file.conf: -------------------------------------------------------------------------------- 1 | ; 用于配置文件上传 & 下载 2 | filerootpath = "static/files/" 3 | maxmemory = 1<<22 4 | -------------------------------------------------------------------------------- /proj-review/conf/log.conf: -------------------------------------------------------------------------------- 1 | ; review module log 2 | 3 | logpath = log/ 4 | logfile = pqbs-review.log 5 | loglevel = full -------------------------------------------------------------------------------- /proj-review/conf/mongo.conf: -------------------------------------------------------------------------------- 1 | ; mongo database config 2 | mongoaddr = localhost 3 | mongoport = 27017 4 | mongodb = openct_pqbs 5 | mongouser = openct 6 | mongopwd = 123456 7 | 8 | ; collections name define 9 | [mongo-collections] 10 | ; review 11 | users = "users" 12 | assignments = "assignments" 13 | projects = "projects" 14 | steps = "steps" 15 | tasks = "tasks" 16 | fileRecords = "file_records" 17 | references = "references" 18 | 19 | ; warehouse 20 | tempQuestions = "temp_questions" 21 | finalQuestions = "final_questions" 22 | tempTestPapers = "temp_test_papers" 23 | finalTestPapers = "final_test_papers" -------------------------------------------------------------------------------- /proj-review/constant/code.go: -------------------------------------------------------------------------------- 1 | package constant 2 | 3 | var ( 4 | SUCCESS = 1000 5 | FAIL = 2000 6 | ) 7 | -------------------------------------------------------------------------------- /proj-review/constant/msg.go: -------------------------------------------------------------------------------- 1 | package constant 2 | 3 | var Message = make(map[int]string) 4 | 5 | func init() { 6 | message := make(map[int]string) 7 | message[SUCCESS] = "ok" 8 | message[FAIL] = "发生未知错误" 9 | 10 | Message = message 11 | } 12 | -------------------------------------------------------------------------------- /proj-review/controllers/assignment.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import beego "github.com/beego/beego/v2/server/web" 4 | 5 | type AssignmentController struct { 6 | beego.Controller 7 | } 8 | -------------------------------------------------------------------------------- /proj-review/controllers/default.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | beego "github.com/beego/beego/v2/server/web" 7 | "proj-review/auth" 8 | "proj-review/log" 9 | ) 10 | 11 | // Test controller, no used. 12 | type MainController struct { 13 | beego.Controller 14 | } 15 | 16 | func (c *MainController) Get() { 17 | c.Data["Website"] = "beego.me" 18 | c.Data["Email"] = "astaxie@gmail.com" 19 | c.TplName = "index.tpl" 20 | } 21 | 22 | func (c *MainController) List() { 23 | c.TplName = "api.html" 24 | } 25 | 26 | func (c *MainController) Demo() { 27 | c.Ctx.Output.Download("tests/api-test.http", "api.http") 28 | } 29 | 30 | // universal functions in controller 31 | 32 | // unmarshalBody parse the response body (json type) 33 | func unmarshalBody(body []byte, obj interface{}) error { 34 | // marshal json body 35 | if err := json.Unmarshal(body, obj); err != nil { 36 | log.Logger.Warn("[JSON] " + err.Error()) 37 | return err 38 | } 39 | return nil 40 | } 41 | 42 | // parseUserToken get user id from token string 43 | func parseUserToken(token string) (string, error) { 44 | // 45 | fmt.Println("recv token: ", token) 46 | // 47 | tokenData, err := auth.ParseToken(token) 48 | if err != nil { 49 | return "", err 50 | } 51 | // 52 | fmt.Println("recv user: ", tokenData.UserID) 53 | fmt.Println("recv token time from ", tokenData.IssuedAt, " to ", tokenData.ExpiresAt) 54 | // 55 | return tokenData.UserID, nil 56 | } 57 | 58 | func checkHttpBodyEmpty(body []byte) bool { 59 | if len(body) == 0 { 60 | return false 61 | } 62 | return true 63 | } 64 | -------------------------------------------------------------------------------- /proj-review/go.mod: -------------------------------------------------------------------------------- 1 | module proj-review 2 | 3 | go 1.16 4 | 5 | require github.com/beego/beego/v2 v2.0.1 6 | 7 | require ( 8 | github.com/dgrijalva/jwt-go v3.2.0+incompatible 9 | github.com/google/uuid v1.3.0 10 | github.com/microcosm-cc/bluemonday v1.0.15 11 | github.com/qiniu/qmgo v0.9.4 12 | github.com/russross/blackfriday v1.6.0 13 | github.com/smartystreets/goconvey v1.6.4 14 | go.mongodb.org/mongo-driver v1.7.1 15 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 16 | ) 17 | -------------------------------------------------------------------------------- /proj-review/log/log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "fmt" 5 | "github.com/beego/beego/v2/core/logs" 6 | beego "github.com/beego/beego/v2/server/web" 7 | ) 8 | 9 | var Logger *logs.BeeLogger 10 | 11 | func init() { 12 | // 设置日志生成器 13 | log := logs.NewLogger() 14 | // 读取配置 15 | logPath, err := beego.AppConfig.String("logpath") 16 | if err != nil { 17 | fmt.Println("load log path config error.") 18 | } 19 | logFile, err := beego.AppConfig.String("logfile") 20 | if err != nil { 21 | fmt.Println("load log filename config error.") 22 | } 23 | // 配置日志输出 todo: more options need to be config by .conf 24 | logConfig := fmt.Sprintf( 25 | `{"filename":"%s","level":7,"daily":true,"maxdays":10,"color":true}`, 26 | logPath+logFile, 27 | ) 28 | log.SetLogger( 29 | logs.AdapterFile, 30 | logConfig, 31 | ) 32 | log.SetLogger(logs.AdapterConsole) 33 | log.EnableFuncCallDepth(true) 34 | log.SetLevel(logs.LevelDebug) 35 | 36 | Logger = log 37 | } 38 | -------------------------------------------------------------------------------- /proj-review/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | beego "github.com/beego/beego/v2/server/web" 5 | _ "proj-review/database" 6 | _ "proj-review/routers" 7 | ) 8 | 9 | func main() { 10 | beego.Run() 11 | } 12 | -------------------------------------------------------------------------------- /proj-review/models/reference.go: -------------------------------------------------------------------------------- 1 | package models 2 | -------------------------------------------------------------------------------- /proj-review/models/step.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/qiniu/qmgo/field" 5 | ) 6 | 7 | type Step struct { 8 | field.DefaultField `bson:",inline"` 9 | Uuid string `json:"uuid" bson:"uuid"` 10 | Belong string `json:"belong" bson:"belong"` 11 | Name string `json:"name" bson:"name"` 12 | Status int `json:"status" bson:"status"` 13 | Tasks string `json:"tasks" bson:"tasks"` 14 | Description string `json:"description" bson:"description"` 15 | } 16 | -------------------------------------------------------------------------------- /proj-review/models/task.go: -------------------------------------------------------------------------------- 1 | package models 2 | -------------------------------------------------------------------------------- /proj-review/request/assignment.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | type MakeAssignment struct { 4 | UserId string `json:"user_id"` 5 | ProjectId string `json:"project_id"` 6 | Role int `json:"role"` 7 | Operator string `json:"operator"` 8 | } 9 | 10 | type ChangeAssignment struct { 11 | AssignmentId string `json:"assignment_id"` 12 | NewRole int `json:"new_role"` 13 | Operator string `json:"operator"` 14 | } 15 | -------------------------------------------------------------------------------- /proj-review/request/default.go: -------------------------------------------------------------------------------- 1 | package request 2 | -------------------------------------------------------------------------------- /proj-review/request/file.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | /* 4 | Define some request structures for file operations. 5 | */ 6 | 7 | // UploadFile define the upload file request format 8 | type UploadFile struct { 9 | UserId string `json:"user_id"` 10 | FileName string `json:"file_name"` 11 | Type string `json:"type"` 12 | Description string `json:"description"` 13 | Tags []string `json:"tags"` 14 | } 15 | 16 | // SearchFile define the search request format, todo 17 | type SearchFile struct { 18 | FileName string `json:"file_name"` 19 | Type string `json:"type"` 20 | Tags []string `json:"tags"` 21 | } 22 | 23 | // GetFileInfo: just using http-get with url params 24 | // DownloadFile: just using http-get with url params 25 | -------------------------------------------------------------------------------- /proj-review/request/project.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | type CreateProject struct { 4 | Name string `json:"name"` 5 | Description string `json:"description"` 6 | Requirement string `json:"requirement"` 7 | Target string `json:"target"` 8 | GradeRange []string `json:"grade_range"` 9 | Subjects []string `json:"subjects"` 10 | Summary string `json:"summary"` 11 | Creator string `json:"creator"` 12 | } 13 | 14 | type SearchProject struct { 15 | Name string `json:"name"` 16 | GradeRange []string `json:"grade_range"` 17 | Subjects []string `json:"subjects"` 18 | } 19 | 20 | type GetUserProjects struct { 21 | UserId string `json:"user_id"` 22 | } 23 | -------------------------------------------------------------------------------- /proj-review/request/user.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | // CheckDuplicate 4 | type CheckDuplicate struct { 5 | Phone string `json:"phone"` 6 | Email string `json:"email"` 7 | } 8 | 9 | //UserLogin define the user login struct 10 | type UserLogin struct { 11 | Phone string `json:"phone"` 12 | Email string `json:"email"` 13 | Password string `json:"password"` 14 | } 15 | 16 | // UserRegister defines create user request format 17 | type UserRegister struct { 18 | Name string `json:"name"` 19 | Password string `json:"password"` 20 | Email string `json:"email"` 21 | Phone string `json:"phone"` 22 | Gender bool `json:"gender"` 23 | Degree string `json:"degree"` 24 | Position string `json:"position"` 25 | Employer string `json:"employer"` 26 | Major string `json:"major"` 27 | } 28 | 29 | // UserUpdatePassword define the update password req format 请求更新密码 30 | type UserUpdatePassword struct { 31 | ID string `json:"id"` 32 | OldPassword string `json:"old_password"` 33 | NewPassword string `json:"new_password"` 34 | } 35 | 36 | // UserUpdateInfo define the user info updating request format 37 | type UserUpdateInfo struct { 38 | ID string `json:"id"` 39 | Name string `json:"name"` 40 | Email string `json:"email"` 41 | Phone string `json:"phone"` 42 | Gender bool `json:"gender"` 43 | Degree string `json:"degree"` 44 | Position string `json:"position"` 45 | Employer string `json:"employer"` 46 | Major string `json:"major"` 47 | } 48 | 49 | // GetUserInfo: just using http-get with url params 50 | // UserLogout: just using http-get with url params 51 | 52 | // UserSearch define search users struct 53 | type UserSearch struct { 54 | Phone string `json:"phone"` 55 | Email string `json:"email"` 56 | Name string `json:"name"` 57 | Degree string `json:"degree"` 58 | Position string `json:"position"` 59 | Employer string `json:"employer"` 60 | Major string `json:"major"` 61 | } 62 | -------------------------------------------------------------------------------- /proj-review/response/assignment.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | import "time" 4 | 5 | type AssignmentDefault struct { 6 | AssignmentId string `json:"assignment_id"` 7 | Description string `json:"description"` 8 | } 9 | 10 | type GetAssignments struct { 11 | Count int `json:"count"` 12 | Assignments []AssignmentItem `json:"assignments"` 13 | Description string `json:"description"` 14 | } 15 | 16 | type AssignmentItem struct { 17 | Uuid string `json:"uuid"` 18 | UserId string `json:"user_id"` 19 | UserName string `json:"user_name"` 20 | ProjectId string `json:"project_id"` 21 | ProjectName string `json:"project_name"` 22 | Role int `json:"role"` 23 | IsConfirmed bool `json:"is_confirmed"` 24 | Status int `json:"status"` 25 | CreatedAt time.Time `json:"created_at"` 26 | } 27 | -------------------------------------------------------------------------------- /proj-review/response/default.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | // Default define the default response format 4 | type Default struct { 5 | Code int `json:"code"` 6 | Message string `json:"message"` 7 | Data interface{} `json:"data"` 8 | } 9 | 10 | // GenResponse function to generate default response struct. 11 | func GenResponse(code int, msg string, data interface{}) Default { 12 | return Default{ 13 | Code: code, 14 | Message: msg, 15 | Data: data, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /proj-review/response/file.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | // FileDefault 4 | type FileDefault struct { 5 | FileID string `json:"file_id"` 6 | FileName string `json:"file_name"` 7 | FileType string `json:"file_type"` 8 | FilePath string `json:"file_path"` 9 | Description string `json:"description"` 10 | } 11 | 12 | // FindFile 13 | type FindFile struct { 14 | FileID string `json:"file_id"` 15 | FileName string `json:"file_name"` 16 | FileType string `json:"file_type"` 17 | FileTags []string `json:"file_tags"` 18 | FilePath string `json:"file_path"` 19 | FileDescription string `json:"file_description"` 20 | FileOwner string `json:"file_owner"` 21 | Description string `json:"description"` 22 | } 23 | 24 | // SearchFiles 25 | type SearchFiles struct { 26 | SearchCount int `json:"search_count"` 27 | Results []FileItem `json:"results"` 28 | Description string `json:"description"` 29 | } 30 | 31 | type FileItem struct { 32 | FileID string `json:"file_id"` 33 | FileName string `json:"file_name"` 34 | FileType string `json:"file_type"` 35 | FileTags []string `json:"file_tags"` 36 | FilePath string `json:"file_path"` 37 | FileOwner string `json:"file_owner"` 38 | FileDescription string `json:"file_description"` 39 | } 40 | -------------------------------------------------------------------------------- /proj-review/response/project.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | import "time" 4 | 5 | type ProjectDefault struct { 6 | ProjectID string `json:"project_id"` 7 | ProjectName string `json:"project_name"` 8 | Description string `json:"description"` 9 | } 10 | 11 | type ProjectInfo struct { 12 | ProjectId string `json:"project_id"` 13 | ProjectName string `json:"project_name"` 14 | ProjectDescription string `json:"project_description"` 15 | Requirement string `json:"requirement"` 16 | Target string `json:"target"` 17 | GradeRange []string `json:"grade_range"` 18 | Subjects []string `json:"subjects"` 19 | Summary string `json:"summary"` 20 | Creator string `json:"creator"` 21 | Status int `json:"status"` 22 | Group interface{} `json:"group"` 23 | Timetable interface{} `json:"timetable"` 24 | Steps interface{} `json:"steps"` 25 | Description string `json:"description"` 26 | CreateAt time.Time `json:"create_at"` 27 | UpdatedAt time.Time `json:"updated_at"` 28 | } 29 | -------------------------------------------------------------------------------- /proj-review/response/user.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | // UserDefault 4 | /* 5 | This response used in: 6 | */ 7 | type UserDefault struct { 8 | UserID string `json:"user_id"` 9 | Name string `json:"name"` 10 | Description string `json:"description"` 11 | } 12 | 13 | // UserInfo 14 | type UserInfo struct { 15 | UserID string `json:"user_id"` 16 | Name string `json:"name"` 17 | Email string `json:"email"` 18 | Phone string `json:"phone"` 19 | Gender bool `json:"gender"` 20 | Degree string `json:"degree"` 21 | Position string `json:"position"` 22 | Employer string `json:"employer"` 23 | Major string `json:"major"` 24 | Description string `json:"description"` 25 | } 26 | 27 | // UserList 28 | type UserList struct { 29 | UserList []UserInfo `json:"user_list"` 30 | Count int `json:"count"` 31 | Description string `json:"description"` 32 | } 33 | 34 | // LoginResponse defines login result response 35 | type LoginResponse struct { 36 | UserID string `json:"user_id"` 37 | UserInfo UserInfo `json:"user_info"` 38 | Token string `json:"token"` 39 | Description string `json:"description"` 40 | } 41 | 42 | // CheckDuplicate 43 | type CheckDuplicate struct { 44 | Result bool `json:"result"` 45 | Description string `json:"description"` 46 | } 47 | -------------------------------------------------------------------------------- /proj-review/routers/access.go: -------------------------------------------------------------------------------- 1 | package routers 2 | -------------------------------------------------------------------------------- /proj-review/routers/auth.go: -------------------------------------------------------------------------------- 1 | package routers 2 | 3 | /* 4 | provide some apis (routers) for auth module 5 | */ 6 | -------------------------------------------------------------------------------- /proj-review/routers/default.go: -------------------------------------------------------------------------------- 1 | package routers 2 | 3 | import ( 4 | beego "github.com/beego/beego/v2/server/web" 5 | "proj-review/controllers" 6 | ) 7 | 8 | func init() { 9 | beego.Router("/", &controllers.MainController{}) 10 | // 开发测试使用 11 | beego.Router("/api/list", &controllers.MainController{}, "get:List") 12 | beego.Router("/api/demo", &controllers.MainController{}, "get:Demo") 13 | } 14 | -------------------------------------------------------------------------------- /proj-review/routers/file.go: -------------------------------------------------------------------------------- 1 | package routers 2 | 3 | import ( 4 | beego "github.com/beego/beego/v2/server/web" 5 | "proj-review/controllers" 6 | ) 7 | 8 | func init() { 9 | beego.Router("/file/getInfo", &controllers.FileController{}, "get:GetFileInfo") 10 | beego.Router("/file/download", &controllers.FileController{}, "get:DownloadFile") 11 | beego.Router("/file/upload", &controllers.FileController{}, "post:UploadFile") 12 | beego.Router("/file/search", &controllers.FileController{}, "post:SearchFile") 13 | beego.Router("/file/delete", &controllers.FileController{}, "get:DeleteFile") 14 | } 15 | -------------------------------------------------------------------------------- /proj-review/routers/project.go: -------------------------------------------------------------------------------- 1 | package routers 2 | 3 | import ( 4 | beego "github.com/beego/beego/v2/server/web" 5 | "proj-review/controllers" 6 | ) 7 | 8 | func init() { 9 | // projects 10 | beego.Router("/proj/createEmpty", &controllers.ProjectController{}, "post:CreateNewProject") 11 | beego.Router("/proj/getInfo", &controllers.ProjectController{}, "get:GetProjectInfo") 12 | // assignments 13 | beego.Router("/proj/userAssign", &controllers.ProjectController{}, "get:GetUserAssignments") 14 | beego.Router("/proj/projectAssign", &controllers.ProjectController{}, "get:GetProjectAssignments") 15 | beego.Router("/proj/makeAssign", &controllers.ProjectController{}, "post:MakeNewAssignment") 16 | beego.Router("/proj/changeAssign", &controllers.ProjectController{}, "post:ChangeAssignment") 17 | beego.Router("/proj/removeAssign", &controllers.ProjectController{}, "get:RemoveAssignment") 18 | 19 | } 20 | -------------------------------------------------------------------------------- /proj-review/routers/user.go: -------------------------------------------------------------------------------- 1 | package routers 2 | 3 | import ( 4 | beego "github.com/beego/beego/v2/server/web" 5 | "proj-review/controllers" 6 | ) 7 | 8 | func init() { 9 | // 用户登录 & 注册路由 10 | beego.Router("/user/checkInfo", &controllers.UserController{}, "post:CheckDuplicate") 11 | beego.Router("/user/register", &controllers.UserController{}, "post:UserRegister") 12 | beego.Router("/user/login", &controllers.UserController{}, "post:UserLogin") 13 | // todo: 用户退出登陆操作 14 | beego.Router("/user/logout", &controllers.UserController{}, "get:UserLogout") 15 | beego.Router("/user/delete", &controllers.UserController{}, "get:DeleteUser") 16 | // todp: search user 17 | beego.Router("/user/search", &controllers.UserController{}, "post:SearchUser") 18 | beego.Router("/user/getInfo", &controllers.UserController{}, "get:GetUserInfo") 19 | beego.Router("/user/updateInfo", &controllers.UserController{}, "post:UpdateUserInfo") 20 | beego.Router("/user/updatePwd", &controllers.UserController{}, "post:UpdateUserPassword") 21 | } 22 | -------------------------------------------------------------------------------- /proj-review/static/js/reload.min.js: -------------------------------------------------------------------------------- 1 | function b(a){var c=new WebSocket(a);c.onclose=function(){setTimeout(function(){b(a)},2E3)};c.onmessage=function(){location.reload()}}try{if(window.WebSocket)try{b("ws://localhost:12450/reload")}catch(a){console.error(a)}else console.log("Your browser does not support WebSockets.")}catch(a){console.error("Exception during connecting to Reload:",a)}; 2 | -------------------------------------------------------------------------------- /proj-review/tests/default_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "path/filepath" 7 | _ "proj-review/routers" 8 | "runtime" 9 | "testing" 10 | 11 | beego "github.com/beego/beego/v2/server/web" 12 | . "github.com/smartystreets/goconvey/convey" 13 | ) 14 | 15 | func init() { 16 | _, file, _, _ := runtime.Caller(0) 17 | apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator)))) 18 | beego.TestBeegoInit(apppath) 19 | } 20 | 21 | // TestBeego is a sample to run an endpoint test 22 | func TestBeego(t *testing.T) { 23 | r, _ := http.NewRequest("GET", "/", nil) 24 | w := httptest.NewRecorder() 25 | beego.BeeApp.Handlers.ServeHTTP(w, r) 26 | 27 | beego.Trace("testing", "TestBeego", "Code[%d]\n%s", w.Code, w.Body.String()) 28 | 29 | Convey("Subject: Test Station Endpoint\n", t, func() { 30 | Convey("Status Code Should Be 200", func() { 31 | So(w.Code, ShouldEqual, 200) 32 | }) 33 | Convey("The Result Should Not Be Empty", func() { 34 | So(w.Body.Len(), ShouldBeGreaterThan, 0) 35 | }) 36 | }) 37 | } 38 | -------------------------------------------------------------------------------- /proj-review/tests/file-api-test.http: -------------------------------------------------------------------------------- 1 | POST http://localhost:9001/file/search 2 | Content-Type: application/json 3 | 4 | { 5 | "file_name": "雷达图.png", 6 | "type": ".png" 7 | } 8 | 9 | ### 10 | GET http://localhost:9001/file/delete?file_id=9094ce1c-e402-4e07-a363-a3383a471010 11 | Accept: application/json 12 | 13 | 14 | ### 15 | GET http://localhost:9001/file/getInfo?file_id=9094ce1c-e402-4e07-a363-a3383a471010 16 | Accept: application/json 17 | 18 | ### 19 | GET http://localhost:9001/file/download?file_id=9094ce1c-e402-4e07-a363-a3383a471010 20 | Accept: application/json 21 | 22 | ### xx 23 | POST http://localhost:9001/file/upload 24 | Content-Type: multipart/form-data; boundary=WebAppBoundary 25 | 26 | --WebAppBoundary 27 | Content-Disposition: form-data; name="field-name"; filename="file.txt" 28 | 29 | < ./relative/path/to/local_file.txt 30 | --WebAppBoundary-- -------------------------------------------------------------------------------- /proj-review/tests/proj-api-test.http: -------------------------------------------------------------------------------- 1 | POST http://localhost:9001/proj/changeAssign 2 | Content-Type: application/json 3 | Token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYzk5M2FhM2MtYWRlOS00ZDk5LWE1NmItNmE1YjQ3MmQ5ZGJhIiwiZXhwIjoxNjI5NzE2MDUxLCJpYXQiOjE2MjkxMTEyNTEsImlzcyI6InJvYm90LTFAcHFicy5jb20ifQ.D1jdCkOv56qn_BQaDym_Omg2LkHj7s6PjjTYpKstRS4 4 | 5 | { 6 | "assignment_id": "a33cbbc9-5497-48df-9d95-f3f25f270af9", 7 | "new_role": 1 8 | } 9 | 10 | ### 11 | POST http://localhost:9001/proj/makeAssign 12 | Content-Type: application/json 13 | Token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYzk5M2FhM2MtYWRlOS00ZDk5LWE1NmItNmE1YjQ3MmQ5ZGJhIiwiZXhwIjoxNjI5NzE2MDUxLCJpYXQiOjE2MjkxMTEyNTEsImlzcyI6InJvYm90LTFAcHFicy5jb20ifQ.D1jdCkOv56qn_BQaDym_Omg2LkHj7s6PjjTYpKstRS4 14 | 15 | { 16 | "user_id": "1c00da28-0c1c-42a2-bff2-b00ed5d8ac52", 17 | "project_id": "17dc1bf8-7b4d-42e8-8b53-4971aa65cf0d", 18 | "role": 1 19 | } 20 | 21 | ### 22 | GET http://localhost:9001/proj/removeAssign?assignment_id=b16d1aa9-8572-4152-871d-2a5b06c0e2f0 23 | Accept: application/json 24 | 25 | ### 26 | 27 | GET http://localhost:9001/proj/projectAssign?proj_id=12ef6101-e47f-41fe-814f-b13a922ece8d 28 | Accept: application/json 29 | 30 | ### 31 | GET http://localhost:9001/proj/userAssign?user_id=1c00da28-0c1c-42a2-bff2-b00ed5d8ac52 32 | Accept: application/json 33 | 34 | ### 35 | 36 | GET http://localhost:9001/proj/getInfo?proj_id=12ef6101-e47f-41fe-814f-b13a922ece8d 37 | Accept: application/json 38 | 39 | ### 40 | POST http://localhost:9001/proj/createEmpty 41 | Content-Type: application/json 42 | Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYzk5M2FhM2MtYWRlOS00ZDk5LWE1NmItNmE1YjQ3MmQ5ZGJhIiwiZXhwIjoxNjI5MzY0OTI0LCJpYXQiOjE2Mjg3NjAxMjQsImlzcyI6InJvYm90LTFAcHFicy5jb20ifQ.5ifVw1DyoXsxQL092qdMoShFMcvkC3qjM2ZBThiQi7s 43 | 44 | { 45 | "name": "test-project-3", 46 | "Description": "this is a no.3 test-project, which is an empty project.", 47 | "requirement": "nothing... just testing.", 48 | "target": "test create project api.", 49 | "grade_range": ["10", "12", "15"], 50 | "subjects": ["go", "html"], 51 | "summary": "speed up..." 52 | } 53 | 54 | ### 55 | -------------------------------------------------------------------------------- /proj-review/tests/user-api-test.http: -------------------------------------------------------------------------------- 1 | POST http://localhost:9001/user/checkInfo 2 | Content-Type: application/json 3 | 4 | { 5 | "phone": "13000000011", 6 | "email": "robot-5@pqbs.com" 7 | } 8 | 9 | ### 10 | POST http://localhost:9001/user/updateInfo 11 | Content-Type: application/json 12 | 13 | { 14 | "id": "c993aa3c-ade9-4d99-a56b-6a5b472d9dba", 15 | "name": "robot-01", 16 | "email": "robot-1@pqbs.com", 17 | "phone": "13000000001", 18 | "gender": false, 19 | "degree": "robot", 20 | "position": "robot-man", 21 | "employer": "developer", 22 | "major": "test" 23 | } 24 | 25 | ### 26 | GET http://localhost:9001/user/delete?user_id=c2dbc93b-f1c0-43b8-b4fc-6ecea7f52591 27 | Accept: application/json 28 | 29 | ### 30 | GET http://localhost:9001/user/getInfo?user_id=c993aa3c-ade9-4d99-a56b-6a5b472d9dba 31 | Accept: application/json 32 | 33 | ### 34 | POST http://localhost:9001/user/updatePwd 35 | Content-Type: application/json 36 | 37 | { 38 | "id": "c993aa3c-ade9-4d99-a56b-6a5b472d9dba", 39 | "old_password": "123456", 40 | "new_password": "abcdef" 41 | } 42 | 43 | 44 | ### 45 | POST http://localhost:9001/user/login 46 | Content-Type: application/json 47 | 48 | { 49 | "email": "robot-1@pqbs.com", 50 | "password": "abcdef" 51 | } 52 | 53 | ### 54 | POST http://localhost:9001/user/register 55 | Content-Type: application/json 56 | 57 | { 58 | "name": "robot-2", 59 | "password": "123456", 60 | "email": "robot-2@pqbs.com", 61 | "phone": "13000000002", 62 | "gender": false, 63 | "degree": "robot", 64 | "position": "robot-man", 65 | "employer": "developer", 66 | "major": "test" 67 | } 68 | 69 | 70 | ### 71 | POST http://localhost:9001/user/search 72 | Content-Type: application/json 73 | 74 | { 75 | "name": "robot-3", 76 | "employer": "developer", 77 | "major": "test" 78 | } -------------------------------------------------------------------------------- /proj-review/utils/gendoc.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "github.com/microcosm-cc/bluemonday" 5 | "github.com/russross/blackfriday" 6 | "io/ioutil" 7 | "os" 8 | "proj-review/log" 9 | ) 10 | 11 | func readAll(filePth string) ([]byte, error) { 12 | f, err := os.Open(filePth) 13 | if err != nil { 14 | return nil, err 15 | } 16 | return ioutil.ReadAll(f) 17 | } 18 | 19 | func markdownToHTML(md string) string { 20 | myHTMLFlags := 0 | 21 | blackfriday.HTML_USE_XHTML | 22 | blackfriday.HTML_USE_SMARTYPANTS | 23 | blackfriday.HTML_SMARTYPANTS_FRACTIONS | 24 | blackfriday.HTML_SMARTYPANTS_DASHES | 25 | blackfriday.HTML_SMARTYPANTS_LATEX_DASHES 26 | 27 | myExtensions := 0 | 28 | blackfriday.EXTENSION_NO_INTRA_EMPHASIS | 29 | blackfriday.EXTENSION_TABLES | 30 | blackfriday.EXTENSION_FENCED_CODE | 31 | blackfriday.EXTENSION_AUTOLINK | 32 | blackfriday.EXTENSION_STRIKETHROUGH | 33 | blackfriday.EXTENSION_SPACE_HEADERS | 34 | blackfriday.EXTENSION_HEADER_IDS | 35 | blackfriday.EXTENSION_BACKSLASH_LINE_BREAK | 36 | blackfriday.EXTENSION_DEFINITION_LISTS | 37 | blackfriday.EXTENSION_HARD_LINE_BREAK 38 | 39 | renderer := blackfriday.HtmlRenderer(myHTMLFlags, "", "") 40 | bytes := blackfriday.MarkdownOptions([]byte(md), renderer, blackfriday.Options{ 41 | Extensions: myExtensions, 42 | }) 43 | theHTML := string(bytes) 44 | return bluemonday.UGCPolicy().Sanitize(theHTML) 45 | } 46 | 47 | func GenApiDoc() { 48 | path := "views/api.md" 49 | res, err := readAll(path) 50 | if err != nil { 51 | log.Logger.Warn("Build API docs error: " + err.Error()) 52 | return 53 | } 54 | 55 | result := markdownToHTML(string(res)) 56 | // 写入到文件 57 | dstFile, err := os.Create("views/api.html") 58 | if err != nil { 59 | log.Logger.Warn("Build API docs error: " + err.Error()) 60 | return 61 | } 62 | defer dstFile.Close() 63 | dstFile.WriteString(result + "\n") 64 | } 65 | -------------------------------------------------------------------------------- /proj-review/utils/hash.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "crypto/sha256" 5 | "encoding/base64" 6 | ) 7 | 8 | func GenSha256(str string) string { 9 | h := sha256.New() 10 | h.Write([]byte(str)) 11 | return ConvertToBase64(h.Sum(nil)) 12 | } 13 | 14 | func ConvertToBase64(str []byte) string { 15 | enc := base64.StdEncoding.EncodeToString(str) 16 | return enc 17 | } 18 | -------------------------------------------------------------------------------- /proj-review/utils/mkdir.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | "time" 8 | ) 9 | 10 | // CreateDateDir 根据当前日期来创建文件夹 11 | func CreateDateDir(Path string) string { 12 | t := time.Now() 13 | folderDate := fmt.Sprintf("%d-%d-%d", t.Year(), t.Month(), t.Day()) 14 | folderPath := filepath.Join(Path, folderDate) 15 | if _, err := os.Stat(folderPath); os.IsNotExist(err) { 16 | // 必须分成两步:先创建文件夹、再修改权限 17 | os.MkdirAll(folderPath, os.ModePerm) //0777 18 | os.Chmod(folderPath, os.ModePerm) 19 | } 20 | return folderPath 21 | } 22 | 23 | // IsDirExists 判断所给路径文件/文件夹是否存在 24 | func IsDirExists(path string) bool { 25 | _, err := os.Stat(path) //os.Stat获取文件信息 26 | if err != nil { 27 | if os.IsExist(err) { 28 | return true 29 | } 30 | return false 31 | } 32 | return true 33 | } 34 | 35 | // IsDir 判断所给路径是否为文件夹 36 | func IsDir(path string) bool { 37 | s, err := os.Stat(path) 38 | if err != nil { 39 | return false 40 | } 41 | return s.IsDir() 42 | } 43 | 44 | // IsFile 判断所给路径是否为文件 45 | func IsFile(path string) bool { 46 | return !IsDir(path) 47 | } 48 | -------------------------------------------------------------------------------- /proj-review/utils/uuid.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import "github.com/google/uuid" 4 | 5 | /* 6 | 用于生成uuid使用, 这里使用V1(基于timestamp)和V4版本(基于随机数) 7 | */ 8 | 9 | // GenUuidV1 generate the uuid version 1 (timestamp) 10 | func GenUuidV1() (string, error) { 11 | res, err := uuid.NewUUID() 12 | if err != nil { 13 | return "", err 14 | } 15 | return res.String(), nil 16 | } 17 | 18 | // GenUuidV4 generate the uuid version 4 (random number) 19 | func GenUuidV4() string { 20 | res := uuid.New() 21 | return res.String() 22 | } 23 | -------------------------------------------------------------------------------- /proj-review/views/api.md: -------------------------------------------------------------------------------- 1 | 2 | # User 3 | - [x] [2021-8-15] /user/checkInfo:检查是否重复注册邮箱 & 手机号码; 4 | - [x] [2021-8-15] /user/register:用户注册; 5 | - [x] [2021-8-15] /user/login: 用户登录; 6 | - [x] [2021-8-15] /user/getInfo:根据id获取用户信息; 7 | - [x] [2021-8-15] /user/updateInfo:更新用户信息; 8 | - [x] [2021-8-15] /user/updatePwd:用户更新密码; 9 | - [ ] [2021-8-15] /user/resetPwd:重置密码; 10 | - [ ] [2021-] /user/logout:退出登录; 11 | - [x] [2021-8-15] /user/delete:删除用户; 12 | - [x] [2021-8-15] /user/search:搜索用户; 13 | 14 | # File 15 | - [x] [2021-8-15] /file/upload:上传文件 16 | - [x] [2021-8-15] /file/download:使用id下载文件 17 | - [x] [2021-8-15] /file/getInfo:获取文件记录信息; 18 | - [x] [2021-8-15] /file/delete:删除文件记录(不在磁盘上删除) 19 | - [x] [2021-8-15] /file/search:文件搜索; 20 | 21 | # Project 22 | - [x] [2021-8-15] /proj/createEmpty:创建空项目(创建项目管理员关联); 23 | - [ ] [2021-] /proj/createTemplate:创建模板项目(7个标准流程) 24 | - [ ] [2021-] /proj/set:设置项目信息; 25 | - [x] [2021-8-16] /proj/makeAssign:创建项目人员分配角色; 26 | - [ ] [2021-] /proj/makeGroupAssigns:批量进行人员分配; 27 | - [x] [2021-8-16] /proj/changeAssign:更改项目人员分配角色; 28 | - [ ] [2021-] /proj/removeAssign:移除某个分配记录; 29 | - [x] [2021-8-15] /proj/userAssign:获取某个用户参与的项目角色; 30 | - [x] [2021-8-15] /proj/projectAssign:获取某个项目的人员分配信息 31 | - [ ] [2021-] /proj/changeState:更改项目进度; 32 | - [ ] [2021-] /proj/dataStat:项目数据统计; 33 | - [ ] [2021-] /step/create:创建流程; 34 | - [ ] [2021-] /step/changeState:更改流程进度; 35 | - [ ] [2021-] /step/set:设置流程的信息; 36 | - [ ] [2021-] /task/create:创建任务; 37 | - [ ] [2021-] /task/changeState:更改任务进度 38 | - [ ] [2021-] /task/set:设置任务信息; 39 | - [ ] [2021-] /task/delete:删除任务 40 | - [ ] [2021-] /task/newRef:创建任务下的材料引用; 41 | - [ ] [2021-] /task/reviewRef:管理员审核任务材料; 42 | 43 | # Questions 44 | - [ ] [2021-] /question/new 45 | - [ ] [2021-] /question/import 46 | - [ ] [2021-] /question/getInfo 47 | - [ ] [2021-] /question/update 48 | - [ ] [2021-] /question/review 49 | - [ ] [2021-] /question/trace 50 | - [ ] [2021-] /question/compare 51 | - [ ] [2021-] /question/finish 52 | - [ ] [2021-] /question/search 53 | 54 | # Exam Paper 55 | - [ ] [2021-] /exam/new 56 | - [ ] [2021-] /exam/update 57 | - [ ] [2021-] /exam/review 58 | - [ ] [2021-] /exam/getInfo 59 | - [ ] [2021-] /exam/trace 60 | - [ ] [2021-] /exam/compare 61 | - [ ] [2021-] /exam/finish 62 | - [ ] [2021-] /exam/getFinal 63 | - [ ] [2021-] /exam/search 64 | -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T170925.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 2001, 3 | "message": "", 4 | "data": [ 5 | null 6 | ] 7 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T170954.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 2001, 3 | "message": "", 4 | "data": [ 5 | null 6 | ] 7 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T171040.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 2001, 3 | "message": "", 4 | "data": [ 5 | null 6 | ] 7 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T171401.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZTU5YmRjNDAtZTU1MS00MjM2LTljZjAtNzNlMmRmNmE3OGNmIiwiZXhwIjoxNjI5OTY5MjQxLCJpYXQiOjE2MjkzNjQ0NDEsImlzcyI6InJvYm90MUBvcGVuY3QuY29tIn0.F8A5BbxUHo86frL7YKqPkK0lT9rHVuKfqtWxPAkUefE", 4 | "data": [ 5 | { 6 | "name": "", 7 | "age": 0, 8 | "locaion": "", 9 | "email": "robot1@openct.com", 10 | "phone": "", 11 | "gender": false, 12 | "degree": "", 13 | "position": "", 14 | "employer": "", 15 | "major": "" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T171454.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZTU5YmRjNDAtZTU1MS00MjM2LTljZjAtNzNlMmRmNmE3OGNmIiwiZXhwIjoxNjI5OTY5Mjk0LCJpYXQiOjE2MjkzNjQ0OTQsImlzcyI6InJvYm90MUBvcGVuY3QuY29tIn0._0bGgd_Icp7FkW3K1hCWpBkeuAjHiI3Ce1BXwPG-Lvk", 4 | "data": [ 5 | { 6 | "name": "robot1", 7 | "age": 0, 8 | "locaion": "china", 9 | "email": "robot1@openct.com", 10 | "phone": "10000000001", 11 | "gender": true, 12 | "degree": "本科", 13 | "position": "developer", 14 | "employer": "openct-community", 15 | "major": "program" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T171716.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZTU5YmRjNDAtZTU1MS00MjM2LTljZjAtNzNlMmRmNmE3OGNmIiwiZXhwIjoxNjI5OTY5NDM1LCJpYXQiOjE2MjkzNjQ2MzUsImlzcyI6InJvYm90MUBvcGVuY3QuY29tIn0.qbkcF-aEjNp6Nvr-3WHiK8B-aKHc_RG9Av_xTn2PGEM", 4 | "data": [ 5 | { 6 | "Id": "611e1e4dfe69b544cb451d3e", 7 | "CreateAt": "2021-08-19T09:03:09.604Z", 8 | "UpdateAt": "2021-08-19T09:03:09.604Z", 9 | "uuid": "e59bdc40-e551-4236-9cf0-73e2df6a78cf", 10 | "profile": { 11 | "name": "robot1", 12 | "age": 0, 13 | "locaion": "china", 14 | "email": "robot1@openct.com", 15 | "phone": "10000000001", 16 | "gender": true, 17 | "degree": "本科", 18 | "position": "developer", 19 | "employer": "openct-community", 20 | "major": "program" 21 | }, 22 | "password": "", 23 | "salt": "" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T171810.404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Not Found 6 | 81 | 82 | 83 |
84 |
85 | 88 |
89 |
The page you have requested has flown the coop.
Perhaps you are here because:

90 |

    The page has moved
    The page no longer exists
    You were looking for your puppy and got lost
    You 91 | like 404 pages 92 |
93 | Go Home
94 | 95 |
Powered by beego 2.0.0 96 |
97 |
98 |
99 | 100 | 101 | -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T171820.400.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": [ 5 | "e59bdc40-e551-4236-9cf0-73e2df6a78cf" 6 | ] 7 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T171855.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 2103, 3 | "message": "", 4 | "data": [ 5 | "e59bdc40-e551-4236-9cf0-73e2df6a78cf" 6 | ] 7 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T171944.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 2103, 3 | "message": "e59bdc40-e551-4236-9cf0-73e2df6a78cf", 4 | "data": [ 5 | null 6 | ] 7 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T171957.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZTU5YmRjNDAtZTU1MS00MjM2LTljZjAtNzNlMmRmNmE3OGNmIiwiZXhwIjoxNjI5OTY5NTk2LCJpYXQiOjE2MjkzNjQ3OTYsImlzcyI6InJvYm90MUBvcGVuY3QuY29tIn0.DJhEl6SPLLO7hva1Kd4VitW0bGZoC5P3Kuhiplz22sE", 4 | "data": [ 5 | { 6 | "Id": "611e1e4dfe69b544cb451d3e", 7 | "CreateAt": "2021-08-19T09:03:09.604Z", 8 | "UpdateAt": "2021-08-19T09:03:09.604Z", 9 | "uuid": "e59bdc40-e551-4236-9cf0-73e2df6a78cf", 10 | "profile": { 11 | "name": "robot1", 12 | "age": 0, 13 | "locaion": "china", 14 | "email": "robot1@openct.com", 15 | "phone": "10000000001", 16 | "gender": true, 17 | "degree": "本科", 18 | "position": "developer", 19 | "employer": "openct-community", 20 | "major": "program" 21 | }, 22 | "password": "", 23 | "salt": "" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T172053.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": [ 5 | { 6 | "name": "robot1", 7 | "age": 0, 8 | "locaion": "china", 9 | "email": "robot1@openct.com", 10 | "phone": "10000000001", 11 | "gender": true, 12 | "degree": "本科", 13 | "position": "developer", 14 | "employer": "openct-community", 15 | "major": "program" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T172234.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": { 5 | "name": "robot1", 6 | "age": 0, 7 | "locaion": "china", 8 | "email": "robot1@openct.com", 9 | "phone": "10000000001", 10 | "gender": true, 11 | "degree": "本科", 12 | "position": "developer", 13 | "employer": "openct-community", 14 | "major": "program" 15 | } 16 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T172324.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZTU5YmRjNDAtZTU1MS00MjM2LTljZjAtNzNlMmRmNmE3OGNmIiwiZXhwIjoxNjI5OTY5ODA0LCJpYXQiOjE2MjkzNjUwMDQsImlzcyI6InJvYm90MUBvcGVuY3QuY29tIn0.AVd_2XAiSmjGN9pCuXN-jSC33Ps6qyvjPyaa1M7bdYk", 4 | "data": { 5 | "Id": "611e1e4dfe69b544cb451d3e", 6 | "CreateAt": "2021-08-19T09:03:09.604Z", 7 | "UpdateAt": "2021-08-19T09:03:09.604Z", 8 | "uuid": "e59bdc40-e551-4236-9cf0-73e2df6a78cf", 9 | "profile": { 10 | "name": "robot1", 11 | "age": 0, 12 | "locaion": "china", 13 | "email": "robot1@openct.com", 14 | "phone": "10000000001", 15 | "gender": true, 16 | "degree": "本科", 17 | "position": "developer", 18 | "employer": "openct-community", 19 | "major": "program" 20 | }, 21 | "password": "", 22 | "salt": "" 23 | } 24 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T172352.200.json: -------------------------------------------------------------------------------- 1 | "logout success" -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T172607.200.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beego application error 6 | 50 | 52 | 53 | 54 | 57 |
58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 |
Request Method:GET
Request URL:/review/user/logout
RemoteAddr:127.0.0.1
72 |
73 | Stack 74 |
C:/DevTools/golang/go_17/src/runtime/panic.go:1038
75 | C:/DevTools/golang/go_17/src/runtime/panic.go:90
76 | D:/OpenCT/OpenItem/review/controllers/user.go:156
77 | C:/DevTools/golang/go_17/src/reflect/value.go:543
78 | C:/DevTools/golang/go_17/src/reflect/value.go:339
79 | C:/Users/kkoog/go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/router.go:883
80 | C:/Users/kkoog/go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/filter.go:81
81 | C:/Users/kkoog/go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/router.go:664
82 | C:/DevTools/golang/go_17/src/net/http/server.go:2878
83 | C:/DevTools/golang/go_17/src/net/http/server.go:1929
84 | C:/DevTools/golang/go_17/src/runtime/asm_amd64.s:1581
85 | 
86 |
87 |
88 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T172629.200.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beego application error 6 | 50 | 52 | 53 | 54 | 57 |
58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 |
Request Method:GET
Request URL:/review/user/logout
RemoteAddr:127.0.0.1
72 |
73 | Stack 74 |
C:/DevTools/golang/go_17/src/runtime/panic.go:1038
75 | C:/DevTools/golang/go_17/src/runtime/panic.go:90
76 | D:/OpenCT/OpenItem/review/controllers/user.go:156
77 | C:/DevTools/golang/go_17/src/reflect/value.go:543
78 | C:/DevTools/golang/go_17/src/reflect/value.go:339
79 | C:/Users/kkoog/go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/router.go:883
80 | C:/Users/kkoog/go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/filter.go:81
81 | C:/Users/kkoog/go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/router.go:664
82 | C:/DevTools/golang/go_17/src/net/http/server.go:2878
83 | C:/DevTools/golang/go_17/src/net/http/server.go:1929
84 | C:/DevTools/golang/go_17/src/runtime/asm_amd64.s:1581
85 | 
86 |
87 |
88 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T172636.200.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beego application error 6 | 50 | 52 | 53 | 54 | 57 |
58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 |
Request Method:GET
Request URL:/review/user/logout
RemoteAddr:127.0.0.1
72 |
73 | Stack 74 |
C:/DevTools/golang/go_17/src/runtime/panic.go:1038
75 | C:/DevTools/golang/go_17/src/runtime/panic.go:90
76 | D:/OpenCT/OpenItem/review/controllers/user.go:156
77 | C:/DevTools/golang/go_17/src/reflect/value.go:543
78 | C:/DevTools/golang/go_17/src/reflect/value.go:339
79 | C:/Users/kkoog/go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/router.go:883
80 | C:/Users/kkoog/go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/filter.go:81
81 | C:/Users/kkoog/go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/router.go:664
82 | C:/DevTools/golang/go_17/src/net/http/server.go:2878
83 | C:/DevTools/golang/go_17/src/net/http/server.go:1929
84 | C:/DevTools/golang/go_17/src/runtime/asm_amd64.s:1581
85 | 
86 |
87 |
88 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T172647.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "e59bdc40-e551-4236-9cf0-73e2df6a78cf" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T172709.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "40f98bd5-e074-4951-8a56-615ed9258ce4" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T172827.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": null 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T173234.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZTU5YmRjNDAtZTU1MS00MjM2LTljZjAtNzNlMmRmNmE3OGNmIiwiZXhwIjoxNjI5OTcwMzU0LCJpYXQiOjE2MjkzNjU1NTQsImlzcyI6InJvYm90MUBvcGVuY3QuY29tIn0.cbIALnwYx2kp8uq92mLgxVtQCoAMOG9gfm5ooFGHDsA", 4 | "data": { 5 | "Id": "611e1e4dfe69b544cb451d3e", 6 | "CreateAt": "2021-08-19T09:03:09.604Z", 7 | "UpdateAt": "2021-08-19T09:03:09.604Z", 8 | "uuid": "e59bdc40-e551-4236-9cf0-73e2df6a78cf", 9 | "profile": { 10 | "name": "robot1", 11 | "age": 0, 12 | "locaion": "china", 13 | "email": "robot1@openct.com", 14 | "phone": "10000000001", 15 | "gender": true, 16 | "degree": "本科", 17 | "position": "developer", 18 | "employer": "openct-community", 19 | "major": "program" 20 | }, 21 | "password": "", 22 | "salt": "" 23 | } 24 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T173351.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 2001, 3 | "message": "", 4 | "data": "e59bdc40-e551-4236-9cf0-73e2df6a78cf" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T173453.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 2001, 3 | "message": "", 4 | "data": "e59bdc40-e551-4236-9cf0-73e2df6a78cf" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T173531.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "e59bdc40-e551-4236-9cf0-73e2df6a78cf" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T173650.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 2001, 3 | "message": "", 4 | "data": "" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-19T173745.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "e59bdc40-e551-4236-9cf0-73e2df6a78cf" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-20T173424.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": null 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-20T173441.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": null 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-20T173509.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "38509279-4363-4fa4-b3b8-f7e8cf711690" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-20T173526.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 2001, 3 | "message": "", 4 | "data": "" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-20T173545.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "93515443-dbab-42b9-bc4c-d3aedb7fa1f2" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-20T173556.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "c41d2a26-d4c7-45a8-a570-2312857ed49f" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-20T173717.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": { 5 | "name": "robot0", 6 | "age": 0, 7 | "locaion": "china", 8 | "email": "robot0@openct.com", 9 | "phone": "10000000000", 10 | "gender": true, 11 | "degree": "本科", 12 | "position": "developer", 13 | "employer": "openct-community", 14 | "major": "program" 15 | } 16 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-20T185844.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 2103, 3 | "message": "93515443-dbab-42b9-bc4c-d3aedb7fa1f2", 4 | "data": null 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-20T185859.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiOTM1MTU0NDMtZGJhYi00MmI5LWJjNGMtZDNhZWRiN2ZhMWYyIiwiZXhwIjoxNjMwMDYxOTM5LCJpYXQiOjE2Mjk0NTcxMzksImlzcyI6InJvYm90MUBvcGVuY3QuY29tIn0.c6icyTvtRUjuai-51S2PuzSj3VLDfyij-wqEV5oJnJA", 4 | "data": { 5 | "Id": "611f777182927262361ed420", 6 | "CreateAt": "2021-08-20T09:35:45.167Z", 7 | "UpdateAt": "2021-08-20T09:35:45.167Z", 8 | "uuid": "93515443-dbab-42b9-bc4c-d3aedb7fa1f2", 9 | "profile": { 10 | "name": "robot1", 11 | "age": 0, 12 | "locaion": "china", 13 | "email": "robot1@openct.com", 14 | "phone": "10000000001", 15 | "gender": true, 16 | "degree": "本科", 17 | "position": "developer", 18 | "employer": "openct-community", 19 | "major": "program" 20 | }, 21 | "password": "", 22 | "salt": "" 23 | } 24 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-23T111250.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiOTM1MTU0NDMtZGJhYi00MmI5LWJjNGMtZDNhZWRiN2ZhMWYyIiwiZXhwIjoxNjMwMjkzMTcwLCJpYXQiOjE2Mjk2ODgzNzAsImlzcyI6InJvYm90MUBvcGVuY3QuY29tIn0.9XZHK6l8Z_ZqnzL1sWsr-jqKCCDTWC2AGgTO5OeRBgc", 4 | "data": { 5 | "Id": "611f777182927262361ed420", 6 | "CreateAt": "2021-08-20T09:35:45.167Z", 7 | "UpdateAt": "2021-08-20T09:35:45.167Z", 8 | "uuid": "93515443-dbab-42b9-bc4c-d3aedb7fa1f2", 9 | "profile": { 10 | "name": "robot1", 11 | "age": 0, 12 | "locaion": "china", 13 | "email": "robot1@openct.com", 14 | "phone": "10000000001", 15 | "gender": true, 16 | "degree": "本科", 17 | "position": "developer", 18 | "employer": "openct-community", 19 | "major": "program" 20 | }, 21 | "password": "", 22 | "salt": "" 23 | } 24 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-24T085435.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "88eded2e-2fab-461b-9a43-a93d21df66c9" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-24T085452.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "c38121f9-4584-402d-8253-54d60e9e2f9b" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-24T085502.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "4cc3a021-8a9d-4d46-bd00-ad202ce1b5d1" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-24T085511.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "95e24377-9e90-4d93-895c-5fb336de0570" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-24T085520.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "741a34fb-5dd6-477d-86bc-6be475b56ee3" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-24T085529.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "31ac623c-a4f7-4b60-b18b-5d0c3d560820" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-24T085550.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "3bb8d658-eb4c-4b59-a688-5ab93be3ac30" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-24T085559.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "29f98f18-6b58-4d90-9ba8-a03820f60ab7" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-24T085607.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "e34361e9-24ed-465d-9f77-7d294c0eb48a" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-24T085622.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "", 4 | "data": "f5f9b556-6482-432c-ae47-0039068309aa" 5 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-24T092901.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiODhlZGVkMmUtMmZhYi00NjFiLTlhNDMtYTkzZDIxZGY2NmM5IiwiZXhwIjoxNjMwMzczMzQwLCJpYXQiOjE2Mjk3Njg1NDAsImlzcyI6InRlc3RtYW4tMUBvcGVuY3QuY29tIn0.EVJPeN2-1TiVaZNVwId5R0poYw_rfC5C1yAXQ0iJL5g", 4 | "data": { 5 | "Id": "6124434be55b388e3bc3072d", 6 | "CreateAt": "2021-08-24T00:54:35.655Z", 7 | "UpdateAt": "2021-08-24T00:54:35.655Z", 8 | "uuid": "88eded2e-2fab-461b-9a43-a93d21df66c9", 9 | "profile": { 10 | "name": "test-man-1", 11 | "age": 0, 12 | "locaion": "china", 13 | "email": "testman-1@openct.com", 14 | "phone": "11000000001", 15 | "gender": true, 16 | "degree": "本科", 17 | "position": "test-man", 18 | "employer": "openct-community", 19 | "major": "program" 20 | }, 21 | "password": "", 22 | "salt": "" 23 | } 24 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/2021-08-24T175026.200.json: -------------------------------------------------------------------------------- 1 | { 2 | "operation_code": 1000, 3 | "message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNGNjM2EwMjEtOGE5ZC00ZDQ2LWJkMDAtYWQyMDJjZTFiNWQxIiwiZXhwIjoxNjMwNDAzNDI2LCJpYXQiOjE2Mjk3OTg2MjYsImlzcyI6InRlc3RtYW4tM0BvcGVuY3QuY29tIn0.DToDI-F47QQq_xgXMiWSJvSqE6PY3qcdYkgYhvBxBLk", 4 | "data": { 5 | "Id": "61244366e55b388e3bc3072f", 6 | "CreateAt": "2021-08-24T00:55:02.101Z", 7 | "UpdateAt": "2021-08-24T00:55:02.101Z", 8 | "uuid": "4cc3a021-8a9d-4d46-bd00-ad202ce1b5d1", 9 | "profile": { 10 | "name": "test-man-3", 11 | "age": 0, 12 | "locaion": "china", 13 | "email": "testman-3@openct.com", 14 | "phone": "11000000003", 15 | "gender": true, 16 | "degree": "本科", 17 | "position": "test-man", 18 | "employer": "openct-community", 19 | "major": "program" 20 | }, 21 | "password": "", 22 | "salt": "" 23 | } 24 | } -------------------------------------------------------------------------------- /review/.idea/httpRequests/http-client.cookies: -------------------------------------------------------------------------------- 1 | # domain path name value date 2 | -------------------------------------------------------------------------------- /review/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /review/.idea/review.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /review/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /review/access/check.go: -------------------------------------------------------------------------------- 1 | package access 2 | -------------------------------------------------------------------------------- /review/access/cros.go: -------------------------------------------------------------------------------- 1 | package access 2 | -------------------------------------------------------------------------------- /review/access/filter.go: -------------------------------------------------------------------------------- 1 | package access 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/beego/beego/v2/server/web/context" 7 | "log" 8 | "review/logger" 9 | "review/utils" 10 | ) 11 | 12 | type FilterResponse struct { 13 | Status string `json:"status"` 14 | Msg string `json:"msg"` 15 | Data interface{} `json:"data"` 16 | } 17 | 18 | func denyRequest(ctx *context.Context, message string) { 19 | w := ctx.ResponseWriter 20 | w.WriteHeader(403) 21 | // resp := &controllers.Response{Status: "error", Msg: "Unauthorized operation"} 22 | resp := &FilterResponse{Status: "error", Msg: message} 23 | _, err := w.Write([]byte(utils.StructToJson(resp))) 24 | if err != nil { 25 | logger.Recorder.Error("filter error:" + err.Error()) 26 | } 27 | } 28 | 29 | func TokenFilter(ctx *context.Context) { 30 | method := ctx.Request.Method 31 | if method == "POST" { 32 | var requestBody map[string]interface{} 33 | json.Unmarshal(ctx.Input.RequestBody, &requestBody) 34 | logger.Recorder.Info(fmt.Sprintf("%s", requestBody)) 35 | if requestBody["token"] == nil { 36 | log.Println("deny") 37 | denyRequest(ctx, "no token") 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /review/conf/app.conf: -------------------------------------------------------------------------------- 1 | ; Basic config 2 | appname = PQBS_review_module 3 | httpaddr = localhost 4 | httpport = 9001 5 | runmode = dev 6 | copyrequestbody = true 7 | 8 | # iclude "mysql.conf" 9 | include "mongo.conf" 10 | include "file.conf" 11 | include "log.conf" 12 | include "mail.conf" -------------------------------------------------------------------------------- /review/conf/file.conf: -------------------------------------------------------------------------------- 1 | ; 用于配置文件上传 & 下载 2 | filerootpath = "static/files/" 3 | maxmemory = 1<<22 4 | -------------------------------------------------------------------------------- /review/conf/log.conf: -------------------------------------------------------------------------------- 1 | ; review module log 2 | 3 | logpath = log/ 4 | logfile = pqbs-review.log 5 | loglevel = full -------------------------------------------------------------------------------- /review/conf/mail.conf: -------------------------------------------------------------------------------- 1 | adminmail = "develop_pqbs@163.com" 2 | mailpassword = "develop_pqbs" -------------------------------------------------------------------------------- /review/conf/mongo.conf: -------------------------------------------------------------------------------- 1 | ; mongo database config 2 | mongoaddr = localhost 3 | mongoport = 27017 4 | mongodb = openct_pqbs 5 | mongouser = openct 6 | mongopwd = 123456 7 | 8 | ; collections name define 9 | [mongo-collections] 10 | ; review 11 | users = "users" 12 | assignments = "assignments" 13 | projects = "projects" 14 | steps = "steps" 15 | tasks = "tasks" 16 | fileRecords = "file_records" 17 | submits = "submits" 18 | audits = "audits" 19 | references = "references" 20 | 21 | ; warehouse 22 | tempQuestions = "temp_questions" 23 | finalQuestions = "final_questions" 24 | tempTestPapers = "temp_test_papers" 25 | finalTestPapers = "final_test_papers" -------------------------------------------------------------------------------- /review/controllers/default.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "review/access" 7 | "review/logger" 8 | ) 9 | 10 | // unmarshalBody parse the response body (json type) 11 | func unmarshalBody(body []byte, obj interface{}) error { 12 | // marshal json body 13 | if err := json.Unmarshal(body, obj); err != nil { 14 | logger.Recorder.Warn("[JSON] " + err.Error()) 15 | return err 16 | } 17 | return nil 18 | } 19 | 20 | // parseUserToken get user id from token string 21 | func parseUserToken(token string) (string, error) { 22 | // 23 | fmt.Println("recv token: ", token) 24 | // 25 | tokenData, err := access.ParseToken(token) 26 | if err != nil { 27 | return "", err 28 | } 29 | // 30 | fmt.Println("recv user: ", tokenData.UserID) 31 | fmt.Println("recv token time from ", tokenData.IssuedAt, " to ", tokenData.ExpiresAt) 32 | // 33 | return tokenData.UserID, nil 34 | } 35 | -------------------------------------------------------------------------------- /review/controllers/noticer.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | beego "github.com/beego/beego/v2/server/web" 5 | "net/http" 6 | "review/noticer" 7 | "review/response" 8 | ) 9 | 10 | type NoticerController struct { 11 | beego.Controller 12 | } 13 | 14 | func (n *NoticerController) respondJson(httpCode int, opCode int, message string, data ...interface{}) { 15 | n.Ctx.Output.SetStatus(httpCode) 16 | var d interface{} 17 | if len(data) == 1 { 18 | d = data[0] 19 | } else { 20 | d = data 21 | } 22 | resp := response.GenResponse(opCode, message, d) 23 | n.Data["json"] = resp 24 | n.ServeJSON() 25 | } 26 | 27 | // @Title SendEmail 28 | // @Description 发送邮件 29 | // @Param json body noticer.EmailPackage true "邮件内容" 30 | // @Success 200 {object} response.Default 31 | // @Failure 400 "invalid email-structure json body(token)" 32 | // @router /email [post] 33 | func (n *NoticerController) SendEmail() { 34 | var emailInfo noticer.EmailPackage 35 | err := unmarshalBody(n.Ctx.Input.RequestBody, &emailInfo) 36 | if err != nil { 37 | n.respondJson(http.StatusBadRequest, response.FAIL, "parse body (email information) failed") 38 | return 39 | } 40 | err = noticer.SendEmail(&emailInfo) 41 | if err != nil { 42 | n.respondJson(http.StatusOK, response.FAIL, "send email failed: "+err.Error()) 43 | return 44 | } 45 | n.respondJson(http.StatusOK, response.SUCCESS, "send successfully") 46 | return 47 | } 48 | -------------------------------------------------------------------------------- /review/go.mod: -------------------------------------------------------------------------------- 1 | module review 2 | 3 | go 1.17 4 | 5 | require github.com/beego/beego/v2 v2.0.1 6 | 7 | require ( 8 | github.com/astaxie/beego v1.12.3 // indirect 9 | github.com/dgrijalva/jwt-go v3.2.0+incompatible 10 | github.com/google/uuid v1.1.1 11 | github.com/qiniu/qmgo v1.0.0 12 | github.com/smartystreets/goconvey v1.6.4 13 | go.mongodb.org/mongo-driver v1.7.1 14 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 15 | gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect 16 | gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df 17 | ) 18 | -------------------------------------------------------------------------------- /review/logger/log.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "fmt" 5 | "github.com/beego/beego/v2/core/logs" 6 | beego "github.com/beego/beego/v2/server/web" 7 | ) 8 | 9 | var Recorder *logs.BeeLogger 10 | 11 | func init() { 12 | // 设置日志生成器 13 | log := logs.NewLogger() 14 | // 读取配置 15 | logPath, err := beego.AppConfig.String("logpath") 16 | if err != nil { 17 | fmt.Println("load log path config error.") 18 | } 19 | logFile, err := beego.AppConfig.String("logfile") 20 | if err != nil { 21 | fmt.Println("load log filename config error.") 22 | } 23 | // todo: more options in .conf 24 | logConfig := fmt.Sprintf( 25 | `{"filename":"%s","level":7,"daily":true,"maxdays":10,"color":true}`, 26 | logPath+logFile, 27 | ) 28 | log.SetLogger( 29 | logs.AdapterFile, 30 | logConfig, 31 | ) 32 | log.SetLogger(logs.AdapterConsole) 33 | log.EnableFuncCallDepth(true) 34 | log.SetLevel(logs.LevelDebug) 35 | 36 | Recorder = log 37 | } 38 | -------------------------------------------------------------------------------- /review/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/beego/beego/v2/server/web/filter/cors" 5 | _ "review/routers" 6 | 7 | beego "github.com/beego/beego/v2/server/web" 8 | ) 9 | 10 | func main() { 11 | if beego.BConfig.RunMode == "dev" { 12 | beego.BConfig.WebConfig.DirectoryIndex = true 13 | beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger" 14 | } 15 | 16 | // insert the filter for cross-domain 17 | beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{ 18 | //AllowAllOrigins: true, 19 | AllowMethods: []string{"*"}, 20 | //AllowHeaders: []string{"*"}, 21 | AllowHeaders: []string{"Origin", "Authorization", "Access-Control-Allow-Origin", "content-type", "token"}, 22 | ExposeHeaders: []string{"Content-Length", "Access-Control-Allow-Origin"}, 23 | AllowCredentials: true, 24 | AllowOrigins: []string{"http://49.232.73.36:8085", "http://localhost:*", "http://127.0.0.1:*"}, 25 | })) 26 | beego.Run() 27 | } 28 | -------------------------------------------------------------------------------- /review/models/audit.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/qiniu/qmgo/field" 7 | "github.com/qiniu/qmgo/options" 8 | "go.mongodb.org/mongo-driver/bson" 9 | "review/database" 10 | "review/logger" 11 | "review/request" 12 | "review/response" 13 | "review/utils" 14 | ) 15 | 16 | type Audit struct { 17 | field.DefaultField `bson:",inline"` 18 | Uuid string `json:"uuid" bson:"uuid"` 19 | SubmitContent string `json:"submit_content" bson:"submit_content"` 20 | Result int `json:"result" bson:"result"` 21 | Comment string `json:"comment" bson:"comment"` 22 | Auditor string `json:"auditor" bson:"auditor"` 23 | } 24 | 25 | // result: 0-not pass 1-pass, 2-need correct 26 | 27 | func init() { 28 | // clean old indexes 29 | database.MgoAudits.DropAllIndexes(context.Background()) 30 | err := database.MgoAudits.CreateIndexes( 31 | context.Background(), 32 | []options.IndexModel{ 33 | {Key: []string{"uuid"}, Unique: true}, 34 | {Key: []string{"uuid", "submit_content"}, Unique: true}, 35 | }, 36 | ) 37 | if err != nil { 38 | logger.Recorder.Error("[Mongo Submits] " + err.Error()) 39 | return 40 | } 41 | logger.Recorder.Info("[Mongo] Create the index in submits collection successfully") 42 | return 43 | } 44 | 45 | func GetOneAudit(auditId string) (*Audit, int) { 46 | var audit Audit 47 | err := database.MgoAudits.Find(context.Background(), bson.M{ 48 | "uuid": auditId, 49 | }).One(&audit) 50 | if err != nil { 51 | logger.Recorder.Warn("find audit info err: " + err.Error()) 52 | return nil, response.AuditGetInfoFail 53 | } 54 | return &audit, response.SUCCESS 55 | } 56 | 57 | func GetSubmitAudits(submitId string) (*[]Audit, int) { 58 | var submit Submit 59 | err := database.MgoSubmits.Find(context.Background(), bson.M{ 60 | "uuid": submitId, 61 | }).One(&submit) 62 | if err != nil { 63 | logger.Recorder.Warn("address submit info err: " + err.Error()) 64 | return nil, response.AuditGetInfoFail 65 | } 66 | var audits []Audit 67 | for _, content := range submit.Contents { 68 | var audit Audit 69 | err := database.MgoAudits.Find(context.Background(), bson.M{ 70 | "submit_content": content.Uuid, 71 | }).One(&audit) 72 | if err != nil { 73 | continue 74 | } else { 75 | audits = append(audits, audit) 76 | } 77 | } 78 | return &audits, response.SUCCESS 79 | } 80 | 81 | func MakeOneAudit(req *request.MakeOneAudit) (*Audit, int) { 82 | newAudit := Audit{ 83 | DefaultField: field.DefaultField{}, 84 | Uuid: utils.GenUuidV4(), 85 | SubmitContent: req.SubmitContentId, 86 | Result: req.Result, 87 | Comment: req.Comment, 88 | Auditor: req.UserId, 89 | } 90 | insert, err := database.MgoAudits.InsertOne(context.Background(), &newAudit) 91 | if err != nil { 92 | logger.Recorder.Warn("[mongo create new audit failed] " + err.Error()) 93 | return nil, response.AuditCreateFail 94 | } 95 | logger.Recorder.Info("[Mongo Insert] " + fmt.Sprintf("%s", insert.InsertedID)) 96 | return &newAudit, response.SUCCESS 97 | } 98 | 99 | func CorrectAudit(req *request.UpdateAudit) (*Audit, int) { 100 | err := database.MgoAudits.UpdateOne(context.Background(), bson.M{ 101 | "uuid": req.AuditId, 102 | }, bson.M{ 103 | "$set": bson.M{ 104 | "result": req.NewResult, 105 | "comment": req.NewComment, 106 | "auditor": req.NewAuditor, 107 | }, 108 | }) 109 | if err != nil { 110 | logger.Recorder.Warn("[mongo update new audit failed] " + err.Error()) 111 | return nil, response.AuditCorrectFail 112 | } 113 | var newAudit Audit 114 | database.MgoAudits.Find(context.Background(), bson.M{"uuid": req.AuditId}).One(&newAudit) 115 | return &newAudit, response.SUCCESS 116 | } 117 | 118 | func DeleteAudit(auditId string) int { 119 | // delete in audit collection 120 | err := database.MgoAudits.Remove(context.Background(), bson.M{ 121 | "uuid": auditId, 122 | }) 123 | if err != nil { 124 | return response.AuditDeleteFail 125 | } 126 | return response.SUCCESS 127 | } 128 | -------------------------------------------------------------------------------- /review/models/versionItem.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "github.com/qiniu/qmgo/field" 4 | 5 | // todo: Abstract the versioned object as a base struct. 6 | type VersionItem struct { 7 | field.DefaultField `bson:",inline"` 8 | Uuid string `bson:"uuid"` 9 | Creator string `bson:"creator"` 10 | Updater string `bson:"updater"` 11 | Base string `bson:"base"` 12 | } 13 | -------------------------------------------------------------------------------- /review/noticer/mail.go: -------------------------------------------------------------------------------- 1 | package noticer 2 | 3 | import ( 4 | "gopkg.in/gomail.v2" 5 | ) 6 | 7 | type EmailPackage struct { 8 | Destination []string `json:"destination"` 9 | Subject string `json:"subject"` 10 | Body EmailBody `json:"body"` 11 | } 12 | 13 | type EmailBody struct { 14 | Sender string `json:"sender"` 15 | SendTime string `json:"send_time"` 16 | Message string `json:"message"` 17 | } 18 | 19 | func SendEmail(email *EmailPackage) error { 20 | // 设置邮箱主体 21 | mailConn := map[string]string{ 22 | "user": "develop_pqbs@163.com", 23 | "pass": "HYZXNSQZRZTQMCUP", 24 | "host": "smtp.163.com", 25 | } 26 | 27 | m := gomail.NewMessage( 28 | //就选择utf-8格式保存 29 | gomail.SetEncoding(gomail.Base64), 30 | ) 31 | m.SetHeader("From", m.FormatAddress(mailConn["user"], email.Body.Sender)) 32 | m.SetHeader("To", email.Destination...) 33 | m.SetHeader("Subject", email.Subject) 34 | message := email.Body.Message + "\ntime: " + email.Body.SendTime 35 | m.SetBody("text/html", message) 36 | 37 | // 163 port: 25 38 | d := gomail.NewDialer(mailConn["host"], 25, mailConn["user"], mailConn["pass"]) // 设置邮件正文 39 | //d.TLSConfig = &tls.Config{InsecureSkipVerify: true} 40 | err := d.DialAndSend(m) 41 | return err 42 | } 43 | -------------------------------------------------------------------------------- /review/noticer/message.go: -------------------------------------------------------------------------------- 1 | package noticer 2 | 3 | import "github.com/qiniu/qmgo/field" 4 | 5 | // site message 6 | 7 | type SiteMessage struct { 8 | field.DefaultField `bson:",inline"` 9 | Uuid string `json:"uuid" bson:"uuid"` 10 | Sender string `json:"sender" bson:"sender"` 11 | Receivers []string `json:"receivers" bson:"receivers"` 12 | Message string `json:"message" bson:"message"` 13 | } 14 | -------------------------------------------------------------------------------- /review/query/query.go: -------------------------------------------------------------------------------- 1 | package query 2 | 3 | import ( 4 | "context" 5 | "go.mongodb.org/mongo-driver/bson" 6 | "review/database" 7 | "review/models" 8 | ) 9 | 10 | // get user list 11 | func QueryUsers(ids []string) map[string]models.User { 12 | users := make(map[string]models.User) 13 | for _, id := range ids { 14 | var u models.User 15 | err := database.MgoUsers.Find(context.Background(), bson.M{ 16 | "uuid": id, 17 | }).One(&u) 18 | if err != nil { 19 | continue 20 | } 21 | users[id] = u 22 | } 23 | return users 24 | } 25 | 26 | // get project list 27 | func QueryProjects(ids []string) map[string]models.Project { 28 | projs := make(map[string]models.Project) 29 | for _, id := range ids { 30 | var p models.Project 31 | err := database.MgoProjects.Find(context.Background(), bson.M{ 32 | "uuid": id, 33 | }).One(&p) 34 | if err != nil { 35 | continue 36 | } 37 | projs[id] = p 38 | } 39 | return projs 40 | } 41 | 42 | // get assignment list 43 | func QueryAssignments(ids []string) map[string]models.Assignment { 44 | assigns := make(map[string]models.Assignment) 45 | for _, id := range ids { 46 | var a models.Assignment 47 | err := database.MgoAssignments.Find(context.Background(), bson.M{ 48 | "uuid": id, 49 | }).One(&a) 50 | if err != nil { 51 | continue 52 | } 53 | assigns[id] = a 54 | } 55 | return assigns 56 | } 57 | 58 | // get file list 59 | func QueryFiles(ids []string) map[string]models.FileItem { 60 | files := make(map[string]models.FileItem) 61 | for _, id := range ids { 62 | var p models.FileItem 63 | err := database.MgoFileRecords.Find(context.Background(), bson.M{ 64 | "uuid": id, 65 | }).One(&p) 66 | if err != nil { 67 | continue 68 | } 69 | files[id] = p 70 | } 71 | return files 72 | } 73 | 74 | // get step list 75 | func QuerySteps(ids []string) map[string]models.Step { 76 | steps := make(map[string]models.Step) 77 | for _, id := range ids { 78 | var p models.Step 79 | err := database.MgoSteps.Find(context.Background(), bson.M{ 80 | "uuid": id, 81 | }).One(&p) 82 | if err != nil { 83 | continue 84 | } 85 | steps[id] = p 86 | } 87 | return steps 88 | } 89 | 90 | // get submit list 91 | func QuerySubmits(ids []string) map[string]models.Submit { 92 | submits := make(map[string]models.Submit) 93 | for _, id := range ids { 94 | var s models.Submit 95 | err := database.MgoSubmits.Find(context.Background(), bson.M{ 96 | "uuid": id, 97 | }).One(&s) 98 | if err != nil { 99 | continue 100 | } 101 | submits[id] = s 102 | } 103 | return submits 104 | } 105 | 106 | // get audit list 107 | func QueryAudits(ids []string) map[string]models.Audit { 108 | audits := make(map[string]models.Audit) 109 | for _, id := range ids { 110 | var a models.Audit 111 | err := database.MgoAudits.Find(context.Background(), bson.M{ 112 | "uuid": id, 113 | }).One(&a) 114 | if err != nil { 115 | continue 116 | } 117 | audits[id] = a 118 | } 119 | return audits 120 | } 121 | -------------------------------------------------------------------------------- /review/request/file.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | /* 4 | Define some request structures for file operations. 5 | */ 6 | 7 | // UploadFile define the upload file request format 8 | type UploadFile struct { 9 | UserId string `json:"user_id"` 10 | FileName string `json:"file_name"` 11 | Type string `json:"type"` 12 | SourceProject string `json:"source_project"` 13 | Description string `json:"description"` 14 | Tags []string `json:"tags"` 15 | } 16 | 17 | // UpdateFile: define the struct for update a file version 18 | type UpdateFile struct { 19 | UserId string `json:"user_id"` 20 | BaseFile string `json:"base_file" bson:"base_file"` 21 | FileName string `json:"file_name"` 22 | Type string `json:"type"` 23 | Description string `json:"description"` 24 | Tags []string `json:"tags"` 25 | } 26 | 27 | // SearchFile define the search request format, todo 28 | type SearchFile struct { 29 | FileName string `json:"file_name"` 30 | Type string `json:"type"` 31 | Tags []string `json:"tags"` 32 | } 33 | 34 | // GetFileInfo: just using http-get with url params 35 | // DownloadFile: just using http-get with url params 36 | -------------------------------------------------------------------------------- /review/request/user.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | //UserLogin define the user login struct 4 | type UserLogin struct { 5 | Phone string `json:"phone"` 6 | Email string `json:"email"` 7 | Password string `json:"password"` 8 | } 9 | 10 | // UserRegister defines create user request format 11 | type UserRegister struct { 12 | Name string `json:"name"` 13 | Password string `json:"password"` 14 | Location string `json:"location"` 15 | Email string `json:"email"` 16 | Phone string `json:"phone"` 17 | Gender bool `json:"gender"` 18 | Degree string `json:"degree"` 19 | Position string `json:"position"` 20 | Employer string `json:"employer"` 21 | Major string `json:"major"` 22 | } 23 | 24 | // UserUpdatePassword define the update password req format 请求更新密码 25 | type UserUpdatePassword struct { 26 | ID string `json:"id"` 27 | OldPassword string `json:"old_password"` 28 | NewPassword string `json:"new_password"` 29 | } 30 | 31 | // UserUpdateInfo define the user info updating request format 32 | type UserUpdateInfo struct { 33 | ID string `json:"id"` 34 | Name string `json:"name"` 35 | Email string `json:"email"` 36 | Phone string `json:"phone"` 37 | Gender bool `json:"gender"` 38 | Location string `json:"location"` 39 | Degree string `json:"degree"` 40 | Position string `json:"position"` 41 | Employer string `json:"employer"` 42 | Major string `json:"major"` 43 | } 44 | 45 | // UserSearch define search users struct 46 | type UserSearch struct { 47 | Phone string `json:"phone"` 48 | Email string `json:"email"` 49 | Name string `json:"name"` 50 | Degree string `json:"degree"` 51 | Position string `json:"position"` 52 | Employer string `json:"employer"` 53 | Major string `json:"major"` 54 | } 55 | 56 | // GetUserInfo: just using http-get with url params 57 | // UserLogout: just using http-get with url params 58 | -------------------------------------------------------------------------------- /review/response/code.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | var ( 4 | SUCCESS = 1000 // operation exec successfully 5 | 6 | FAIL = 2000 // operation exec failed with default error 7 | 8 | // Database operations (mongodb) 9 | DatabaseDefaultError = 2001 10 | DatabaseInsertError = 2002 11 | DatabaseUpdateError = 2003 12 | DatabaseDeleteError = 2004 13 | DatabaseNoRecord = 2005 14 | DatabaseUniqueKeyDuplicate = 2006 15 | 16 | // user operations 17 | UserRegisterFail = 2100 18 | UserRegisterPasswordError = 2101 19 | UserLoginFail = 2102 20 | UserAuthError = 2103 21 | UserNotExist = 2104 22 | UserGenerateTokenError = 2105 23 | UserUpdatePasswordError = 2106 24 | 25 | // file operations 26 | FileUploadFail = 2200 27 | FileGetFileFail = 2201 28 | FileDownloadFileFail = 2202 29 | 30 | // project operations 31 | ProjectCreateFail = 2301 32 | ProjectNotExist = 2302 33 | ProjectGetInfoFail = 2303 34 | ProjectUpdateFail = 2304 35 | 36 | // project-assignment operations 37 | AssignmentCreateFail = 2310 38 | AssignmentUserGetFail = 2311 39 | AssignmentProjectGetFail = 2312 40 | AssignmentChangeFail = 2313 41 | AssignmentDeleteFail = 2314 42 | AssignConfirmFail = 2315 43 | 44 | // project-step operations 45 | StepCreateFail = 2320 46 | StepAddAttachmentsFail = 2321 47 | StepUpdateInfoFail = 2322 48 | StepChangeStatusFail = 2323 49 | StepGetInfoFail = 2324 50 | StepSetTimePointFail = 2325 51 | StepDeleteTimePointFail = 2326 52 | StepDeleteFail = 2327 53 | StepGetStatisticFail = 2328 54 | 55 | // project-submit operations 56 | SubmitGetInfoFail = 2330 57 | SubmitCreateFail = 2331 58 | SubmitUpdateFail = 2332 59 | SubmitWithdrawFail = 2333 60 | SubmitDeleteFail = 2334 61 | 62 | // project-audit operations 63 | AuditGetInfoFail = 2340 64 | AuditCreateFail = 2341 65 | AuditCorrectFail = 2342 66 | AuditDeleteFail = 2343 67 | ) 68 | -------------------------------------------------------------------------------- /review/response/default.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | type Default struct { 4 | OperationCode int `json:"operation_code"` 5 | Message string `json:"message"` 6 | Data interface{} `json:"data"` 7 | } 8 | 9 | func GenResponse(opCode int, message string, data interface{}) Default { 10 | return Default{ 11 | OperationCode: opCode, 12 | Message: message, 13 | Data: data, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /review/response/listquery.go: -------------------------------------------------------------------------------- 1 | package response 2 | -------------------------------------------------------------------------------- /review/routers/router.go: -------------------------------------------------------------------------------- 1 | // @APIVersion 1.0.0 2 | // @Title OpenCT PQBS - api document 3 | // @Description beego has a very cool tools to autogenerate documents for your API 4 | // @Contact kkoogqw@hotmail.com 5 | // @TermsOfServiceUrl http:// 6 | // @License Apache 2.0 7 | // @LicenseUrl http://www.apache.org/licenses/LICENSE-2.0.html 8 | package routers 9 | 10 | import ( 11 | "review/controllers" 12 | 13 | beego "github.com/beego/beego/v2/server/web" 14 | ) 15 | 16 | func init() { 17 | ns := beego.NewNamespace("/review", 18 | beego.NSNamespace("/user", 19 | beego.NSInclude( 20 | &controllers.UserController{}, 21 | ), 22 | ), 23 | beego.NSNamespace("/file", 24 | beego.NSInclude( 25 | &controllers.FileController{}, 26 | ), 27 | ), 28 | beego.NSNamespace("/proj", 29 | beego.NSInclude( 30 | &controllers.ProjectController{}, 31 | ), 32 | ), 33 | beego.NSNamespace("/query", 34 | beego.NSInclude( 35 | &controllers.QueryController{}, 36 | ), 37 | ), 38 | beego.NSNamespace("/noticer", 39 | beego.NSInclude( 40 | &controllers.NoticerController{}, 41 | ), 42 | ), 43 | ) 44 | beego.AddNamespace(ns) 45 | } 46 | -------------------------------------------------------------------------------- /review/swagger.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/review/swagger.zip -------------------------------------------------------------------------------- /review/swagger/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/review/swagger/favicon-16x16.png -------------------------------------------------------------------------------- /review/swagger/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/review/swagger/favicon-32x32.png -------------------------------------------------------------------------------- /review/swagger/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Swagger UI 7 | 8 | 9 | 10 | 11 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
69 | 70 | 71 | 72 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /review/swagger/oauth2-redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 54 | -------------------------------------------------------------------------------- /review/swagger/swagger-ui-bundle.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA6+FA;;;;;;;;;;;;;;;;;;;;;;;;;;AAyTA;;;;;;AAoIA;AAi7FA;AAmtCA;AAi0IA;AA0oJA;AAgwFA;AAyrGA;AA0lFA;AA4nFA;AA+9CA;AA+gDA;AAwrCA;AA60EA;;;;;AA6oCA;AAsyJA;;;;;;;;;;;;;;AA64EA;AA4mIA;AAquJA;AA2qHA;AA2mGA;AAiiEA;AAq4DA;AAg3DA;AAoPA;;;;;;AAk7FA;AA07FA;;;;;AAi8CA;AAgsFA;AAs2CA;AAglCA;AAu9CA;AAy8EA;AAsiCA;AA+yFA;;;;;;;;;AAgkDA;AA2zIA;AAu7FA;AAmrFA;AAu0EA","sourceRoot":""} -------------------------------------------------------------------------------- /review/swagger/swagger-ui-standalone-preset.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AA8QA;AAmvGA;AAuxFA;;;;;;AAocA;AAkvFA;AAu+CA;AAo+CA;AAgrCA;AAuyEA","sourceRoot":""} -------------------------------------------------------------------------------- /review/swagger/swagger-ui.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui.css","sources":[],"mappings":"","sourceRoot":""} -------------------------------------------------------------------------------- /review/swagger/swagger-ui.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AA0yCA;AAoyHA;AAmyHA;AAykGA;AA+9BA;AA6iCA;AAojCA;AAu5BA","sourceRoot":""} -------------------------------------------------------------------------------- /review/tests/default_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "path/filepath" 7 | _ "review/routers" 8 | "runtime" 9 | "testing" 10 | 11 | "github.com/beego/beego/v2/core/logs" 12 | beego "github.com/beego/beego/v2/server/web" 13 | . "github.com/smartystreets/goconvey/convey" 14 | ) 15 | 16 | func init() { 17 | _, file, _, _ := runtime.Caller(0) 18 | apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator)))) 19 | beego.TestBeegoInit(apppath) 20 | } 21 | 22 | // TestGet is a sample to run an endpoint test 23 | func TestGet(t *testing.T) { 24 | r, _ := http.NewRequest("GET", "/v1/object", nil) 25 | w := httptest.NewRecorder() 26 | beego.BeeApp.Handlers.ServeHTTP(w, r) 27 | 28 | logs.Info("testing", "TestGet", "Code[%d]\n%s", w.Code, w.Body.String()) 29 | 30 | Convey("Subject: Test Station Endpoint\n", t, func() { 31 | Convey("Status Code Should Be 200", func() { 32 | So(w.Code, ShouldEqual, 200) 33 | }) 34 | Convey("The Result Should Not Be Empty", func() { 35 | So(w.Body.Len(), ShouldBeGreaterThan, 0) 36 | }) 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /review/tests/file-test.http: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/review/tests/file-test.http -------------------------------------------------------------------------------- /review/tests/user-test.http: -------------------------------------------------------------------------------- 1 | PUT http://127.0.0.1:9001/review/user/ 2 | Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZTU5YmRjNDAtZTU1MS00MjM2LTljZjAtNzNlMmRmNmE3OGNmIiwiZXhwIjoxNjI5OTY5ODA0LCJpYXQiOjE2MjkzNjUwMDQsImlzcyI6InJvYm90MUBvcGVuY3QuY29tIn0.AVd_2XAiSmjGN9pCuXN-jSC33Ps6qyvjPyaa1M7bdYk 3 | Content-Type: application/json 4 | 5 | { 6 | "id": "e59bdc40-e551-4236-9cf0-73e2df6a78cf", 7 | "degree": "本科", 8 | "email": "robot1@openct.com", 9 | "employer": "openct-community", 10 | "gender": true, 11 | "location": "china", 12 | "major": "program", 13 | "name": "robot1", 14 | "phone": "10000000001", 15 | "position": "developer" 16 | } 17 | 18 | ### 19 | DELETE http://127.0.0.1:9001/review/user/75ea985b-c9c8-43da-94d0-d3b22f461838 20 | Accept: application/json 21 | 22 | 23 | ### 24 | GET http://127.0.0.1:9001/review/user/logout 25 | Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZTU5YmRjNDAtZTU1MS00MjM2LTljZjAtNzNlMmRmNmE3OGNmIiwiZXhwIjoxNjI5OTY5ODA0LCJpYXQiOjE2MjkzNjUwMDQsImlzcyI6InJvYm90MUBvcGVuY3QuY29tIn0.AVd_2XAiSmjGN9pCuXN-jSC33Ps6qyvjPyaa1M7bdYk 26 | Accept: application/json 27 | 28 | ### 29 | GET http://127.0.0.1:9001/review/user/38509279-4363-4fa4-b3b8-f7e8cf711690 30 | Accept: application/json 31 | 32 | ### 33 | PUT http://127.0.0.1:9001/review/user/password 34 | Content-Type: application/json 35 | 36 | { 37 | "id": "e59bdc40-e551-4236-9cf0-73e2df6a78cf", 38 | "new_password": "abcdef", 39 | "old_password": "123456" 40 | } 41 | 42 | ### 43 | POST http://127.0.0.1:9001/review/user/login 44 | Content-Type: application/json 45 | 46 | { 47 | "email": "testman-3@openct.com", 48 | "password": "123456" 49 | } 50 | 51 | ### 52 | POST http://127.0.0.1:9001/review/user 53 | Content-Type: application/json 54 | 55 | { 56 | "degree": "本科", 57 | "email": "testman-0@openct.com", 58 | "employer": "openct-community", 59 | "gender": true, 60 | "location": "china", 61 | "major": "program", 62 | "name": "test-man-0", 63 | "password": "123456", 64 | "phone": "11000000000", 65 | "position": "test-man" 66 | } 67 | 68 | ### 69 | -------------------------------------------------------------------------------- /review/utils/crypto.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "crypto/sha256" 5 | "encoding/base64" 6 | ) 7 | 8 | func GenSha256(str string) string { 9 | h := sha256.New() 10 | h.Write([]byte(str)) 11 | return ConvertToBase64(h.Sum(nil)) 12 | } 13 | 14 | func ConvertToBase64(str []byte) string { 15 | enc := base64.StdEncoding.EncodeToString(str) 16 | return enc 17 | } 18 | -------------------------------------------------------------------------------- /review/utils/json.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "encoding/json" 5 | "review/logger" 6 | ) 7 | 8 | func StructToJson(v interface{}) string { 9 | //data, err := json.MarshalIndent(v, "", " ") 10 | data, err := json.Marshal(v) 11 | if err != nil { 12 | logger.Recorder.Error("convert struct to json error: " + err.Error()) 13 | } 14 | return string(data) 15 | } 16 | 17 | func JsonToStruct(data string, v interface{}) error { 18 | return json.Unmarshal([]byte(data), v) 19 | } 20 | -------------------------------------------------------------------------------- /review/utils/mkdir.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | "time" 8 | ) 9 | 10 | // CreateDateDir 根据当前日期来创建文件夹 11 | func CreateDateDir(Path string) string { 12 | t := time.Now() 13 | folderDate := fmt.Sprintf("%d-%d-%d", t.Year(), t.Month(), t.Day()) 14 | folderPath := filepath.Join(Path, folderDate) 15 | if _, err := os.Stat(folderPath); os.IsNotExist(err) { 16 | // 必须分成两步:先创建文件夹、再修改权限 17 | os.MkdirAll(folderPath, os.ModePerm) //0777 18 | os.Chmod(folderPath, os.ModePerm) 19 | } 20 | return folderPath 21 | } 22 | 23 | // IsDirExists 判断所给路径文件/文件夹是否存在 24 | func IsDirExists(path string) bool { 25 | _, err := os.Stat(path) //os.Stat获取文件信息 26 | if err != nil { 27 | if os.IsExist(err) { 28 | return true 29 | } 30 | return false 31 | } 32 | return true 33 | } 34 | 35 | // IsDir 判断所给路径是否为文件夹 36 | func IsDir(path string) bool { 37 | s, err := os.Stat(path) 38 | if err != nil { 39 | return false 40 | } 41 | return s.IsDir() 42 | } 43 | 44 | // IsFile 判断所给路径是否为文件 45 | func IsFile(path string) bool { 46 | return !IsDir(path) 47 | } 48 | -------------------------------------------------------------------------------- /review/utils/uuid.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import "github.com/google/uuid" 4 | 5 | /* 6 | 用于生成uuid使用, 这里使用V1(基于timestamp)和V4版本(基于随机数) 7 | */ 8 | 9 | // GenUuidV1 generate the uuid version 1 (timestamp) 10 | func GenUuidV1() (string, error) { 11 | res, err := uuid.NewUUID() 12 | if err != nil { 13 | return "", err 14 | } 15 | return res.String(), nil 16 | } 17 | 18 | // GenUuidV4 generate the uuid version 4 (random number) 19 | func GenUuidV4() string { 20 | res := uuid.New() 21 | return res.String() 22 | } 23 | -------------------------------------------------------------------------------- /warehouse/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /warehouse/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /warehouse/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /warehouse/.idea/warehouse.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /warehouse/conf/app.conf: -------------------------------------------------------------------------------- 1 | appname = question-warehouse 2 | httpaddr = localhost 3 | httpport = 9002 4 | runmode = dev 5 | autorender = false 6 | copyrequestbody = true 7 | EnableDocs = true 8 | 9 | include "mongo.conf" 10 | include "log.conf" -------------------------------------------------------------------------------- /warehouse/conf/log.conf: -------------------------------------------------------------------------------- 1 | ; review module log 2 | logpath = log/ 3 | logfile = qbank.log 4 | loglevel = full -------------------------------------------------------------------------------- /warehouse/conf/mongo.conf: -------------------------------------------------------------------------------- 1 | ; mongo database config 2 | mongoaddr = localhost 3 | mongoport = 27017 4 | mongodb = openct_pqbs 5 | mongouser = openct 6 | mongopwd = 123456 7 | 8 | ; collections name define 9 | [mongo-collections] 10 | ; collections name define 11 | tempQuestions = "temp_questions" 12 | finalQuestions = "final_questions" 13 | tempTestPapers = "temp_test_papers" 14 | finalTestPapers = "final_test_papers" -------------------------------------------------------------------------------- /warehouse/controllers/default.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "warehouse/logger" 6 | ) 7 | 8 | func unmarshalBody(body []byte, obj interface{}) error { 9 | // marshal json body 10 | if err := json.Unmarshal(body, obj); err != nil { 11 | logger.Recorder.Warn("[JSON] " + err.Error()) 12 | return err 13 | } 14 | return nil 15 | } 16 | -------------------------------------------------------------------------------- /warehouse/controllers/user.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "warehouse/models" 6 | 7 | beego "github.com/beego/beego/v2/server/web" 8 | ) 9 | 10 | // Operations about Users 11 | type UserController struct { 12 | beego.Controller 13 | } 14 | 15 | // @Title CreateUser 16 | // @Description create users 17 | // @Param body body models.User true "body for user content" 18 | // @Success 200 {int} models.User.Id 19 | // @Failure 403 body is empty 20 | // @router / [post] 21 | func (u *UserController) Post() { 22 | var user models.User 23 | json.Unmarshal(u.Ctx.Input.RequestBody, &user) 24 | uid := models.AddUser(user) 25 | u.Data["json"] = map[string]string{"uid": uid} 26 | u.ServeJSON() 27 | } 28 | 29 | // @Title GetAll 30 | // @Description get all Users 31 | // @Success 200 {object} models.User 32 | // @router / [get] 33 | func (u *UserController) GetAll() { 34 | users := models.GetAllUsers() 35 | u.Data["json"] = users 36 | u.ServeJSON() 37 | } 38 | 39 | // @Title Get 40 | // @Description get user by uid 41 | // @Param uid path string true "The key for staticblock" 42 | // @Success 200 {object} models.User 43 | // @Failure 403 :uid is empty 44 | // @router /:uid [get] 45 | func (u *UserController) Get() { 46 | uid := u.GetString(":uid") 47 | if uid != "" { 48 | user, err := models.GetUser(uid) 49 | if err != nil { 50 | u.Data["json"] = err.Error() 51 | } else { 52 | u.Data["json"] = user 53 | } 54 | } 55 | u.ServeJSON() 56 | } 57 | 58 | // @Title Update 59 | // @Description update the user 60 | // @Param uid path string true "The uid you want to update" 61 | // @Param body body models.User true "body for user content" 62 | // @Success 200 {object} models.User 63 | // @Failure 403 :uid is not int 64 | // @router /:uid [put] 65 | func (u *UserController) Put() { 66 | uid := u.GetString(":uid") 67 | if uid != "" { 68 | var user models.User 69 | json.Unmarshal(u.Ctx.Input.RequestBody, &user) 70 | uu, err := models.UpdateUser(uid, &user) 71 | if err != nil { 72 | u.Data["json"] = err.Error() 73 | } else { 74 | u.Data["json"] = uu 75 | } 76 | } 77 | u.ServeJSON() 78 | } 79 | 80 | // @Title Delete 81 | // @Description delete the user 82 | // @Param uid path string true "The uid you want to delete" 83 | // @Success 200 {string} delete success! 84 | // @Failure 403 uid is empty 85 | // @router /:uid [delete] 86 | func (u *UserController) Delete() { 87 | uid := u.GetString(":uid") 88 | models.DeleteUser(uid) 89 | u.Data["json"] = "delete success!" 90 | u.ServeJSON() 91 | } 92 | 93 | // @Title Login 94 | // @Description Logs user into the system 95 | // @Param username query string true "The username for login" 96 | // @Param password query string true "The password for login" 97 | // @Success 200 {string} login success 98 | // @Failure 403 user not exist 99 | // @router /login [get] 100 | func (u *UserController) Login() { 101 | username := u.GetString("username") 102 | password := u.GetString("password") 103 | if models.Login(username, password) { 104 | u.Data["json"] = "login success" 105 | } else { 106 | u.Data["json"] = "user not exist" 107 | } 108 | u.ServeJSON() 109 | } 110 | 111 | // @Title logout 112 | // @Description Logs out current logged in user session 113 | // @Success 200 {string} logout success 114 | // @router /logout [get] 115 | func (u *UserController) Logout() { 116 | u.Data["json"] = "logout success" 117 | u.ServeJSON() 118 | } 119 | -------------------------------------------------------------------------------- /warehouse/go.mod: -------------------------------------------------------------------------------- 1 | module warehouse 2 | 3 | go 1.15 4 | 5 | require github.com/beego/beego/v2 v2.0.1 6 | 7 | require ( 8 | github.com/astaxie/beego v1.12.3 // indirect 9 | github.com/golang/protobuf v1.5.2 // indirect 10 | github.com/google/uuid v1.3.0 11 | github.com/mitchellh/mapstructure v1.4.1 // indirect 12 | github.com/qiniu/qmgo v1.0.3 13 | github.com/smartystreets/goconvey v1.6.4 14 | github.com/stretchr/testify v1.7.0 // indirect 15 | go.mongodb.org/mongo-driver v1.7.2 16 | golang.org/x/sys v0.0.0-20210903071746-97244b99971b // indirect 17 | golang.org/x/text v0.3.7 // indirect 18 | golang.org/x/tools v0.1.2 // indirect 19 | gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect 20 | gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 21 | gopkg.in/yaml.v2 v2.4.0 // indirect 22 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 23 | ) 24 | -------------------------------------------------------------------------------- /warehouse/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "fmt" 5 | "github.com/beego/beego/v2/core/logs" 6 | beego "github.com/beego/beego/v2/server/web" 7 | ) 8 | 9 | var Recorder *logs.BeeLogger 10 | 11 | func init() { 12 | // 设置日志生成器 13 | log := logs.NewLogger() 14 | // 读取配置 15 | logPath, err := beego.AppConfig.String("logpath") 16 | if err != nil { 17 | fmt.Println("load log path config error.") 18 | } 19 | logFile, err := beego.AppConfig.String("logfile") 20 | if err != nil { 21 | fmt.Println("load log filename config error.") 22 | } 23 | // todo: more options in .conf 24 | logConfig := fmt.Sprintf( 25 | `{"filename":"%s","level":7,"daily":true,"maxdays":10,"color":true}`, 26 | logPath+logFile, 27 | ) 28 | log.SetLogger( 29 | logs.AdapterFile, 30 | logConfig, 31 | ) 32 | log.SetLogger(logs.AdapterConsole) 33 | log.EnableFuncCallDepth(true) 34 | log.SetLevel(logs.LevelDebug) 35 | 36 | Recorder = log 37 | } 38 | -------------------------------------------------------------------------------- /warehouse/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | beego "github.com/beego/beego/v2/server/web" 5 | "github.com/beego/beego/v2/server/web/filter/cors" 6 | _ "warehouse/logger" 7 | _ "warehouse/models" 8 | _ "warehouse/routers" 9 | ) 10 | 11 | func main() { 12 | if beego.BConfig.RunMode == "dev" { 13 | beego.BConfig.WebConfig.DirectoryIndex = true 14 | beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger" 15 | } 16 | 17 | // insert the filter for cross-domain 18 | beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{ 19 | //AllowAllOrigins: true, 20 | AllowMethods: []string{"*"}, 21 | //AllowHeaders: []string{"*"}, 22 | AllowHeaders: []string{"Origin", "Authorization", "Access-Control-Allow-Origin", "content-type", "token"}, 23 | ExposeHeaders: []string{"Content-Length", "Access-Control-Allow-Origin"}, 24 | AllowCredentials: true, 25 | AllowOrigins: []string{"http://49.232.73.36:8085", "http://localhost:*", "http://127.0.0.1:*"}, 26 | })) 27 | beego.Run() 28 | } 29 | -------------------------------------------------------------------------------- /warehouse/models/query.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "context" 5 | "gopkg.in/mgo.v2/bson" 6 | "warehouse/database" 7 | "warehouse/logger" 8 | ) 9 | 10 | // 进行批量查询的方法 11 | func QueryTempQuestions(idList []string) map[string]TempQuestion { 12 | questionsMap := make(map[string]TempQuestion) 13 | for _, id := range idList { 14 | var question TempQuestion 15 | err := database.MgoTempQuestions.Find( 16 | context.Background(), 17 | bson.M{ 18 | "uuid": id, 19 | }, 20 | ).One(&question) 21 | if err != nil { 22 | logger.Recorder.Error("get temp-question error: [" + id + "]" + err.Error()) 23 | continue 24 | } 25 | questionsMap[id] = question 26 | } 27 | return questionsMap 28 | } 29 | 30 | func QueryFinalQuestions(idList []string) map[string]FinalQuestion { 31 | questionsMap := make(map[string]FinalQuestion) 32 | for _, id := range idList { 33 | var question FinalQuestion 34 | err := database.MgoFinalQuestions.Find( 35 | context.Background(), 36 | bson.M{ 37 | "uuid": id, 38 | }, 39 | ).One(&question) 40 | if err != nil { 41 | logger.Recorder.Error("get final-question error: [" + id + "]" + err.Error()) 42 | continue 43 | } 44 | questionsMap[id] = question 45 | } 46 | return questionsMap 47 | } 48 | 49 | func QueryTempTestpaper(idList []string) map[string]TempTestpaper { 50 | testpaperMap := make(map[string]TempTestpaper) 51 | for _, id := range idList { 52 | var testPaper TempTestpaper 53 | err := database.MgoTempTestPaper.Find( 54 | context.Background(), 55 | bson.M{ 56 | "uuid": id, 57 | }, 58 | ).One(&testPaper) 59 | if err != nil { 60 | logger.Recorder.Error("get final-test-paper error: [" + id + "]" + err.Error()) 61 | continue 62 | } 63 | testpaperMap[id] = testPaper 64 | } 65 | return testpaperMap 66 | } 67 | 68 | func QueryFinalTestpaper(idList []string) map[string]FinalTestpaper { 69 | testpaperMap := make(map[string]FinalTestpaper) 70 | for _, id := range idList { 71 | var testPaper FinalTestpaper 72 | err := database.MgoFinalTestPaper.Find( 73 | context.Background(), 74 | bson.M{ 75 | "uuid": id, 76 | }, 77 | ).One(&testPaper) 78 | if err != nil { 79 | logger.Recorder.Error("get final-test-paper error: [" + id + "]" + err.Error()) 80 | continue 81 | } 82 | testpaperMap[id] = testPaper 83 | } 84 | return testpaperMap 85 | } 86 | -------------------------------------------------------------------------------- /warehouse/models/request.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type QueryListRequest struct { 4 | IdList []string `json:"id_list"` 5 | } 6 | 7 | // Questions 8 | type NewQuestionRequest struct { 9 | SourceProject string `json:"source_project"` 10 | Author string `json:"author"` 11 | Info QuestionInfo `json:"info"` 12 | BasicProps QuestionBasicProps `json:"basic_props"` 13 | SpecProps QuestionSpecProps `json:"spec_props"` 14 | ExtraProps QuestionExtraProps `json:"extra_props"` 15 | AdvancedProps QuestionAdvancedProps `json:"advanced_props"` 16 | ApplyRecord QuestionApplyRecord `json:"apply_record"` 17 | } 18 | 19 | type UpdateQuestionRequest struct { 20 | BaseQuestion string `json:"base_question"` 21 | Author string `json:"author"` 22 | NewInfo QuestionInfo `json:"new_info"` 23 | NewBasicProps QuestionBasicProps `json:"new_basic_props"` 24 | NewSpecProps QuestionSpecProps `json:"new_spec_props"` 25 | NewExtraProps QuestionExtraProps `json:"new_extra_props"` 26 | NewAdvancedProps QuestionAdvancedProps `json:"new_advanced_props"` 27 | NewApplyRecord QuestionApplyRecord `json:"new_apply_record"` 28 | } 29 | 30 | type AddQuestionCommentRequest struct { 31 | QuestionId string `json:"question_id"` 32 | Comment string `json:"comment"` 33 | Author string `json:"'author'"` 34 | } 35 | 36 | // Testpaper 37 | type NewTestpaperRequest struct { 38 | SourceProject string `json:"source_project"` 39 | Author string `json:"author"` 40 | Title string `json:"title"` 41 | Info []TestpaperPart `json:"info"` 42 | Props TestpaperProps `json:"props"` 43 | } 44 | 45 | type UpdateTestpaperRequest struct { 46 | BaseTestpaper string `json:"base_testpaper"` 47 | Author string `json:"author"` 48 | NewTitle string `json:"new_title"` 49 | NewInfo []TestpaperPart `json:"new_info"` 50 | NewProps TestpaperProps `json:"new_props"` 51 | } 52 | 53 | type AddTestpaperCommentRequest struct { 54 | TestpaperId string `json:"testpaper_id"` 55 | Comment string `json:"comment"` 56 | Author string `json:"author"` 57 | } 58 | -------------------------------------------------------------------------------- /warehouse/models/testpaper.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/qiniu/qmgo/field" 5 | "time" 6 | ) 7 | 8 | type QuestionItem struct { 9 | QuestionId string `json:"question_id" bson:"question_id"` 10 | Score int `json:"score" bson:"score"` 11 | Comment string `json:"comment" bson:"comment"` 12 | } 13 | 14 | type TestpaperPart struct { 15 | Title string `json:"title" bson:"title"` 16 | Description string `json:"description" bson:"description"` 17 | QuestionList []QuestionItem `json:"question_list" bson:"question_list"` 18 | Score int `json:"score" bson:"score"` 19 | } 20 | 21 | type TestpaperProps struct { 22 | GradeRange []string `json:"grade_range" bson:"grade_range"` 23 | Subjects []string `json:"subjects" bson:"subjects"` 24 | Difficulty string `json:"difficulty" bson:"difficulty"` 25 | TimeLimit string `json:"time_limit" bson:"time_limit"` 26 | } 27 | 28 | type TestpaperComment struct { 29 | TimePoint time.Time `json:"time_point" bson:"time_point"` 30 | Comment string `json:"comment" bson:"comment"` 31 | Author string `json:"author" bson:"author"` 32 | } 33 | 34 | type TempTestpaper struct { 35 | field.DefaultField `bson:",inline"` 36 | Uuid string `json:"uuid" bson:"uuid"` 37 | IsRoot bool `json:"is_root" bson:"is_root"` 38 | Base string `json:"base" bson:"base"` 39 | SourceProject string `json:"source_project" bson:"source_project"` 40 | Author string `json:"author" bson:"author"` 41 | Title string `json:"title" bson:"title"` 42 | Info []TestpaperPart `json:"info" bson:"info"` 43 | Props TestpaperProps `json:"props" bson:"props"` 44 | CommentRecord []TestpaperComment `json:"comment_record" bson:"comment_record"` 45 | } 46 | 47 | type FinalTestpaper struct { 48 | field.DefaultField `bson:",inline"` 49 | Uuid string `json:"uuid" bson:"uuid"` 50 | SourceProject string `json:"source_project" bson:"source_project"` 51 | Author string `json:"author" bson:"author"` 52 | Title string `json:"title" bson:"title"` 53 | Info []TestpaperPart `json:"info" bson:"info"` 54 | Props TestpaperProps `json:"props" bson:"props"` 55 | } 56 | -------------------------------------------------------------------------------- /warehouse/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "errors" 5 | "strconv" 6 | "time" 7 | ) 8 | 9 | var ( 10 | UserList map[string]*User 11 | ) 12 | 13 | func init() { 14 | UserList = make(map[string]*User) 15 | u := User{"user_11111", "astaxie", "11111", Profile{"male", 20, "Singapore", "astaxie@gmail.com"}} 16 | UserList["user_11111"] = &u 17 | } 18 | 19 | type User struct { 20 | Id string 21 | Username string 22 | Password string 23 | Profile Profile 24 | } 25 | 26 | type Profile struct { 27 | Gender string 28 | Age int 29 | Address string 30 | Email string 31 | } 32 | 33 | func AddUser(u User) string { 34 | u.Id = "user_" + strconv.FormatInt(time.Now().UnixNano(), 10) 35 | UserList[u.Id] = &u 36 | return u.Id 37 | } 38 | 39 | func GetUser(uid string) (u *User, err error) { 40 | if u, ok := UserList[uid]; ok { 41 | return u, nil 42 | } 43 | return nil, errors.New("User not exists") 44 | } 45 | 46 | func GetAllUsers() map[string]*User { 47 | return UserList 48 | } 49 | 50 | func UpdateUser(uid string, uu *User) (a *User, err error) { 51 | if u, ok := UserList[uid]; ok { 52 | if uu.Username != "" { 53 | u.Username = uu.Username 54 | } 55 | if uu.Password != "" { 56 | u.Password = uu.Password 57 | } 58 | if uu.Profile.Age != 0 { 59 | u.Profile.Age = uu.Profile.Age 60 | } 61 | if uu.Profile.Address != "" { 62 | u.Profile.Address = uu.Profile.Address 63 | } 64 | if uu.Profile.Gender != "" { 65 | u.Profile.Gender = uu.Profile.Gender 66 | } 67 | if uu.Profile.Email != "" { 68 | u.Profile.Email = uu.Profile.Email 69 | } 70 | return u, nil 71 | } 72 | return nil, errors.New("User Not Exist") 73 | } 74 | 75 | func Login(username, password string) bool { 76 | for _, u := range UserList { 77 | if u.Username == username && u.Password == password { 78 | return true 79 | } 80 | } 81 | return false 82 | } 83 | 84 | func DeleteUser(uid string) { 85 | delete(UserList, uid) 86 | } 87 | -------------------------------------------------------------------------------- /warehouse/routers/router.go: -------------------------------------------------------------------------------- 1 | // @APIVersion 1.0.0 2 | // @Title OpenCT Question-warehouse API 3 | // @Description beego has a very cool tools to autogenerate documents for your API 4 | // @Contact kkoogqw@hotmial.com 5 | // @TermsOfServiceUrl http://beego.me/ 6 | // @License Apache 2.0 7 | // @LicenseUrl http://www.apache.org/licenses/LICENSE-2.0.html 8 | package routers 9 | 10 | import ( 11 | "warehouse/controllers" 12 | 13 | beego "github.com/beego/beego/v2/server/web" 14 | ) 15 | 16 | func init() { 17 | ns := beego.NewNamespace("/qbank", 18 | beego.NSNamespace("/question", 19 | beego.NSInclude( 20 | &controllers.QuestionController{}, 21 | ), 22 | ), 23 | beego.NSNamespace("/testpaper", 24 | beego.NSInclude( 25 | &controllers.TestpaperController{}, 26 | ), 27 | ), 28 | beego.NSNamespace("/query", 29 | beego.NSInclude( 30 | &controllers.QueryController{}, 31 | ), 32 | ), 33 | ) 34 | beego.AddNamespace(ns) 35 | } 36 | -------------------------------------------------------------------------------- /warehouse/swagger.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/warehouse/swagger.zip -------------------------------------------------------------------------------- /warehouse/swagger/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/warehouse/swagger/favicon-16x16.png -------------------------------------------------------------------------------- /warehouse/swagger/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/warehouse/swagger/favicon-32x32.png -------------------------------------------------------------------------------- /warehouse/swagger/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Swagger UI 7 | 8 | 9 | 10 | 11 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
69 | 70 | 71 | 72 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /warehouse/swagger/oauth2-redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 54 | -------------------------------------------------------------------------------- /warehouse/swagger/swagger-ui-bundle.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA6+FA;;;;;;;;;;;;;;;;;;;;;;;;;;AAyTA;;;;;;AAoIA;AAi7FA;AAmtCA;AAi0IA;AA0oJA;AAgwFA;AAyrGA;AA0lFA;AA4nFA;AA+9CA;AA+gDA;AAwrCA;AA60EA;;;;;AA6oCA;AAsyJA;;;;;;;;;;;;;;AA64EA;AA4mIA;AAquJA;AA2qHA;AA2mGA;AAiiEA;AAq4DA;AAg3DA;AAoPA;;;;;;AAk7FA;AA07FA;;;;;AAi8CA;AAgsFA;AAs2CA;AAglCA;AAu9CA;AAy8EA;AAsiCA;AA+yFA;;;;;;;;;AAgkDA;AA2zIA;AAu7FA;AAmrFA;AAu0EA","sourceRoot":""} -------------------------------------------------------------------------------- /warehouse/swagger/swagger-ui-standalone-preset.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AA8QA;AAmvGA;AAuxFA;;;;;;AAocA;AAkvFA;AAu+CA;AAo+CA;AAgrCA;AAuyEA","sourceRoot":""} -------------------------------------------------------------------------------- /warehouse/swagger/swagger-ui.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui.css","sources":[],"mappings":"","sourceRoot":""} -------------------------------------------------------------------------------- /warehouse/swagger/swagger-ui.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AA0yCA;AAoyHA;AAmyHA;AAykGA;AA+9BA;AA6iCA;AAojCA;AAu5BA","sourceRoot":""} -------------------------------------------------------------------------------- /warehouse/tests/default_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "path/filepath" 7 | "runtime" 8 | "testing" 9 | _ "warehouse/routers" 10 | 11 | "github.com/beego/beego/v2/core/logs" 12 | beego "github.com/beego/beego/v2/server/web" 13 | . "github.com/smartystreets/goconvey/convey" 14 | ) 15 | 16 | func init() { 17 | _, file, _, _ := runtime.Caller(0) 18 | apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator)))) 19 | beego.TestBeegoInit(apppath) 20 | } 21 | 22 | // TestGet is a sample to run an endpoint test 23 | func TestGet(t *testing.T) { 24 | r, _ := http.NewRequest("GET", "/v1/object", nil) 25 | w := httptest.NewRecorder() 26 | beego.BeeApp.Handlers.ServeHTTP(w, r) 27 | 28 | logs.Info("testing", "TestGet", "Code[%d]\n%s", w.Code, w.Body.String()) 29 | 30 | Convey("Subject: Test Station Endpoint\n", t, func() { 31 | Convey("Status Code Should Be 200", func() { 32 | So(w.Code, ShouldEqual, 200) 33 | }) 34 | Convey("The Result Should Not Be Empty", func() { 35 | So(w.Body.Len(), ShouldBeGreaterThan, 0) 36 | }) 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /warehouse/utils/uuid.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import "github.com/google/uuid" 4 | 5 | /* 6 | 用于生成uuid使用, 这里使用V1(基于timestamp)和V4版本(基于随机数) 7 | */ 8 | 9 | // GenUuidV1 generate the uuid version 1 (timestamp) 10 | func GenUuidV1() (string, error) { 11 | res, err := uuid.NewUUID() 12 | if err != nil { 13 | return "", err 14 | } 15 | return res.String(), nil 16 | } 17 | 18 | // GenUuidV4 generate the uuid version 4 (random number) 19 | func GenUuidV4() string { 20 | res := uuid.New() 21 | return res.String() 22 | } 23 | -------------------------------------------------------------------------------- /web/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /web/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `yarn start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `yarn test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `yarn build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `yarn eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `yarn build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /web/build/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": { 3 | "main.css": "./static/css/main.28dd778d.chunk.css", 4 | "main.js": "./static/js/main.f8299ca7.chunk.js", 5 | "main.js.map": "./static/js/main.f8299ca7.chunk.js.map", 6 | "runtime-main.js": "./static/js/runtime-main.3b3646ce.js", 7 | "runtime-main.js.map": "./static/js/runtime-main.3b3646ce.js.map", 8 | "static/css/2.e4902758.chunk.css": "./static/css/2.e4902758.chunk.css", 9 | "static/js/2.75a36cd2.chunk.js": "./static/js/2.75a36cd2.chunk.js", 10 | "static/js/2.75a36cd2.chunk.js.map": "./static/js/2.75a36cd2.chunk.js.map", 11 | "index.html": "./index.html", 12 | "static/css/2.e4902758.chunk.css.map": "./static/css/2.e4902758.chunk.css.map", 13 | "static/css/main.28dd778d.chunk.css.map": "./static/css/main.28dd778d.chunk.css.map", 14 | "static/js/2.75a36cd2.chunk.js.LICENSE.txt": "./static/js/2.75a36cd2.chunk.js.LICENSE.txt", 15 | "static/media/Rockets.bcd94bd9.png": "./static/media/Rockets.bcd94bd9.png", 16 | "static/media/index.less": "./static/media/login_background.d1cc80fb.png", 17 | "static/media/proposition-paper-icon.2d177c41.png": "./static/media/proposition-paper-icon.2d177c41.png" 18 | }, 19 | "entrypoints": [ 20 | "static/js/runtime-main.3b3646ce.js", 21 | "static/css/2.e4902758.chunk.css", 22 | "static/js/2.75a36cd2.chunk.js", 23 | "static/css/main.28dd778d.chunk.css", 24 | "static/js/main.f8299ca7.chunk.js" 25 | ] 26 | } -------------------------------------------------------------------------------- /web/build/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/build/favicon.ico -------------------------------------------------------------------------------- /web/build/index.html: -------------------------------------------------------------------------------- 1 | React App
-------------------------------------------------------------------------------- /web/build/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/build/logo192.png -------------------------------------------------------------------------------- /web/build/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/build/logo512.png -------------------------------------------------------------------------------- /web/build/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /web/build/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /web/build/static/js/2.75a36cd2.chunk.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /* 2 | object-assign 3 | (c) Sindre Sorhus 4 | @license MIT 5 | */ 6 | 7 | /*! 8 | Copyright (c) 2018 Jed Watson. 9 | Licensed under the MIT License (MIT), see 10 | http://jedwatson.github.io/classnames 11 | */ 12 | 13 | /*!@license 14 | * UAParser.js v0.7.28 15 | * Lightweight JavaScript-based User-Agent string parser 16 | * https://github.com/faisalman/ua-parser-js 17 | * 18 | * Copyright © 2012-2021 Faisal Salman 19 | * Licensed under MIT License 20 | */ 21 | 22 | /** @license React v0.20.2 23 | * scheduler.production.min.js 24 | * 25 | * Copyright (c) Facebook, Inc. and its affiliates. 26 | * 27 | * This source code is licensed under the MIT license found in the 28 | * LICENSE file in the root directory of this source tree. 29 | */ 30 | 31 | /** @license React v16.13.1 32 | * react-is.production.min.js 33 | * 34 | * Copyright (c) Facebook, Inc. and its affiliates. 35 | * 36 | * This source code is licensed under the MIT license found in the 37 | * LICENSE file in the root directory of this source tree. 38 | */ 39 | 40 | /** @license React v17.0.2 41 | * react-dom-server.browser.production.min.js 42 | * 43 | * Copyright (c) Facebook, Inc. and its affiliates. 44 | * 45 | * This source code is licensed under the MIT license found in the 46 | * LICENSE file in the root directory of this source tree. 47 | */ 48 | 49 | /** @license React v17.0.2 50 | * react-dom.production.min.js 51 | * 52 | * Copyright (c) Facebook, Inc. and its affiliates. 53 | * 54 | * This source code is licensed under the MIT license found in the 55 | * LICENSE file in the root directory of this source tree. 56 | */ 57 | 58 | /** @license React v17.0.2 59 | * react-jsx-runtime.production.min.js 60 | * 61 | * Copyright (c) Facebook, Inc. and its affiliates. 62 | * 63 | * This source code is licensed under the MIT license found in the 64 | * LICENSE file in the root directory of this source tree. 65 | */ 66 | 67 | /** @license React v17.0.2 68 | * react.production.min.js 69 | * 70 | * Copyright (c) Facebook, Inc. and its affiliates. 71 | * 72 | * This source code is licensed under the MIT license found in the 73 | * LICENSE file in the root directory of this source tree. 74 | */ 75 | 76 | //! moment.js 77 | -------------------------------------------------------------------------------- /web/build/static/js/runtime-main.3b3646ce.js: -------------------------------------------------------------------------------- 1 | !function(e){function t(t){for(var n,l,i=t[0],f=t[1],a=t[2],p=0,s=[];p0.2%", 43 | "not dead", 44 | "not op_mini all" 45 | ], 46 | "development": [ 47 | "last 1 chrome version", 48 | "last 1 firefox version", 49 | "last 1 safari version" 50 | ] 51 | }, 52 | "homepage": "." 53 | } 54 | -------------------------------------------------------------------------------- /web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/public/favicon.ico -------------------------------------------------------------------------------- /web/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /web/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/public/logo192.png -------------------------------------------------------------------------------- /web/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/public/logo512.png -------------------------------------------------------------------------------- /web/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /web/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /web/src/App.jsx: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2021-07-31 16:42:56 4 | * @LastEditTime: 2021-08-14 04:24:11 5 | * @LastEditors: Please set LastEditors 6 | * @Description: In User Settings Edit 7 | * @FilePath: \OpenItem\web-client\src\App.js 8 | */ 9 | import './App.less'; 10 | import React, { Component } from 'react' 11 | import {Switch,Route,Redirect,HashRouter as Router} from 'react-router-dom' 12 | import Login from './views/Login' 13 | import Home from './views/Home' 14 | import NotFound from './views/errors/404' 15 | import Forbid from './views/errors/402' 16 | 17 | export default class App extends Component { 18 | getRemSize = ()=>{ 19 | let whdef = 100/1920 20 | let wW = window.innerWidth 21 | let rem = wW * whdef 22 | document.documentElement.style.fontSize = rem + 'px' 23 | } 24 | 25 | componentDidMount = ()=>{ 26 | window.resize = ()=>{ 27 | this.getRemSize() 28 | } 29 | this.getRemSize() 30 | } 31 | 32 | render() { 33 | return ( 34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
45 | ) 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /web/src/App.less: -------------------------------------------------------------------------------- 1 | ::-webkit-scrollbar { 2 | width: 0 !important; 3 | } 4 | ::-webkit-scrollbar { 5 | width: 0 !important;height: 0; 6 | } 7 | -------------------------------------------------------------------------------- /web/src/asset/images/Cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/src/asset/images/Cloud.png -------------------------------------------------------------------------------- /web/src/asset/images/Crying_face.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/src/asset/images/Crying_face.png -------------------------------------------------------------------------------- /web/src/asset/images/Flu_expression.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/src/asset/images/Flu_expression.png -------------------------------------------------------------------------------- /web/src/asset/images/Rockets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/src/asset/images/Rockets.png -------------------------------------------------------------------------------- /web/src/asset/images/Unhapply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/src/asset/images/Unhapply.png -------------------------------------------------------------------------------- /web/src/asset/images/login_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/src/asset/images/login_background.png -------------------------------------------------------------------------------- /web/src/asset/images/openct_logo_1082x328.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/src/asset/images/openct_logo_1082x328.png -------------------------------------------------------------------------------- /web/src/asset/images/proposition-paper-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/src/asset/images/proposition-paper-icon.png -------------------------------------------------------------------------------- /web/src/components/BuildTeam/index.less: -------------------------------------------------------------------------------- 1 | [data-component=build-team-page]{ 2 | width: 100%; 3 | min-height: 6rem; 4 | background-color: white; 5 | .member-list{ 6 | width: 100%; 7 | box-sizing: border-box; 8 | padding: 0px .2rem; 9 | } 10 | } -------------------------------------------------------------------------------- /web/src/components/CalendarButton/index.less: -------------------------------------------------------------------------------- 1 | [data-component=calendar-button-box]{ 2 | position: relative; 3 | width: max-content; 4 | height: max-content; 5 | > .calendar-box{ 6 | width: auto; 7 | max-height: 0; 8 | overflow: hidden; 9 | transition: all .2s; 10 | position: absolute; 11 | background-color: white; 12 | filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25)); 13 | top: .34rem; 14 | left: 50%; 15 | transform: translateX(-50%); 16 | z-index: 600; 17 | .ant-picker-calendar-date-value,th{ 18 | font-size: .14rem; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /web/src/components/ChangeTags/index.less: -------------------------------------------------------------------------------- 1 | .site-tag-plus { 2 | background: #fff; 3 | border-style: dashed; 4 | } 5 | 6 | .edit-tag { 7 | user-select: none; 8 | } 9 | 10 | .tag-input { 11 | width: 78px; 12 | margin-right: 8px; 13 | vertical-align: top; 14 | } -------------------------------------------------------------------------------- /web/src/components/ChoiceQuestionEditer/index.less: -------------------------------------------------------------------------------- 1 | [data-component=choice-question-editer]{ 2 | width: 100%; 3 | height: auto; 4 | .question-params{ 5 | > .title{ 6 | width: 100%; 7 | height: .41rem; 8 | background-color: #EEEEEE; 9 | line-height: .41rem; 10 | box-sizing: border-box; 11 | padding-left: .1rem; 12 | > span{ 13 | font-size: .14rem; 14 | color: #000000; 15 | 16 | } 17 | } 18 | > .param-item{ 19 | width: 100%; 20 | height: .32rem; 21 | .label{ 22 | box-sizing: border-box; 23 | padding-left: .1rem; 24 | line-height: .32rem; 25 | > span{ 26 | font-size: .14rem; 27 | color: #000000; 28 | } 29 | } 30 | .value{ 31 | > .ant-select{ 32 | width: 100%; 33 | } 34 | > .tag-list{ 35 | width: 100%; 36 | height: 100%; 37 | display: flex; 38 | align-items: center; 39 | } 40 | } 41 | } 42 | } 43 | .question-complete-box{ 44 | width: 100%; 45 | margin-top: .77rem; 46 | margin-bottom: .5rem; 47 | } 48 | } -------------------------------------------------------------------------------- /web/src/components/CompletionStatus/index.less: -------------------------------------------------------------------------------- 1 | [data-component=completion-status-box]{ 2 | width: 100%; 3 | display: flex; 4 | justify-content: space-between; 5 | box-sizing: border-box; 6 | padding-left: 0.47rem; 7 | > .left-box{ 8 | > .title{ 9 | height: .24rem; 10 | line-height: .24rem; 11 | margin-bottom: .08rem; 12 | > span{ 13 | font-size: .14rem; 14 | color: #8C8C8C; 15 | } 16 | } 17 | > .value-list{ 18 | .ant-statistic-title{ 19 | font-size: .14rem; 20 | color: rgba(0, 0, 0, 0.45); 21 | } 22 | .ant-statistic-content-value-int,.ant-statistic-content-suffix{ 23 | font-size: .26rem; 24 | color: rgba(0, 0, 0, 0.85); 25 | } 26 | } 27 | } 28 | > .right-box{ 29 | .statistic-item-title{ 30 | font-size: .14rem; 31 | color: #000000D9; 32 | line-height: .22rem; 33 | box-sizing: border-box; 34 | padding-left: .14rem; 35 | position: relative; 36 | > .circle{ 37 | width: .06rem; 38 | height: .06rem; 39 | position: absolute; 40 | left: 0; 41 | top: 50%; 42 | transform: translateY(-50%); 43 | border-radius: 50%; 44 | } 45 | } 46 | .ant-statistic-content-value-int,.ant-statistic-content-suffix{ 47 | font-size: .26rem; 48 | color: rgba(0, 0, 0, 0.85); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /web/src/components/DataTable/index.less: -------------------------------------------------------------------------------- 1 | [data-component=data-table-box]{ 2 | width: 100%; 3 | height: calc(100% - .38rem); 4 | box-sizing: border-box; 5 | padding: 0rem .25rem 0rem .4rem; 6 | position: relative; 7 | .ant-table-thead,.ant-table-row{ 8 | height: .58rem; 9 | } 10 | .ant-table-cell{ 11 | font-size: .14rem; 12 | } 13 | > .footer{ 14 | width: 100%; 15 | height: .40rem; 16 | display: flex; 17 | align-items: center; 18 | position: absolute; 19 | bottom: 0; 20 | left: 0; 21 | box-sizing: border-box; 22 | padding-left: .4rem; 23 | } 24 | } -------------------------------------------------------------------------------- /web/src/components/DifficultyBox/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import './index.less' 3 | 4 | 5 | export default class index extends Component { 6 | 7 | state={ 8 | value:1 9 | } 10 | 11 | render() { 12 | return ( 13 |
14 |
15 | { 16 | [1,2,3,4,5].map(item=>( 17 |
{ 18 | this.setState({ 19 | value:item 20 | }) 21 | this.props.onChange(item) 22 | }}> 23 |
{item}
24 |
25 |
26 | )) 27 | } 28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | ) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /web/src/components/DifficultyBox/index.less: -------------------------------------------------------------------------------- 1 | [data-component=difficulty-box]{ 2 | width: 100%; 3 | height: 32px; 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | position: relative; 8 | > .difficulty-process-box{ 9 | width: 100%; 10 | height: .04rem; 11 | background-color: #F5F5F5; 12 | display: flex; 13 | align-items: center; 14 | justify-content: space-between; 15 | position: relative; 16 | > .value-item{ 17 | width: .08rem; 18 | height: .08rem; 19 | border-radius: .08rem; 20 | 21 | position: relative; 22 | cursor: pointer; 23 | z-index: 10; 24 | transition: all .5s; 25 | > .value{ 26 | width: .16rem; 27 | height: .16rem; 28 | text-align: center; 29 | position: absolute; 30 | bottom: -.16rem; 31 | left: -.04rem; 32 | } 33 | > .center-cir{ 34 | width: .04rem; 35 | height: .04rem; 36 | background-color: white; 37 | border-radius: .04rem; 38 | position: absolute; 39 | left: .02rem; 40 | top: .02rem; 41 | } 42 | } 43 | > .difficulty-process-value{ 44 | height: 100%; 45 | position: absolute; 46 | left: 0; 47 | top: 0; 48 | background-color: #91D5FF; 49 | z-index: 8; 50 | transition: all .5s; 51 | } 52 | > .selected-cir{ 53 | width: .15rem; 54 | height: .15rem; 55 | position: absolute; 56 | top: -0.055rem; 57 | border-radius: .15rem; 58 | background-color: #91D5FF; 59 | z-index: 12; 60 | transform: translateX(-50%); 61 | display: flex; 62 | align-items: center; 63 | justify-content: center; 64 | transition: all .5s; 65 | > .circle-1{ 66 | width: .11rem; 67 | height: .11rem; 68 | background-color: white; 69 | border-radius: .11rem; 70 | display: flex; 71 | align-items: center; 72 | justify-content: center; 73 | > .circle-2{ 74 | width: .07rem; 75 | height: .07rem; 76 | border-radius: .07rem; 77 | background-color: #91D5FF; 78 | display: flex; 79 | align-items: center; 80 | justify-content: center; 81 | > .circle-3{ 82 | width: .04rem; 83 | height: .04rem; 84 | border-radius: .04rem; 85 | background-color: white; 86 | } 87 | } 88 | } 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /web/src/components/HistoryQuestion/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import {Row,Col,Button} from 'antd' 3 | import './index.less' 4 | 5 | export default class index extends Component { 6 | render() { 7 | return ( 8 |
9 | 10 | 11 | 题目题目题目题目题目题目题目题目题目题目题目题目题目题目题目题目......题目题目题目题目题目题目题目题目题目题目题目题目题目题目题目题目.题目题目题目题目题目题目题目题目.(最多5行过多省略)题目题目题目题目题目题目题目题目题目题目题目题目题目题目题目题目......题目题目题目题目题目题目题目题目题目题目题目题目题目题目题目题目.题目题目题目题目题目题目题目题目.(最多5行过多省略) 12 | 13 | 14 | 15 | 16 | 学科名称: 17 | 18 | 19 | 数学 20 | 21 | 22 | 23 | 24 | 能力纬度: 25 | 26 | 27 | 参数1;参数2;参数3 28 | 29 | 30 | 31 | 32 | 内容纬度 33 | 34 | 35 | 参数1;参数2;参数3 36 | 37 | 38 | 39 | 40 | 难度等级: 41 | 42 | 43 | 参数1 44 | 45 | 46 | 47 | 48 | 49 | 50 | 答案:xxxx 51 | 52 | 53 | 54 | 55 | 56 |
57 | ) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /web/src/components/HistoryQuestion/index.less: -------------------------------------------------------------------------------- 1 | [data-component=history-question-item]{ 2 | width: 100%; 3 | box-sizing: border-box; 4 | padding: .14rem .1rem .16rem .24rem; 5 | background-color: #FFFEFE33; 6 | border: .01rem solid #2DB7F5; 7 | margin-top: .2rem; 8 | > .queston-content{ 9 | width: 100%; 10 | > .question-title{ 11 | width: 100%; 12 | box-sizing: border-box; 13 | padding-top: .11rem; 14 | overflow: hidden; 15 | text-overflow: ellipsis; 16 | display: -webkit-box; 17 | -webkit-line-clamp: 5; 18 | -webkit-box-orient: vertical; 19 | text-align: justify; 20 | line-height: .22rem; 21 | > span{ 22 | font-size: .14rem; 23 | color: #00000059; 24 | } 25 | } 26 | > .question-params{ 27 | width: 100%; 28 | > .params-item{ 29 | width: 100%; 30 | > .title{ 31 | line-height: .22rem; 32 | > span{ 33 | font-size: .1rem; 34 | color: #1890FF; 35 | } 36 | } 37 | > .value{ 38 | line-height: .22rem; 39 | overflow: hidden; 40 | text-overflow: ellipsis; 41 | white-space: nowrap; 42 | > span{ 43 | font-size: .1rem; 44 | color: #1890FF; 45 | } 46 | } 47 | } 48 | } 49 | } 50 | 51 | > .question-footer{ 52 | width: 100%; 53 | margin-top: .25rem; 54 | > .question-answer{ 55 | display: flex; 56 | align-items: center; 57 | > span{ 58 | font-size: .1rem; 59 | color: #1890FF; 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /web/src/components/MaterialWarehouse/index.less: -------------------------------------------------------------------------------- 1 | [data-component=material-warehouse-box]{ 2 | width: 100%; 3 | height: calc(100% - .38rem); 4 | box-sizing: border-box; 5 | padding:0rem .21rem 0rem .23rem; 6 | > .container{ 7 | width: 100%; 8 | height: calc(100% - .4rem); 9 | .empty-state-box{ 10 | width: 100%; 11 | height: 100%; 12 | display: flex; 13 | align-items: center; 14 | justify-content: center; 15 | > .ant-empty{ 16 | margin: 0; 17 | } 18 | } 19 | .file-item{ 20 | width: 1rem; 21 | height: 1rem; 22 | background-color: #F3F3F3; 23 | float: left; 24 | margin-right: .1rem; 25 | display: flex; 26 | align-content: center; 27 | justify-content: center; 28 | flex-wrap: wrap; 29 | cursor: pointer; 30 | > .icon{ 31 | width: 100%; 32 | height: .5rem; 33 | display: flex; 34 | align-items: center; 35 | justify-content: center; 36 | font-size: .32rem; 37 | } 38 | > .name{ 39 | text-align: center; 40 | overflow:hidden; 41 | white-space: nowrap; 42 | text-overflow: ellipsis; 43 | box-sizing: border-box; 44 | padding: 0px .08rem; 45 | > span{ 46 | font-size: .08rem; 47 | } 48 | } 49 | } 50 | > .upload-download-box{ 51 | float: left; 52 | margin-right: .1rem; 53 | .file-load-btn{ 54 | width: 100%; 55 | height: 100%; 56 | display: flex; 57 | align-content: center; 58 | justify-content: center; 59 | flex-wrap: wrap; 60 | } 61 | > .ant-upload-picture-card-wrapper{ 62 | width: 1rem; 63 | height: 1rem; 64 | > .ant-upload{ 65 | width: 100%; 66 | height: 100%; 67 | margin: 0; 68 | } 69 | } 70 | } 71 | } 72 | > .footer{ 73 | display: flex; 74 | align-items: flex-end; 75 | width: 100%; 76 | height: .4rem; 77 | } 78 | } -------------------------------------------------------------------------------- /web/src/components/ModifyRecordModal/index.less: -------------------------------------------------------------------------------- 1 | [data-component=modify-record-box]{ 2 | width: 100%; 3 | > .basic{ 4 | width: 100%; 5 | height: 1.49rem; 6 | box-sizing: border-box; 7 | padding: .16rem .16rem 0px .16rem; 8 | border: 1px solid #F0F0F0; 9 | border-radius: .02rem; 10 | margin-bottom: .32rem; 11 | > .id{ 12 | font-size: .16rem; 13 | line-height: .24rem; 14 | font-weight: 400; 15 | color: #000000; 16 | height: .24rem; 17 | } 18 | > .date{ 19 | height: .22rem; 20 | line-height: .22rem; 21 | font-size: .14rem; 22 | color: rgba(0, 0, 0, 0.45); 23 | } 24 | } 25 | .ant-table-cell{ 26 | font-size: .14rem; 27 | } 28 | .ant-table-thead,.ant-table-row{ 29 | height: .56rem; 30 | } 31 | } -------------------------------------------------------------------------------- /web/src/components/ModulaCard/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import './index.less' 3 | 4 | export default class index extends Component { 5 | render() { 6 | return ( 7 |
8 |
9 |
10 | {this.props.title} 11 |
12 | {this.props.right} 13 |
14 |
15 | {this.props.children} 16 |
17 | ) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /web/src/components/ModulaCard/index.less: -------------------------------------------------------------------------------- 1 | [data-component=modula-card-box]{ 2 | width: 100%; 3 | height: 100%; 4 | background-color: #fff; 5 | box-sizing: border-box; 6 | padding: .16rem 0rem ; 7 | > .title{ 8 | width: 100%; 9 | height: .22rem; 10 | box-sizing: border-box; 11 | padding: 0px .26rem; 12 | display: flex; 13 | align-items: center; 14 | margin-bottom: .16rem; 15 | position: relative; 16 | > .icon{ 17 | display: block; 18 | width: .06rem; 19 | height: .18rem; 20 | background-color: #1890FF; 21 | margin-right: .16rem; 22 | } 23 | > span{ 24 | font-size: .16rem; 25 | font-weight: 400; 26 | line-height: .22rem; 27 | } 28 | > .right{ 29 | position: absolute; 30 | height: 100%; 31 | right: .14rem; 32 | top: 0; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /web/src/components/Step/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Row, Col } from 'antd' 3 | import TaskRequirements from '../TaskRequirements' 4 | import CompletionStatus from '../CompletionStatus' 5 | import MaterialWarehouse from '../MaterialWarehouse' 6 | import DataTable from '../DataTable' 7 | import './index.less' 8 | 9 | export default class index extends Component { 10 | 11 | render() { 12 | return ( 13 |
14 | 15 | 16 | 17 | 22 | 23 | 24 | 28 | 29 | 30 | 36 | 37 | 38 | 39 | 40 | 46 | 47 | 48 | 49 |
50 | ) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /web/src/components/Step/index.less: -------------------------------------------------------------------------------- 1 | [data-component=step-page]{ 2 | width: 100%; 3 | height: auto; 4 | .addition-box{ 5 | width: 100%; 6 | height: 100%; 7 | background-color: white; 8 | } 9 | } -------------------------------------------------------------------------------- /web/src/components/TaskRequirements/index.less: -------------------------------------------------------------------------------- 1 | [data-component=task-requirements-box]{ 2 | width: 100%; 3 | height: calc(100% - .38rem); 4 | > .describe-box{ 5 | width: 100%; 6 | height: .66rem; 7 | box-sizing: border-box; 8 | padding: 0rem 0rem 0rem .5rem; 9 | display: flex; 10 | align-items: center; 11 | justify-content: space-between; 12 | margin-bottom: .21rem; 13 | > .context{ 14 | width: 5rem; 15 | height: 100%; 16 | > p{ 17 | font-size: .14rem; 18 | line-height: .22rem; 19 | margin: 0; 20 | } 21 | } 22 | > .btn-box{ 23 | height: 100%; 24 | } 25 | } 26 | > .choice-box{ 27 | width: 100%; 28 | height: .32rem; 29 | box-sizing: border-box; 30 | padding: 0rem 0rem 0rem .5rem; 31 | display: flex; 32 | .ant-btn { 33 | border-color: #1890FF; 34 | color: #1890FF; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /web/src/components/UpLoadModal/index.less: -------------------------------------------------------------------------------- 1 | [data-component=up-load-modal-box]{ 2 | width: 100%; 3 | .material__id{ 4 | display: block; 5 | .ant-form-item-control{ 6 | box-sizing: border-box; 7 | padding-left: 0.4008rem; 8 | max-width: 91.66666667%; 9 | .ant-form-item-control-input{ 10 | width: 100%; 11 | max-width: 100%; 12 | .ant-input { 13 | background-color: #FFFFFF; 14 | } 15 | } 16 | .ant-form-item-extra{ 17 | font-size: .14rem; 18 | line-height: .22rem; 19 | color: #00000073; 20 | } 21 | } 22 | } 23 | .upload-file-item{ 24 | width: 100%; 25 | height: .22rem; 26 | line-height: .22rem; 27 | > .anticon{ 28 | color: #00000073; 29 | font-size: .11rem; 30 | } 31 | > span{ 32 | font-size: .14rem; 33 | color: #1890FF; 34 | cursor: pointer; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /web/src/components/UpLoadQuestionModal/index.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-ct/OpenItem-old/2b4e89b9ba8cd0acd9b8c7a1c33f15da03f03386/web/src/components/UpLoadQuestionModal/index.less -------------------------------------------------------------------------------- /web/src/conf/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2021-08-12 00:18:40 4 | * @LastEditTime: 2021-08-12 23:20:33 5 | * @LastEditors: Please set LastEditors 6 | * @Description: In User Settings Edit 7 | * @FilePath: \OpenItem\web\src\conf\index.js 8 | */ 9 | module.exports = { 10 | baseURL:'http://49.232.73.36:8081', 11 | } 12 | -------------------------------------------------------------------------------- /web/src/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2021-07-31 16:42:56 4 | * @LastEditTime: 2021-08-13 01:38:48 5 | * @LastEditors: Please set LastEditors 6 | * @Description: In User Settings Edit 7 | * @FilePath: \OpenItem\web-client\src\index.js 8 | */ 9 | import React from 'react'; 10 | import ReactDOM from 'react-dom'; 11 | import './index.less'; 12 | import 'antd/dist/antd.less'; 13 | import App from './App.jsx'; 14 | import store from './store' 15 | 16 | ReactDOM.render( , document.getElementById('root') ); 17 | 18 | store.subscribe(()=>{ 19 | ReactDOM.render(,document.getElementById('root')) 20 | }) -------------------------------------------------------------------------------- /web/src/index.less: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | 15 | html,body,#root,#App{ 16 | width: 19.2rem; 17 | height: 100%; 18 | margin: 0; 19 | padding: 0; 20 | } 21 | -------------------------------------------------------------------------------- /web/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/src/setupProxy.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2021-09-19 00:17:31 4 | * @LastEditTime: 2021-10-02 01:45:35 5 | * @LastEditors: Please set LastEditors 6 | * @Description: In User Settings Edit 7 | * @FilePath: \OpenItem\web\src\setupProxy.js 8 | */ 9 | const { createProxyMiddleware } = require('http-proxy-middleware'); 10 | 11 | module.exports = function (app) { 12 | // /api 表示代理路径 13 | // target 表示目标服务器的地址 14 | // app.use(createProxyMiddleware('/user', {target: "http://49.232.73.36:8081/review"})); 15 | // app.use(createProxyMiddleware('/proj', {target: "http://49.232.73.36:8081/review"})); 16 | // app.use(createProxyMiddleware('/file', {target: "http://49.232.73.36:8081/review"})); 17 | // app.use(createProxyMiddleware('/query/assign', {target: "http://49.232.73.36:8081/review"})); 18 | // app.use(createProxyMiddleware('/query/audit', {target: "http://49.232.73.36:8081/review"})); 19 | // app.use(createProxyMiddleware('/query/file', {target: "http://49.232.73.36:8081/review"})); 20 | // app.use(createProxyMiddleware('/query/proj', {target: "http://49.232.73.36:8081/review"})); 21 | // app.use(createProxyMiddleware('/query/step', {target: "http://49.232.73.36:8081/review"})); 22 | // app.use(createProxyMiddleware('/query/submit', {target: "http://49.232.73.36:8081/review"})); 23 | // app.use(createProxyMiddleware('/query/user', {target: "http://49.232.73.36:8081/review"})); 24 | // app.use(createProxyMiddleware('/question', {target: "http://49.232.73.36:8082/qbank"})); 25 | // app.use(createProxyMiddleware('/testpaper', {target: "http://49.232.73.36:8082/qbank"})); 26 | // app.use(createProxyMiddleware('/query/f_question', {target: "http://49.232.73.36:8082/qbank"})); 27 | // app.use(createProxyMiddleware('/query/f_testpaper', {target: "http://49.232.73.36:8082/qbank"})); 28 | // app.use(createProxyMiddleware('/query/t_question', {target: "http://49.232.73.36:8082/qbank"})); 29 | // app.use(createProxyMiddleware('/query/t_testpaper', {target: "http://49.232.73.36:8082/qbank"})); 30 | } -------------------------------------------------------------------------------- /web/src/store/action.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2021-08-13 01:12:25 4 | * @LastEditTime: 2021-09-17 13:47:42 5 | * @LastEditors: Please set LastEditors 6 | * @Description: In User Settings Edit 7 | * @FilePath: \OpenItem\web\src\store\user\action.js 8 | */ 9 | 10 | import { SET_USERINFO,SET_PROJECTBASEINFO } from './constants' 11 | 12 | export const setuserinfo = (data)=>({type:SET_USERINFO,data}) 13 | export const setprojectbaseinfo = (data)=>({type:SET_PROJECTBASEINFO,data}) 14 | -------------------------------------------------------------------------------- /web/src/store/constants.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2021-08-13 01:12:11 4 | * @LastEditTime: 2021-09-17 13:50:51 5 | * @LastEditors: Please set LastEditors 6 | * @Description: In User Settings Edit 7 | * @FilePath: \OpenItem\web\src\store\user\constants.js 8 | */ 9 | const SET_TOKEN = "setToken" 10 | const CLEAR_TOKEN = "clearToken" 11 | const SET_USERINFO = "setuserinfo" 12 | const SET_PROJECTBASEINFO = "setprojectbaseinfo" 13 | 14 | module.exports = { 15 | SET_TOKEN, 16 | CLEAR_TOKEN, 17 | SET_USERINFO, 18 | SET_PROJECTBASEINFO 19 | } -------------------------------------------------------------------------------- /web/src/store/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2021-08-13 01:12:32 4 | * @LastEditTime: 2021-08-13 01:23:29 5 | * @LastEditors: Please set LastEditors 6 | * @Description: In User Settings Edit 7 | * @FilePath: \OpenItem\web\src\store\user\index.js 8 | */ 9 | import { createStore } from 'redux'; 10 | import reducer from './reducer'; 11 | 12 | const store = createStore(reducer); 13 | 14 | export default store; 15 | -------------------------------------------------------------------------------- /web/src/store/reducer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2021-08-13 00:58:37 4 | * @LastEditTime: 2021-09-17 13:46:36 5 | * @LastEditors: Please set LastEditors 6 | * @Description: In User Settings Edit 7 | * @FilePath: \OpenItem\web\src\store\user\reduce.js 8 | */ 9 | import { SET_PROJECTBASEINFO, SET_USERINFO } from './constants' 10 | import { getCookie, setCookie } from '../utils/cookies' 11 | import { getStorage, setStorage } from '../utils/storage' 12 | 13 | const userState = { 14 | token:getCookie('token'), 15 | userInfo:getStorage('userInfo'), 16 | currentProjectBaseInfo:getStorage('projectBaseInfo') 17 | } 18 | 19 | export default function userReduce(state=userState,action){ 20 | switch(action.type){ 21 | case SET_USERINFO: 22 | setCookie('token',action.data.message) 23 | setStorage('userInfo',{...action.data.data.profile,Id:action.data.data.uuid}) 24 | return {...state, userInfo:getStorage('userInfo'),token:getCookie('token')} 25 | case SET_PROJECTBASEINFO: 26 | setStorage('projectBaseInfo',action.data) 27 | return {...state, userInfo:getStorage('userInfo'),token:getCookie('token'),projectBaseInfo:getStorage('projectBaseInfo')} 28 | default: 29 | return state 30 | } 31 | } -------------------------------------------------------------------------------- /web/src/utils/cookies.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2021-08-12 00:25:43 4 | * @LastEditTime: 2021-08-12 23:18:32 5 | * @LastEditors: Please set LastEditors 6 | * @Description: 操作Cookie 7 | * @FilePath: \OpenItem\web\src\utils\cookies.js 8 | */ 9 | 10 | 11 | 12 | 13 | 14 | 15 | /** 16 | * @description: 存值 17 | * @param {*} name 18 | * @param {*} value 19 | * @return {*} 20 | */ 21 | function setCookie(name,value){ 22 | var d = new Date(); 23 | d.setTime(d.getTime()+(60*60*1000)); //保存一个小时 24 | var expires = "expires="+d.toGMTString(); 25 | document.cookie = name+"="+value+"; "+expires; 26 | } 27 | 28 | 29 | /** 30 | * @description: 获取指定Cookie的值 31 | * @param {*} name 32 | * @return {*} 33 | */ 34 | function getCookie(name){ 35 | name = name + "="; 36 | var ca = document.cookie.split(';'); 37 | for(var i=0; i { 18 | if (checkCookie('token')) { 19 | //Authorization Bearer 20 | config.headers['Token'] = getCookie('token') 21 | } 22 | return config 23 | }, 24 | error => { 25 | return Promise.reject(error) 26 | } 27 | ) 28 | 29 | request.interceptors.response.use( 30 | response => { 31 | const code = response.data.operation_code 32 | if(code===1000||!code){ 33 | // const res = {...response.data.data,token:response.data.message||''} 34 | if(!code){ 35 | return response 36 | }else{ 37 | const res = {...response.data} 38 | return res 39 | } 40 | }else if(code===2000){ 41 | return Promise.reject(response.data) 42 | }else{ 43 | return Promise.reject(response.data) 44 | } 45 | }, 46 | error => { 47 | console.log(error) 48 | return Promise.reject(error.response.data||error.response) 49 | } 50 | ) 51 | 52 | export default request 53 | -------------------------------------------------------------------------------- /web/src/utils/storage.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2021-08-14 00:09:49 4 | * @LastEditTime: 2021-08-25 00:24:32 5 | * @LastEditors: Please set LastEditors 6 | * @Description: In User Settings Edit 7 | * @FilePath: \OpenItem\web\src\utils\storage.js 8 | */ 9 | 10 | function getStorage(name) { 11 | return localStorage.getItem(name)===null?null:JSON.parse(localStorage.getItem(name)) 12 | } 13 | 14 | function setStorage(name,value) { 15 | localStorage.setItem(name,JSON.stringify(value)) 16 | } 17 | 18 | function checkStorage(name) { 19 | return localStorage.getItem(name)!==null 20 | } 21 | 22 | function delStorage(name) { 23 | localStorage.removeItem(name) 24 | } 25 | 26 | module.exports = { 27 | getStorage, 28 | setStorage, 29 | checkStorage, 30 | delStorage 31 | } -------------------------------------------------------------------------------- /web/src/views/Home/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Layout, Menu, Avatar, Button } from 'antd'; 3 | import DocumentTitle from 'react-document-title' 4 | import {Switch, Route,Redirect} from 'react-router-dom' 5 | import { UserOutlined } from '@ant-design/icons'; 6 | import PendingTasks from '../PendingTasks' 7 | import ProjectManagement from '../ProjectManagement' 8 | import PropositionPaper from '../PropositionPaper' 9 | import NotFound from '../errors/404' 10 | import Forbid from '../errors/402' 11 | import store from '../../store'; 12 | import './index.less' 13 | 14 | 15 | const { Header , Content } = Layout; 16 | 17 | export default class index extends Component { 18 | 19 | state = { 20 | menuCurrentSelected:"pending-tasks" 21 | } 22 | 23 | funcChange = (e)=>{ 24 | this.setState({ 25 | menuCurrentSelected:e.key 26 | }) 27 | this.props.history.push(`/home/${e.key}`) 28 | } 29 | 30 | render() { 31 | return ( 32 | 33 | 34 |
35 |
36 |
37 |
38 |
39 | Landing 40 |
41 |
42 |
43 | 44 | 45 | 项目管理 46 | 47 | 48 | 人员管理 49 | 50 | 51 | 命题组卷 52 | 53 | 54 | 系统设置 55 | 56 | 57 |
58 |
59 | 60 | 61 |
62 |
63 | } size={24}/> 64 | {store.getState().userInfo.name} 65 | {/* stacker */} 66 |
67 |
68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
80 |
81 | ) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /web/src/views/Login/index.less: -------------------------------------------------------------------------------- 1 | [data-component=login-page]{ 2 | width: 100%; 3 | height: 100%; 4 | position: relative; 5 | background-image: url(../../asset/images/login_background.png); 6 | background-size: cover; 7 | background-repeat: no-repeat; 8 | background-color: #EEF4FF; 9 | overflow: hidden; 10 | > .login-box{ 11 | width: 6.4rem; 12 | height: 4.5rem; 13 | background: #FFFFFF; 14 | border-radius: .4rem; 15 | box-sizing: border-box; 16 | padding: .26rem .28rem .61rem .69rem; 17 | position: absolute; 18 | right: 1.69rem; 19 | top: 2.57rem; 20 | > .login-btn__box{ 21 | width: 100%; 22 | height: .52rem 23 | } 24 | > .login-btn__change{ 25 | margin-bottom: .06rem; 26 | > .ant-btn{ 27 | float: right; 28 | background-color: #FFC000; 29 | border-color: #FFC000; 30 | } 31 | } 32 | > .login-btn__operation{ 33 | display: flex; 34 | width: 4.43rem; 35 | > .space-box{ 36 | flex: 0 0 29.16666667%; 37 | } 38 | } 39 | > .login-form{ 40 | width: 100%; 41 | height: calc(100% - 1.76rem); 42 | display: flex; 43 | align-content: center; 44 | flex-wrap: wrap; 45 | > .ant-form{ 46 | width: 4.43rem; 47 | > .ant-form-item{ 48 | > .ant-form-item-label{ 49 | box-sizing: border-box; 50 | margin-right: .31rem; 51 | > label{ 52 | font-size: .24rem; 53 | font-weight: 600; 54 | &::before{ 55 | display: none; 56 | } 57 | } 58 | } 59 | } 60 | } 61 | > .more-choice-box{ 62 | width: 4.43rem; 63 | text-align: right; 64 | > a{ 65 | color: #55BAFF; 66 | border-bottom: .01rem solid #55BAFF; 67 | padding-bottom: .01rem; 68 | font-size: .16rem; 69 | font-weight: 400; 70 | } 71 | } 72 | } 73 | > .state-box{ 74 | width: 100%; 75 | height: .38rem; 76 | box-sizing: border-box; 77 | padding-left: .36rem; 78 | margin-bottom: .28rem; 79 | > .message{ 80 | width: 100%; 81 | height: 100%; 82 | display: flex; 83 | align-items: center; 84 | svg{ 85 | width: .2744rem; 86 | height: .2744rem; 87 | color: #FF8C00; 88 | margin-right: .15rem; 89 | } 90 | > .content{ 91 | font-size: .16rem; 92 | color: #FF8C00; 93 | } 94 | } 95 | } 96 | } 97 | > .login-describe{ 98 | width: 3.2rem; 99 | position: absolute; 100 | top: 3rem; 101 | left: 1.83rem; 102 | box-sizing: border-box; 103 | padding-top: .3rem; 104 | > h1{ 105 | font-weight: bold; 106 | color: #1890FF; 107 | font-size: .38rem; 108 | } 109 | > .describe-item{ 110 | word-wrap: break-word; 111 | color: #1890FF; 112 | font-size: .18rem; 113 | } 114 | } 115 | } 116 | 117 | .ant-spin-nested-loading,.ant-spin-container{ 118 | height: 100%; 119 | } 120 | 121 | -------------------------------------------------------------------------------- /web/src/views/PendingTasks/index.less: -------------------------------------------------------------------------------- 1 | [data-component=pending-tasks-page]{ 2 | width: 100%; 3 | height: 100%; 4 | > .ant-layout-header{ 5 | width: 100%; 6 | height: .64rem; 7 | background: #FFFFFF; 8 | display: flex; 9 | align-items: center; 10 | justify-content: space-between; 11 | box-sizing: border-box; 12 | padding: 0rem .08rem; 13 | line-height: .64rem; 14 | > .title{ 15 | font-size: .16rem; 16 | color: #000000D9; 17 | } 18 | > .right-box{ 19 | display: flex; 20 | align-items: center; 21 | height: .64rem; 22 | > .ant-dropdown-trigger,.ant-input-search{ 23 | margin-right: .16rem; 24 | } 25 | > .ant-dropdown-trigger{ 26 | font-size: .14rem; 27 | } 28 | } 29 | } 30 | > .ant-layout-content{ 31 | background-color: #FFFFFF; 32 | .ant-table-header{ 33 | > .table{ 34 | height: .48rem; 35 | } 36 | .ant-table-cell::before{ 37 | display: none; 38 | } 39 | } 40 | .ant-table-row{ 41 | height: .48rem; 42 | > .ant-table-cell{ 43 | height: .48rem; 44 | padding: 0; 45 | font-size: 14px; 46 | } 47 | } 48 | } 49 | > .ant-layout-footer{ 50 | padding: 0rem .2rem 0rem 0rem; 51 | height: .5rem; 52 | background-color: #ffffff; 53 | display: flex; 54 | align-items: center; 55 | flex-direction: row-reverse; 56 | } 57 | } -------------------------------------------------------------------------------- /web/src/views/ProjectManagement/index.less: -------------------------------------------------------------------------------- 1 | [data-component=project-management-page]{ 2 | width: 100%; 3 | height: 100%; 4 | background-color: #EEEEEE; 5 | overflow-y: scroll; 6 | > .ant-page-header{ 7 | background-color: #FFFFFF; 8 | padding: .16rem 0rem 0rem 0rem; 9 | > .ant-page-header-heading{ 10 | box-sizing: border-box; 11 | padding: 0rem .24rem; 12 | } 13 | > .ant-page-header-content{ 14 | padding-left: .564rem; 15 | } 16 | .ant-page-header-heading-title{ 17 | font-size: .2rem; 18 | font-weight: 500; 19 | line-height: .28rem; 20 | color: #000000; 21 | } 22 | .ant-page-header-heading-sub-title{ 23 | font-size: .14rem; 24 | line-height: .22rem; 25 | color: rgba(0, 0, 0, 0.85); 26 | } 27 | .ant-tabs-nav-list{ 28 | padding-left: .564rem 29 | } 30 | .ant-descriptions{ 31 | width: 6.62rem; 32 | } 33 | .ant-tabs-tab-btn{ 34 | font-size: .14rem; 35 | } 36 | } 37 | > .container{ 38 | width: 100%; 39 | } 40 | .ant-spin-nested-loading{ 41 | height: auto; 42 | background-color: white; 43 | } 44 | .page-content-box{ 45 | width: 100%; 46 | box-sizing: border-box; 47 | padding: .3rem; 48 | } 49 | } -------------------------------------------------------------------------------- /web/src/views/PropositionPaper/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import {Switch, Route,Redirect} from 'react-router-dom' 3 | import CreatePaper from './views/CreatePaper' 4 | import UploadQuestions from './views/UploadQuestions' 5 | import Home from './views/Home/home' 6 | 7 | export default class index extends Component { 8 | render() { 9 | return ( 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | ) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /web/src/views/errors/402.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import DocumentTitle from 'react-document-title' 3 | import Rockets from '../../asset/images/Rockets.png' 4 | import Cloude from '../../asset/images/Cloud.png' 5 | import Unhapply from '../../asset/images/Unhapply.png' 6 | import './index.less' 7 | 8 | export default class index extends Component { 9 | render() { 10 | return ( 11 | 12 |
13 | 火箭图 14 | 云 15 | 不高兴 16 |
17 | 402 18 |

19 | 错误原因错误原因错误原因错误原因 20 | 错误原因错误原因错误原因错误原因 21 | 错误原因错误原因错误原因错误原因 22 |

23 |
24 |
25 | 26 | ) 27 | } 28 | } -------------------------------------------------------------------------------- /web/src/views/errors/404.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import DocumentTitle from 'react-document-title' 3 | import Rockets from '../../asset/images/Rockets.png' 4 | import CryingFace from '../../asset/images/Crying_face.png' 5 | import FluExpression from '../../asset/images/Flu_expression.png' 6 | import './index.less' 7 | 8 | export default class index extends Component { 9 | render() { 10 | return ( 11 | 12 |
13 | 火箭图 14 | 哭脸图 15 | 尴尬图 16 |
17 |
18 |
19 |
20 | 404 21 |

22 | 错误原因错误原因错误原因错误原因 23 | 错误原因错误原因错误原因错误原因 24 | 错误原因错误原因错误原因错误原因 25 |

26 |
27 |
28 | 29 | ) 30 | } 31 | } -------------------------------------------------------------------------------- /web/src/views/errors/index.less: -------------------------------------------------------------------------------- 1 | [data-component=error_page__404]{ 2 | width: 100%; 3 | min-height: 10.8rem; 4 | position: relative; 5 | background-color: #FFFFFF; 6 | > .pattern{ 7 | position: absolute; 8 | } 9 | > .pattern__1{ 10 | width: 3.2032rem; 11 | height: 3.2042rem; 12 | top: 1.637rem; 13 | left: 4.34rem; 14 | } 15 | > .pattern__2{ 16 | width: 1.8731rem; 17 | height: 1.8731rem; 18 | left: 3.0534rem; 19 | top: 4.3634rem; 20 | } 21 | > .pattern__3{ 22 | width: 1.89rem; 23 | height: 1.89rem; 24 | left: 7.975rem; 25 | top: 3.4681rem; 26 | } 27 | > .pattern__4{ 28 | width: 2.88rem; 29 | height: 2.88rem; 30 | left: 2.33rem; 31 | top: 3.47rem; 32 | } 33 | > .pattern__5{ 34 | width: 1.0625rem; 35 | height: 1.0625rem; 36 | left: 7.23rem; 37 | top: 4.44rem; 38 | } 39 | > .line{ 40 | background-color: #597EF7; 41 | } 42 | > .line__1{ 43 | width: 2.41rem; 44 | height: .23rem; 45 | left: 6.2rem; 46 | top: 5.4rem; 47 | } 48 | > .line__2{ 49 | width: 2.41rem; 50 | height: .06rem; 51 | left: 6.2rem; 52 | top: 5.7rem; 53 | } 54 | > .line__3{ 55 | width: .88rem; 56 | height: .17rem; 57 | left: 4.66rem; 58 | top: 6.24rem; 59 | } 60 | > .line__4{ 61 | width: .88rem; 62 | height: .23rem; 63 | left: 4.66rem; 64 | top: 6.45rem; 65 | } 66 | > .line__5{ 67 | width: 1.0625rem; 68 | height: .06rem; 69 | left: 7.23rem; 70 | top: 5.6681rem; 71 | } 72 | > .title{ 73 | font-size: 1.44rem; 74 | font-weight: 400; 75 | color:#597EF7; 76 | right: 5.74rem; 77 | top: 3.09rem; 78 | line-height: 1.6875rem; 79 | } 80 | > .describe{ 81 | width: 3.84rem; 82 | font-size: .24rem; 83 | line-height: .2813rem; 84 | color: #E5E5E5; 85 | right: 4.33rem; 86 | top: 5.0rem; 87 | } 88 | } --------------------------------------------------------------------------------