refactor: remove redux (#20)

* feat: add store

* feat: add connect

* feat: add loading

* fix: remember menu item

* fix: page size

* refactor: delete api login check

* refactor: set msg err.Error()

* refactor: use function to judge user type

* feat: add global filter

* fix: check project teacher

* refactor: get images from cdn

* refactor: get icon from cdn

* refactor: modify header bar

* refactor: get images from cdn

* fix: fix redux connect

* fix: fix logo size

* feat: add favourite

* fix: favourite menu item

* feat: add loading

* fix: use tag to distinguish user types

* refactor: remove redux

* refactor: ignore commentsRouter*.go
This commit is contained in:
lbaf23 2021-08-13 10:56:22 +08:00 committed by GitHub
parent ae3ac9139f
commit 36506b8e94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 499 additions and 975 deletions

20
.gitignore vendored
View File

@ -1,13 +1,10 @@
# Dependency directories (remove the comment below to include it)
# vendor/
### Go template
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
*.swp
# Test binary, built with `go test -c`
*.test
@ -18,13 +15,16 @@
# Dependency directories (remove the comment below to include it)
# vendor/
*.zip
.idea/
*.iml
tmp/
tmpFiles/
*.tmp
.idea
.vscode
tmp
logs/
files/
lastupdate.tmp
routers/commentsRouter*.go
### Config file

View File

@ -2,6 +2,7 @@ package controllers
import (
"OpenPBL/models"
"OpenPBL/util"
"strconv"
)
@ -21,21 +22,13 @@ type ChaptersResponse struct {
// @router /:id/chapters [get]
func (p *ProjectController) GetProjectChapters() {
user := p.GetSessionUser()
if user == nil {
p.Data["json"] = ChaptersResponse{
Code: 401,
Msg: "请先登录",
}
p.ServeJSON()
return
}
uid := ""
show := false
if user.Tag == "student" {
if util.IsStudent(user) {
uid = user.Name
show = true
}
if user.Tag == "teacher" {
if util.IsTeacher(user) {
uid = p.GetString("studentId")
if uid != "" {
show = true

View File

@ -47,16 +47,6 @@ type MessagesResponse struct {
// @router / [get]
func (m *MessageController) GetUserMessages() {
user := m.GetSessionUser()
var resp ProjectResponse
if user == nil {
resp = ProjectResponse{
Code: 401,
Msg: "请先登录",
}
m.Data["json"] = resp
m.ServeJSON()
return
}
from, err := m.GetInt("from")
if err != nil {
from = 0
@ -99,16 +89,6 @@ func (m *MessageController) GetUserMessages() {
// @router /:messageId/read [post]
func (m *MessageController) ReadUserMessage() {
user := m.GetSessionUser()
var resp ProjectResponse
if user == nil {
resp = ProjectResponse{
Code: 401,
Msg: "请先登录",
}
m.Data["json"] = resp
m.ServeJSON()
return
}
uid := util.GetUserId(user)
mid, err := m.GetInt64(":messageId")
err = models.ReadMessage(mid, uid)
@ -134,16 +114,6 @@ func (m *MessageController) ReadUserMessage() {
// @router /:messageId/delete [post]
func (m *MessageController) DeleteUserMessage() {
user := m.GetSessionUser()
var resp ProjectResponse
if user == nil {
resp = ProjectResponse{
Code: 401,
Msg: "请先登录",
}
m.Data["json"] = resp
m.ServeJSON()
return
}
uid := util.GetUserId(user)
mid, err := m.GetInt64(":messageId")
msg := models.Message{
@ -172,16 +142,6 @@ func (m *MessageController) DeleteUserMessage() {
// @router /read-all [post]
func (m *MessageController) ReadAllUserMessage() {
user := m.GetSessionUser()
var resp ProjectResponse
if user == nil {
resp = ProjectResponse{
Code: 401,
Msg: "请先登录",
}
m.Data["json"] = resp
m.ServeJSON()
return
}
uid := util.GetUserId(user)
err := models.ReadAllMessage(uid)
if err != nil {

View File

@ -44,38 +44,26 @@ type ProjectResponse struct {
// @Failure 400
// @router /:id [get]
func (p *ProjectController) GetProjectDetail() {
pid := p.GetString(":id")
pid, err := p.GetInt64(":id")
user := p.GetSessionUser()
var resp ProjectResponse
if user == nil {
resp = ProjectResponse{
Code: 401,
Msg: "请先登录",
}
p.Data["json"] = resp
p.ServeJSON()
return
}
uid := util.GetUserId(user)
var err error
var project models.ProjectDetail
if user.Tag == "student" {
if util.IsStudent(user) {
project, err = models.GetProjectByPidForStudent(pid, uid)
} else if user.Tag == "teacher" {
project, err = models.GetProjectByPidForTeacher(pid)
} else if util.IsTeacher(user) {
project, err = models.GetProjectByPidForTeacher(pid, uid)
}
if err != nil {
resp = ProjectResponse{
p.Data["json"] = ProjectResponse{
Code: 400,
Msg: err.Error(),
}
} else {
resp = ProjectResponse{
p.Data["json"] = ProjectResponse{
Code: 200,
Project: project,
}
}
p.Data["json"] = resp
p.ServeJSON()
}
@ -90,16 +78,7 @@ func (p *ProjectController) GetProjectDetail() {
func (p *ProjectController) CreateProject() {
user := p.GetSessionUser()
var resp Response
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
p.Data["json"] = resp
p.ServeJSON()
return
}
if user.Tag != "teacher" {
if !util.IsTeacher(user) {
resp = Response{
Code: 403,
Msg: "非法用户",
@ -140,16 +119,7 @@ func (p *ProjectController) CreateProject() {
func (p *ProjectController) UpdateProject() {
user := p.GetSessionUser()
var resp Response
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
p.Data["json"] = resp
p.ServeJSON()
return
}
if user.Tag != "teacher" {
if !util.IsTeacher(user) {
resp = Response{
Code: 403,
Msg: "非法用户",
@ -207,16 +177,7 @@ func (p *ProjectController) UpdateProject() {
func (p *ProjectController) UpdateProjectWeight() {
user := p.GetSessionUser()
var resp Response
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
p.Data["json"] = resp
p.ServeJSON()
return
}
if user.Tag != "teacher" {
if !util.IsTeacher(user) {
resp = Response{
Code: 403,
Msg: "非法用户",
@ -274,16 +235,7 @@ func (u *ProjectController) PublishProject() {
pid, err := u.GetInt64(":id")
var resp Response
user := u.GetSessionUser()
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
u.Data["json"] = resp
u.ServeJSON()
return
}
if user.Tag != "teacher" {
if !util.IsTeacher(user) {
resp = Response{
Code: 403,
Msg: "非法的用户",
@ -327,16 +279,7 @@ func (u *ProjectController) CloseProject() {
pid, err := u.GetInt64(":id")
var resp Response
user := u.GetSessionUser()
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
u.Data["json"] = resp
u.ServeJSON()
return
}
if user.Tag != "teacher" {
if !util.IsTeacher(user) {
resp = Response{
Code: 403,
Msg: "非法的用户",
@ -380,16 +323,7 @@ func (u *ProjectController) DeleteProject() {
pid, err := u.GetInt64(":id")
var resp Response
user := u.GetSessionUser()
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
u.Data["json"] = resp
u.ServeJSON()
return
}
if user.Tag != "teacher" {
if !util.IsTeacher(user) {
resp = Response{
Code: 403,
Msg: "非法的用户",
@ -429,16 +363,6 @@ func (u *ProjectController) RemoveStudent() {
pid, err := u.GetInt64(":projectId")
sid := u.GetString(":studentId")
var resp Response
user := u.GetSessionUser()
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
u.Data["json"] = resp
u.ServeJSON()
return
}
l := &models.LearnProject{
StudentId: sid,
ProjectId: pid,
@ -536,3 +460,52 @@ func (p *ProjectController) GetProjectStudents() {
}
p.ServeJSON()
}
// AddFavouriteProject
// @Title
// @Description
// @Param projectId path string true ""
// @Success 200 {object} Response
// @Failure 401
// @router /:projectId/favourite/add [post]
func (p *ProjectController) AddFavouriteProject() {
pid, err := p.GetInt64(":projectId")
uid := util.GetUserId(p.GetSessionUser())
err = models.AddFavourite(uid, pid)
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{
Code: 200,
Msg: "收藏成功",
}
}
p.ServeJSON()
}
// RemoveFavouriteProject
// @Title
// @Description
// @Param projectId path string true ""
// @Success 200 {object} Response
// @Failure 401
// @router /:projectId/favourite/remove [post]
func (p *ProjectController) RemoveFavouriteProject() {
pid, err := p.GetInt64(":projectId")
uid := util.GetUserId(p.GetSessionUser())
err = models.RemoveFavourite(uid, pid)
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{
Code: 200,
Msg: "移除成功",
}
}
p.ServeJSON()
}

View File

@ -71,31 +71,23 @@ func (pl *ProjectListController) GetUserProjectList() {
text := pl.GetString("text")
user := pl.GetSessionUser()
var data ProjectList
if user == nil {
data = ProjectList{
Code: 401,
Msg: "请先登录",
}
pl.Data["json"] = data
pl.ServeJSON()
return
}
uid := util.GetUserId(user)
var data ProjectList
var projects []models.ProjectDetail
var count int64
if user.Tag == "student" {
if util.IsStudent(user) {
if t == "learning" {
projects, count, err = models.GetMyProjectListBySid(uid, from, size, subject, skill, text, orderBy, orderType, true)
} else if t == "finished" {
projects, count, err = models.GetMyProjectListBySid(uid, from, size, subject, skill, text, orderBy, orderType, false)
} else if t == "public" {
projects, count, err = models.GetPublicProjectListForStudent(uid, from, size, subject, skill, text, orderBy, orderType)
projects, count, err = models.GetPublicProjectListForStudent(uid, from, size, subject, skill, text, orderBy, orderType, false)
} else if t == "favourite" {
projects, count, err = models.GetPublicProjectListForStudent(uid, from, size, subject, skill, text, orderBy, orderType, true)
}
} else if user.Tag == "teacher" {
} else if util.IsTeacher(user) {
if t == "editing" {
projects, count, err = models.GetMyProjectListByTid(uid, from, size, subject, skill, text, orderBy, orderType, false, false)
} else if t == "published" {
@ -103,7 +95,9 @@ func (pl *ProjectListController) GetUserProjectList() {
} else if t == "finished" {
projects, count, err = models.GetMyProjectListByTid(uid, from, size, subject, skill, text, orderBy, orderType, true, true)
} else if t == "public" {
projects, count, err = models.GetPublicProjectListForTeacher(uid, from, size, subject, skill, text, orderBy, orderType)
projects, count, err = models.GetPublicProjectListForTeacher(uid, from, size, subject, skill, text, orderBy, orderType, false)
} else if t == "favourite" {
projects, count, err = models.GetPublicProjectListForTeacher(uid, from, size, subject, skill, text, orderBy, orderType, true)
}
}
data = ProjectList{

View File

@ -123,7 +123,7 @@ func (p *ProjectController) UpdateChapterSection() {
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: "更新失败",
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{
@ -158,7 +158,7 @@ func (p *ProjectController) DeleteChapterSection() {
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: "删除失败",
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{

View File

@ -39,16 +39,7 @@ func (u *StudentController) LearnProject() {
pid, err := u.GetInt64(":projectId")
var resp Response
user := u.GetSessionUser()
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
u.Data["json"] = resp
u.ServeJSON()
return
}
if user.Tag != "student" {
if !util.IsStudent(user) {
resp = Response{
Code: 403,
Msg: "非法的用户",
@ -94,16 +85,7 @@ func (u *StudentController) ExitProject() {
pid, err := u.GetInt64(":projectId")
var resp Response
user := u.GetSessionUser()
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
u.Data["json"] = resp
u.ServeJSON()
return
}
if user.Tag != "student" {
if !util.IsStudent(user) {
resp = Response{
Code: 403,
Msg: "非法的用户",
@ -167,16 +149,7 @@ func (u *StudentController) FinishedProject() {
func (u *StudentController) GetLearnSection() {
var resp Response
user := u.GetSessionUser()
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
u.Data["json"] = resp
u.ServeJSON()
return
}
if user.Tag != "student" {
if !util.IsStudent(user) {
resp = Response{
Code: 403,
Msg: "非法的用户",
@ -213,16 +186,7 @@ func (u *StudentController) GetLearnSection() {
func (u *StudentController) UpdateLearnSection() {
var resp Response
user := u.GetSessionUser()
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
u.Data["json"] = resp
u.ServeJSON()
return
}
if user.Tag != "student" {
if !util.IsStudent(user) {
resp = Response{
Code: 403,
Msg: "非法的用户",
@ -265,16 +229,7 @@ func (u *StudentController) UpdateLearnSection() {
func (u *StudentController) GetLastLearnSection() {
var resp Response
user := u.GetSessionUser()
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
u.Data["json"] = resp
u.ServeJSON()
return
}
if user.Tag != "student" {
if !util.IsStudent(user) {
resp = Response{
Code: 200,
Msg: "",

View File

@ -18,16 +18,7 @@ import (
func (p *ProjectController) CreateSubmit() {
var resp Response
user := p.GetSessionUser()
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
p.Data["json"] = resp
p.ServeJSON()
return
}
if user.Tag != "student" {
if !util.IsStudent(user) {
resp = Response{
Code: 403,
Msg: "非法用户",
@ -85,19 +76,9 @@ func (p *ProjectController) CreateSubmit() {
// @Failure 403 body is empty
// @router /:projectId/task/:taskId/submit/:submitId [post]
func (p *ProjectController) UpdateSubmit() {
var resp Response
user := p.GetSessionUser()
if user == nil {
resp = Response{
Code: 401,
Msg: "请先登录",
}
p.Data["json"] = resp
p.ServeJSON()
return
}
var uid string
if user.Tag == "student" {
if util.IsStudent(user) {
uid = util.GetUserId(user)
}
tid, err := p.GetInt64(":taskId")
@ -120,7 +101,7 @@ func (p *ProjectController) UpdateSubmit() {
Scored: scored,
}
var c = make([]models.Choice, 0)
if user.Tag == "student" && f.SubmitType == "survey" {
if util.IsStudent(user) && f.SubmitType == "survey" {
err = json.Unmarshal([]byte(p.GetString("choices")), &c)
}
err = f.Update(c)

View File

@ -44,7 +44,7 @@ func (p *ProjectController) CreateSurvey() {
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: "创建失败",
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{
@ -79,7 +79,7 @@ func (p *ProjectController) UpdateSurvey() {
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: "更新失败",
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{
@ -114,7 +114,7 @@ func (p *ProjectController) CreateQuestion() {
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: "创建失败",
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{
@ -151,7 +151,7 @@ func (p *ProjectController) UpdateQuestion() {
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: "更新失败",
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{
@ -177,6 +177,7 @@ func (p *ProjectController) ExchangeQuestion() {
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{
@ -203,7 +204,7 @@ func (p *ProjectController) DeleteQuestion() {
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: "参数非法",
Msg: err.Error(),
}
p.ServeJSON()
return
@ -212,7 +213,7 @@ func (p *ProjectController) DeleteQuestion() {
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: "删除失败",
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{

View File

@ -23,26 +23,14 @@ type TaskResponse struct {
// @Failure 400
// @router /:projectId/section/:sectionId/tasks [get]
func (p *ProjectController) GetSectionTasksDetail() {
var resp TaskResponse
sid := p.GetString(":sectionId")
var learning bool
user := p.GetSessionUser()
if user == nil {
resp = TaskResponse{
Response: Response{
Code: 401,
Msg: "请先登录",
},
}
p.Data["json"] = resp
p.ServeJSON()
return
}
showCount := false
if user.Tag != "student" {
if !util.IsStudent(user) {
learning = false
}
if user.Tag == "teacher" {
if util.IsTeacher(user) {
showCount = true
}
uid := util.GetUserId(user)
@ -80,16 +68,6 @@ func (p *ProjectController) GetSectionTasksDetail() {
// @Failure 400
// @router /:projectId/tasks [get]
func (p *ProjectController) GetProjectTasks() {
user := p.GetSessionUser()
if user == nil {
p.Data["json"] = Response{
Code: 401,
Msg: "请先登录",
}
p.ServeJSON()
return
}
pid := p.GetString(":projectId")
tasks, err := models.GetProjectTasks(pid)
if err != nil {
@ -114,37 +92,22 @@ func (p *ProjectController) GetProjectTasks() {
// @Failure 400
// @router /:projectId/tasks-detail [get]
func (p *ProjectController) GetProjectTasksDetail() {
var resp TaskResponse
var learning bool
user := p.GetSessionUser()
if user == nil {
resp = TaskResponse{
Response: Response{
Code: 401,
Msg: "请先登录",
},
}
p.Data["json"] = resp
p.ServeJSON()
return
}
showSubmit := false
teacherScore := false
uid := util.GetUserId(user)
editable := true
showCount := false
pid := p.GetString(":projectId")
if user.Tag == "teacher" {
if util.IsTeacher(user) {
uid = p.GetString("studentId")
showSubmit = true
editable = false
teacherScore = true
showCount = true
}
if user.Tag != "student" {
if !util.IsStudent(user) {
learning = false
} else {
learning = models.IsLearningProject(pid, uid)
@ -209,7 +172,7 @@ func (p *ProjectController) CreateTask() {
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: "创建失败",
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{
@ -251,7 +214,7 @@ func (p *ProjectController) UpdateTask() {
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: "更新失败",
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{
@ -279,7 +242,7 @@ func (p *ProjectController) DeleteTask() {
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: "删除失败",
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{
@ -305,6 +268,7 @@ func (p *ProjectController) ExchangeTask() {
if err != nil {
p.Data["json"] = Response{
Code: 400,
Msg: err.Error(),
}
} else {
p.Data["json"] = Response{

View File

@ -82,6 +82,7 @@ func (a *Adapter) close() {
func (a *Adapter) createTable() {
err := a.Engine.Sync2(
new(Project),
new(Favourite),
new(LearnProject),
new(LearnSection),

View File

@ -31,9 +31,17 @@ type Project struct {
LearnMinuteWeight int `json:"learnMinuteWeight" xorm:"default 100"`
}
type Favourite struct {
ProjectId int64 `json:"projectId" xorm:"not null pk"`
UserId string `json:"userId" xorm:"not null pk"`
CreateAt time.Time `json:"createAt" xorm:"created"`
}
type ProjectDetail struct {
Project `xorm:"extends"`
Learning bool `json:"learning"`
Project `xorm:"extends"`
Learning bool `json:"learning"`
Created bool `json:"created"`
Favourite bool `json:"favourite"`
}
type ProjectSkill struct {
@ -55,15 +63,27 @@ func (p *ProjectSkill) GetEngine() *xorm.Session {
func (p *ProjectSubject) GetEngine() *xorm.Session {
return adapter.Engine.Table(p)
}
func (f *Favourite) GetEngine() *xorm.Session {
return adapter.Engine.Table(f)
}
func GetProjectByPidForTeacher(pid string) (pd ProjectDetail, err error) {
func GetProjectByPidForTeacher(pid int64, uid string) (pd ProjectDetail, err error) {
var p Project
c, err := (&Project{}).GetEngine().
ID(pid).
Get(&p)
favourite, _ := (&Favourite{}).GetEngine().
Exist(&Favourite{
ProjectId: pid,
UserId: uid,
})
created := uid == p.TeacherId
pd = ProjectDetail{
Project: p,
Learning: false,
Created: created,
Favourite: favourite,
}
if !c {
err = errors.New("404")
@ -71,11 +91,17 @@ func GetProjectByPidForTeacher(pid string) (pd ProjectDetail, err error) {
return
}
func GetProjectByPidForStudent(pid string, uid string) (pd ProjectDetail, err error) {
func GetProjectByPidForStudent(pid int64, uid string) (pd ProjectDetail, err error) {
c, err := (&Project{}).GetEngine().
Where("project.id = ?", pid).
Join("LEFT OUTER", LearnProject{}, "project.id = learn_project.project_id and student_id = ?", uid).
Get(&pd)
favourite, _ := (&Favourite{}).GetEngine().
Exist(&Favourite{
ProjectId: pid,
UserId: uid,
})
pd.Favourite = favourite
if !c {
err = errors.New("404")
}
@ -155,4 +181,21 @@ func UpdateClosed(p Project) (err error) {
Cols("closed", "closed_at").
Update(p)
return
}
func AddFavourite(uid string, pid int64) (err error) {
_, err = (&Favourite{}).GetEngine().Insert(Favourite{
ProjectId: pid,
UserId: uid,
CreateAt: time.Time{},
})
return
}
func RemoveFavourite(uid string, pid int64) (err error) {
_, err = (&Favourite{}).GetEngine().Delete(Favourite{
ProjectId: pid,
UserId: uid,
})
return
}

View File

@ -38,23 +38,33 @@ func GetMyProjectListBySid(sid string, from int, size int,
}
func GetPublicProjectListForStudent(sid string, from int, size int,
subject string, skill string, text string, orderBy string, orderType string) (p []ProjectDetail, rows int64, err error) {
subject string, skill string, text string, orderBy string, orderType string, favourite bool) (p []ProjectDetail, rows int64, err error) {
const baseSql = `
select %s from (
select * from project where project.published = true and project.closed = false
%s %s %s
select * from project where project.published = true and project.closed = false
%s %s %s %s
) as p1 left join learn_project on (
p1.id = learn_project.project_id and learn_project.student_id = '%s'
p1.id = learn_project.project_id and learn_project.student_id = '%s'
)
`
const pageSql = " order by p1.%s %s limit %d, %d "
e0 := ""
if favourite {
e0 = `
and exists (
select favourite.project_id from favourite where favourite.project_id = project.id and favourite.user_id = '%s'
)
`
e0 = fmt.Sprintf(e0, sid)
}
e1 := getSubjectExistSql(subject)
e2 := getSkillExistSql(skill)
e3 := getTextSql(text)
sql1 := fmt.Sprintf(baseSql, "*", e1, e2, e3, sid) +
sql1 := fmt.Sprintf(baseSql, "*", e0, e1, e2, e3, sid) +
fmt.Sprintf(pageSql, orderBy, orderType, from, size)
sql2 := fmt.Sprintf(baseSql, "count(*)", e1, e2, e3, sid)
sql2 := fmt.Sprintf(baseSql, "count(*)", e0, e1, e2, e3, sid)
err = adapter.Engine.
SQL(sql1).
@ -95,16 +105,27 @@ func GetMyProjectListByTid(tid string, from int, size int,
}
func GetPublicProjectListForTeacher(sid string, from int, size int,
subject string, skill string, text string, orderBy string, orderType string) (p []ProjectDetail, rows int64, err error) {
baseSql := "select %s from project where published = true and closed = false %s %s %s "
subject string, skill string, text string, orderBy string, orderType string, favourite bool) (p []ProjectDetail, rows int64, err error) {
baseSql := "select %s from project where published = true and closed = false %s %s %s %s "
pageSql := " order by %s %s limit %d, %d "
e0 := ""
if favourite {
e0 = `
and exists (
select favourite.project_id from favourite where favourite.project_id = project.id and favourite.user_id = '%s'
)
`
e0 = fmt.Sprintf(e0, sid)
}
e1 := getSubjectExistSql(subject)
e2 := getSkillExistSql(skill)
e3 := getTextSql(text)
sql1 := fmt.Sprintf(baseSql, "*", e1, e2, e3) +
sql1 := fmt.Sprintf(baseSql, "*", e0, e1, e2, e3) +
fmt.Sprintf(pageSql, orderBy, orderType, from, size)
sql2 := fmt.Sprintf(baseSql, "count(*)", e1, e2, e3)
sql2 := fmt.Sprintf(baseSql, "count(*)", e0, e1, e2, e3)
err = adapter.Engine.
SQL(sql1).

View File

@ -1,514 +0,0 @@
package routers
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/context/param"
)
func init() {
beego.GlobalControllerRouter["OpenPBL/controllers:AuthController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:AuthController"],
beego.ControllerComments{
Method: "GetAccount",
Router: "/account",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:AuthController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:AuthController"],
beego.ControllerComments{
Method: "Login",
Router: "/login",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:AuthController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:AuthController"],
beego.ControllerComments{
Method: "Logout",
Router: "/logout",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:HomeController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:HomeController"],
beego.ControllerComments{
Method: "GetLatestProjects",
Router: "/projects/latest",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:MessageController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:MessageController"],
beego.ControllerComments{
Method: "GetUserMessages",
Router: "/",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:MessageController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:MessageController"],
beego.ControllerComments{
Method: "DeleteUserMessage",
Router: "/:messageId/delete",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:MessageController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:MessageController"],
beego.ControllerComments{
Method: "ReadUserMessage",
Router: "/:messageId/read",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:MessageController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:MessageController"],
beego.ControllerComments{
Method: "ReadAllUserMessage",
Router: "/read-all",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "CreateProject",
Router: "/",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "GetProjectDetail",
Router: "/:id",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "UpdateProject",
Router: "/:id",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "CreateProjectChapter",
Router: "/:id/chapter",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "GetProjectChapters",
Router: "/:id/chapters",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "CloseProject",
Router: "/:id/close",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "DeleteProject",
Router: "/:id/delete",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "PublishProject",
Router: "/:id/publish",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "UpdateProjectWeight",
Router: "/:id/weight",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "UpdateProjectChapter",
Router: "/:projectId/chapter/:chapterId",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "DeleteProjectChapter",
Router: "/:projectId/chapter/:chapterId/delete",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "CreateChapterSection",
Router: "/:projectId/chapter/:chapterId/section",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "UpdateChapterSection",
Router: "/:projectId/chapter/:chapterId/section/:sectionId",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "DeleteChapterSection",
Router: "/:projectId/chapter/:chapterId/section/:sectionId/delete",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "GetChapterSections",
Router: "/:projectId/chapter/:chapterId/sections",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "ExchangeChapterSection",
Router: "/:projectId/chapter/:chapterId/sections/exchange",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "ExchangeProjectChapter",
Router: "/:projectId/chapters/exchange",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "RemoveStudent",
Router: "/:projectId/remove/:studentId",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "GetSectionDetail",
Router: "/:projectId/section/:sectionId",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "GetSectionTasksDetail",
Router: "/:projectId/section/:sectionId/tasks",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "UpdateSectionsMinute",
Router: "/:projectId/sections-minute",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "GetProjectStudents",
Router: "/:projectId/students",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "CreateTask",
Router: "/:projectId/task",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "UpdateTask",
Router: "/:projectId/task/:taskId",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "DeleteTask",
Router: "/:projectId/task/:taskId/delete",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "CreateSubmit",
Router: "/:projectId/task/:taskId/submit",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "UpdateSubmit",
Router: "/:projectId/task/:taskId/submit/:submitId",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "CreateSurvey",
Router: "/:projectId/task/:taskId/survey",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "GetSurveyDetailByTaskId",
Router: "/:projectId/task/:taskId/survey",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "UpdateSurvey",
Router: "/:projectId/task/:taskId/survey/:sid",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "CreateQuestion",
Router: "/:projectId/task/:taskId/survey/:surveyId/question",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "UpdateQuestion",
Router: "/:projectId/task/:taskId/survey/:surveyId/question/:questionId",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "DeleteQuestion",
Router: "/:projectId/task/:taskId/survey/:surveyId/question/:questionId/delete",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "ExchangeQuestion",
Router: "/:projectId/task/:taskId/survey/:surveyId/questions/exchange",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "GetProjectTasks",
Router: "/:projectId/tasks",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "GetProjectTasksDetail",
Router: "/:projectId/tasks-detail",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
beego.ControllerComments{
Method: "ExchangeTask",
Router: "/:projectId/tasks/exchange",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectListController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectListController"],
beego.ControllerComments{
Method: "GetUserProjectList",
Router: "/:projectType",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ResourceController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ResourceController"],
beego.ControllerComments{
Method: "CreateResource",
Router: "/",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ResourceController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ResourceController"],
beego.ControllerComments{
Method: "GetResource",
Router: "/:id",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ResourceController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ResourceController"],
beego.ControllerComments{
Method: "UpdateResource",
Router: "/:id",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:ResourceController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ResourceController"],
beego.ControllerComments{
Method: "UpdateResourceContent",
Router: "/:id/content",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:StudentController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:StudentController"],
beego.ControllerComments{
Method: "ExitProject",
Router: "/exit/:projectId",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:StudentController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:StudentController"],
beego.ControllerComments{
Method: "FinishedProject",
Router: "/finished",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:StudentController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:StudentController"],
beego.ControllerComments{
Method: "GetLastLearnSection",
Router: "/last-learn/project/:projectId",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:StudentController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:StudentController"],
beego.ControllerComments{
Method: "LearnProject",
Router: "/learn/:projectId",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:StudentController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:StudentController"],
beego.ControllerComments{
Method: "GetLearnSection",
Router: "/project/:projectId/section/:sectionId",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["OpenPBL/controllers:StudentController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:StudentController"],
beego.ControllerComments{
Method: "UpdateLearnSection",
Router: "/project/:projectId/section/:sectionId",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
}

View File

@ -1,15 +1,34 @@
package routers
import (
"OpenPBL/controllers"
"github.com/astaxie/beego/context"
"net/http"
"os"
"strings"
)
func apiFilter(ctx *context.Context) {
urlPath := ctx.Request.URL.Path
if strings.HasPrefix(urlPath, "/api/project-list") ||
strings.HasPrefix(urlPath, "/api/project") ||
strings.HasPrefix(urlPath, "/api/message") ||
strings.HasPrefix(urlPath, "/api/resource") ||
strings.HasPrefix(urlPath, "/api/student") {
user := ctx.Input.Session("user")
if user == nil {
ctx.Output.JSON(controllers.Response{
Code: 401,
Msg: "请先登录",
}, true, false)
}
}
}
func TransparentStatic(ctx *context.Context) {
urlPath := ctx.Request.URL.Path
if strings.HasPrefix(urlPath, "/api") {
apiFilter(ctx)
return
}

View File

@ -5,3 +5,10 @@ import "github.com/casdoor/casdoor-go-sdk/auth"
func GetUserId(claims *auth.Claims) (id string) {
return claims.Name
}
func IsStudent(claims *auth.Claims) (b bool) {
return claims.Tag != "老师"
}
func IsTeacher(claims *auth.Claims) (b bool) {
return claims.Tag == "老师"
}

View File

@ -32,7 +32,6 @@
"react-github-button": "^0.1.11",
"react-lz-editor": "^0.12.1",
"react-pdf": "^5.3.2",
"react-redux": "^7.2.4",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"serve": "^12.0.0",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -2,14 +2,14 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="icon" href="https://cdn.open-ct.com/static/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="apple-touch-icon" href="https://cdn.open-ct.com/static/favicon.ico" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -1,17 +1,16 @@
import { Route, BrowserRouter, Switch } from "react-router-dom";
import './App.less';
import AuthCallback from "./pages/User/Auth/AuthCallback";
import HeaderLayout from "./pages/component/Layout/HeaderLayout";
function App() {
return (
<div className="App">
<BrowserRouter>
<div className="App">
<BrowserRouter>
<Route path="/" component={HeaderLayout} />
<Route exact path="/callback" component={AuthCallback} />
</BrowserRouter>
</div>
</BrowserRouter>
</div>
);
}

View File

@ -69,10 +69,22 @@ const ProjectApi = {
},
updateWeight(pid, data) {
return request({
url: `project/${pid}/weight`,
url: `/project/${pid}/weight`,
method: 'post',
data: qs.stringify(data)
})
},
addFavourite(pid) {
return request({
url: `/project/${pid}/favourite/add`,
method: 'post',
})
},
removeFavourite(pid) {
return request({
url: `/project/${pid}/favourite/remove`,
method: 'post',
})
}
}

View File

@ -14,17 +14,17 @@ class CarouselPBL extends React.Component {
super(props);
this.imgArray = [
{
img: require('../../Project/PublicProject/static/image/pbl1.png').default,
img: 'https://cdn.open-ct.com/task-resources//carousel-top-1.png',
title: '',
text: '',
},
{
img: require('../../Project/PublicProject/static/image/pbl2.png').default,
img: 'https://cdn.open-ct.com/task-resources//carousel-top-2.png',
title: '',
text: '',
},
{
img: require('../../Project/PublicProject/static/image/pbl3.png').default,
img: 'https://cdn.open-ct.com/task-resources//carousel-top-3.png',
title: '',
text: '',
},

View File

@ -55,7 +55,7 @@ function LatestProject(obj) {
borderTopLeftRadius: '10px',
borderTopRightRadius: '10px',
}}
fallback={require("../../assets/empty.png").default}
fallback={"https://cdn.open-ct.com/task-resources//openpbl-empty-project.png"}
/>
}
>

View File

@ -0,0 +1,13 @@
import React from 'react';
import ProjectList from '../component/ProjectList';
class FavouriteProject extends React.PureComponent {
render() {
return (
<ProjectList mode="favourite"/>
);
}
}
export default FavouriteProject;

View File

@ -1,20 +1,44 @@
import React from 'react';
import DocumentTitle from 'react-document-title';
import localStorage from "localStorage";
import {Link, Redirect, Route, Switch} from 'react-router-dom'
import {CheckCircleOutlined, CheckOutlined, CopyOutlined, HighlightOutlined, SyncOutlined, StarFilled} from "@ant-design/icons";
import PublishedProject from "../PublishedProject";
import EditingProject from "../EditingProject";
import FinishedProject from "../FinishedProject";
import LearningProject from "../LearningProject";
import {Affix, Button, Layout, Menu} from "antd";
import {CheckCircleOutlined, CheckOutlined, CopyOutlined, HighlightOutlined, SyncOutlined} from "@ant-design/icons";
import ProjectApi from "../../../api/ProjectApi";
import FavouriteProject from "../FavouriteProject";
class MyProject extends React.PureComponent {
state = {
type: localStorage.getItem('type'),
menu: ''
}
componentDidMount() {
this.changeMenu()
}
changeMenu = (e) => {
if (e !== undefined ) {
this.setState({menu: e.key})
return
}
const p = this.props.location.pathname
if (p.endsWith("/published")) {
this.setState({menu: 'published'})
} else if (p.endsWith("/editing")) {
this.setState({menu: 'editing'})
} else if (p.endsWith("/finished")) {
this.setState({menu: 'finished'})
} else if (p.endsWith("/learning")) {
this.setState({menu: 'learning'})
} else if (p.endsWith("/favourite")) {
this.setState({menu: 'favourite'})
}
}
createProject = e => {
ProjectApi.createProject()
.then((res) => {
@ -28,7 +52,7 @@ class MyProject extends React.PureComponent {
}
render() {
const {type} = this.state
const {menu} = this.state
return (
<DocumentTitle title="My Project">
<Layout style={{margin: '20px'}}>
@ -39,10 +63,12 @@ class MyProject extends React.PureComponent {
theme="light"
style={{backgroundColor: '#f2f4f5'}}
>
{type === 'teacher' ?
{this.props.account.tag === '老师' ?
<Menu
defaultSelectedKeys={['published']}
className="menu-bar"
selectedKeys={[menu]}
onClick={e=>this.changeMenu(e)}
mode="inline"
>
<Menu.Item key="published" icon={<CheckCircleOutlined/>}>
@ -60,11 +86,18 @@ class MyProject extends React.PureComponent {
已结束
</Link>
</Menu.Item>
<Menu.Item key="favourite" icon={<StarFilled />}>
<Link to="/my-project/favourite">
收藏夹
</Link>
</Menu.Item>
</Menu>
:
<Menu
defaultSelectedKeys={['learning']}
className="menu-bar"
selectedKeys={[menu]}
onClick={e=>this.changeMenu(e)}
mode="inline"
>
<Menu.Item key="learning" icon={<SyncOutlined/>}>
@ -77,9 +110,14 @@ class MyProject extends React.PureComponent {
已完成
</Link>
</Menu.Item>
<Menu.Item key="favourite" icon={<StarFilled />}>
<Link to="/my-project/favourite">
收藏夹
</Link>
</Menu.Item>
</Menu>
}
{type === 'teacher' ?
{this.props.account.tag === '老师' ?
<Button
type='primary'
shape='round'
@ -88,6 +126,7 @@ class MyProject extends React.PureComponent {
style={{
width: '180px',
margin: '10px',
marginTop: '30px',
}}
>创建项目</Button>
:
@ -96,7 +135,7 @@ class MyProject extends React.PureComponent {
</Layout.Sider>
</Affix>
<Layout.Content style={{marginLeft: '10px'}}>
{type === 'teacher' ?
{this.props.account.tag === '老师' ?
<Switch>
<Route exact path="/my-project" render={() => (
<Redirect to="/my-project/published"/>
@ -104,6 +143,7 @@ class MyProject extends React.PureComponent {
<Route exact path="/my-project/published" component={PublishedProject}/>
<Route exact path="/my-project/editing" component={EditingProject}/>
<Route exact path="/my-project/finished" component={FinishedProject}/>
<Route exact path="/my-project/favourite" component={FavouriteProject}/>
</Switch>
:
<Switch>
@ -112,6 +152,7 @@ class MyProject extends React.PureComponent {
)}/>
<Route exact path="/my-project/learning" component={LearningProject}/>
<Route exact path="/my-project/finished" component={FinishedProject}/>
<Route exact path="/my-project/favourite" component={FavouriteProject}/>
</Switch>
}
</Layout.Content>
@ -121,4 +162,4 @@ class MyProject extends React.PureComponent {
}
}
export default MyProject;
export default MyProject

View File

@ -20,11 +20,15 @@ function ProjectEvaluation(obj) {
const pid = obj.project.id
const published = obj.project.published
const type = localStorage.getItem("type")
const [chapters, setChapters] = useState([])
const [loadChapters, setLoadChapters] = useState(false)
const [defaultOpenedKeys, setDefaultOpenedKeys] = useState([])
const [openedKeys, setOpenedKeys] = useState([])
const [data, setData] = useState([])
const [tasks, setTasks] = useState([])
const [loadTasks, setLoadTasks] = useState(false)
const [learnMinuteWeight, setLearnMinuteWeight] = useState(obj.project.learnMinuteWeight)
@ -36,8 +40,10 @@ function ProjectEvaluation(obj) {
getTasks()
}, []);
const getTasks = () => {
setLoadTasks(true)
TaskApi.getProjectTasks(pid)
.then(res => {
setLoadTasks(false)
if (res.data.code === 200) {
if (res.data.data != null) {
setTasks(res.data.data)
@ -52,8 +58,10 @@ function ProjectEvaluation(obj) {
})
}
const getChapters = () => {
setLoadChapters(true)
ChapterApi.getProjectChapters(pid)
.then((res) => {
setLoadChapters(false)
if (res.data.chapters === null) {
setChapters([])
setDefaultOpenedKeys(0)
@ -223,7 +231,7 @@ function ProjectEvaluation(obj) {
});
return (
<div style={{textAlign: 'left', marginBottom: '30px'}} key="1">
<ReactEcharts option={getOptions()}/>
<ReactEcharts option={getOptions()} showLoading={loadTasks}/>
<div>
<Divider orientation="left">
<p className="evidence-title">章节学习时长</p>
@ -256,6 +264,8 @@ function ProjectEvaluation(obj) {
<List
size="large"
dataSource={item.sections}
locale={{emptyText: '空的'}}
loading={loadChapters}
renderItem={
(item, subIndex) => (
<List.Item>
@ -317,6 +327,7 @@ function ProjectEvaluation(obj) {
</Row>
<Divider/>
<Table
loading={loadTasks}
columns={getColumns()}
dataSource={tasks}
pagination={false}

View File

@ -2,14 +2,15 @@ import React, {useEffect, useState} from 'react';
import QueueAnim from 'rc-queue-anim';
import {Avatar, Button, message, Pagination, Popconfirm, Table} from "antd";
import {DeleteOutlined} from "@ant-design/icons"
import {Link} from "react-router-dom";
import ProjectApi from "../../../../api/ProjectApi";
import util from "../../../component/Util"
import {Link} from "react-router-dom";
function StudentAdmin(obj) {
const pid = obj.project.id
const [students, setStudents] = useState([])
const [loadStudents, setLoadStudents] = useState(false)
const [total, setTotal] = useState(0)
const [page, setPage] = useState(1)
@ -21,8 +22,10 @@ function StudentAdmin(obj) {
}, [pid]);
const updateStudentList = () => {
setLoadStudents(true)
ProjectApi.getProjectStudents(pid)
.then((res) => {
setLoadStudents(false)
if (res.data.code === 200) {
setStudents(res.data.students);
setTotal(res.data.count)
@ -51,6 +54,7 @@ function StudentAdmin(obj) {
<QueueAnim>
<div style={{textAlign: 'left'}} key="1">
<Table
loading={loadStudents}
dataSource={students}
columns={[
{

View File

@ -1,9 +1,24 @@
import React from 'react';
import DocumentTitle from 'react-document-title';
import {Avatar, BackTop, Button, Card, Col, Divider, Image, Menu, message, PageHeader, Popconfirm, Row} from 'antd';
import {
Avatar,
BackTop,
Button,
Card,
Col,
Divider,
Image,
Menu,
message,
PageHeader,
Popconfirm,
Row,
Tag, Tooltip
} from 'antd';
import QueueAnim from 'rc-queue-anim';
import localStorage from 'localStorage';
import {Link} from 'react-router-dom';
import {DeleteOutlined, StarFilled, StarOutlined} from "@ant-design/icons";
import ProjectIntroduce from './component/ProjectIntroduce';
import ProjectOutline from './component/ProjectOutline';
@ -13,7 +28,6 @@ import ProjectApi from "../../../api/ProjectApi";
import StudentApi from "../../../api/StudentApi";
import StudentAdmin from "./component/StudentAdmin";
import {getUser} from "../../User/Auth/Auth";
import {DeleteOutlined} from "@ant-design/icons";
import util from "../../component/Util"
import StudentEvidence from "../Evidence/component/StudentEvidence";
@ -23,7 +37,6 @@ class ProjectInfo extends React.PureComponent {
const pid = this.props.match.params.id;
let url = new URLSearchParams(this.props.location.search)
let menu = url.get("menu")
console.log(menu)
if (menu === undefined || menu === null) {
menu = 'project-introduce'
}
@ -32,8 +45,8 @@ class ProjectInfo extends React.PureComponent {
project: {},
teacher: {},
menu: menu,
type: localStorage.getItem('type'),
lastLearn: {}
lastLearn: {},
favBtLoading: false
};
}
@ -82,7 +95,7 @@ class ProjectInfo extends React.PureComponent {
}
handleClick = (e) => {
if (this.state.type === 'student' && e.key === "student-evidence" && !this.state.project.learning) {
if (this.props.account.tag === '学生' && e.key === "student-evidence" && !this.state.project.learning) {
message.warn("请先加入学习")
return
}
@ -91,7 +104,11 @@ class ProjectInfo extends React.PureComponent {
});
}
back = e => {
window.location.href = '/my-project'
if (this.props.account.tag === '老师') {
window.location.href = '/my-project/published'
} else {
window.location.href = '/my-project/learning'
}
}
learnProject = e => {
StudentApi.learnProject(this.state.pid)
@ -144,7 +161,11 @@ class ProjectInfo extends React.PureComponent {
StudentApi.exitProject(this.state.pid)
.then(res => {
if (res.data.code === 200) {
window.location.href = "/my-project"
if (this.props.account.tag === '老师') {
window.location.href = '/my-project/published'
} else {
window.location.href = '/my-project/learning'
}
} else {
message.error(res.data.msg)
}
@ -157,7 +178,11 @@ class ProjectInfo extends React.PureComponent {
ProjectApi.deleteProject(this.state.pid)
.then(res => {
if (res.data.code === 200) {
window.location.href = "/my-project"
if (this.props.account === '老师') {
window.location.href = '/my-project/published'
} else {
window.location.href = '/my-project/learning'
}
} else {
message.error(res.data.msg)
}
@ -166,6 +191,42 @@ class ProjectInfo extends React.PureComponent {
console.log(e)
})
}
addFavourite = e => {
this.setState({
favBtLoading: true
})
ProjectApi.addFavourite(this.state.pid)
.then(res=>{
this.setState({
favBtLoading: false
})
if (res.data.code === 200) {
this.loadProjectDetail()
message.success(res.data.msg)
} else {
message.error(res.data.msg)
}
})
.catch(e=>{console.log(e)})
}
removeFavourite = e => {
this.setState({
favBtLoading: true
})
ProjectApi.removeFavourite(this.state.pid)
.then(res=>{
this.setState({
favBtLoading: false
})
if (res.data.code === 200) {
this.loadProjectDetail()
message.success(res.data.msg)
} else {
message.error(res.data.msg)
}
})
.catch(e=>{console.log(e)})
}
setProject = project => {
this.setState({
@ -174,7 +235,7 @@ class ProjectInfo extends React.PureComponent {
}
render() {
const {project, teacher, menu, type, pid, lastLearn} = this.state;
const {project, teacher, menu, pid, lastLearn, favBtLoading} = this.state;
const teacherBt = (
<div style={{float: 'right'}}>
@ -332,12 +393,27 @@ class ProjectInfo extends React.PureComponent {
src={project.image}
placeholder
preview={false}
fallback={require("../../assets/empty.png").default}
fallback={"https://cdn.open-ct.com/task-resources//openpbl-empty-project.png"}
/>
</Col>
<Col span={1}>&nbsp;</Col>
<Col flex="auto">
<p style={{fontSize: '20px'}}>{project.projectTitle}</p>
<p style={{fontSize: '20px'}}>
{project.projectTitle}&nbsp;&nbsp;
{project.created ? <Tag color="geekblue">我创建的项目</Tag> : null}
{project.learning ? <Tag color="geekblue">正在学习</Tag> : null}
<span style={{float: 'right'}}>
{project.favourite ?
<Tooltip title="点击取消收藏">
<Button shape="circle" type="text" loading={favBtLoading} icon={<StarFilled/>} onClick={this.removeFavourite}/>
</Tooltip>
:
<Tooltip title="点击收藏">
<Button shape="circle" type="text" loading={favBtLoading} icon={<StarOutlined/>} onClick={this.addFavourite}/>
</Tooltip>
}
</span>
</p>
<p
style={{fontSize: '14px', color: 'gray'}}
>发布时间{util.FilterTime(project.createAt)}
@ -353,7 +429,16 @@ class ProjectInfo extends React.PureComponent {
</span>
</div>
<br/>
{type === 'student' ? studentBt : teacherBt}
{this.props.account.tag === '学生' ?
studentBt
:
<>
{project.created ?
teacherBt
: null
}
</>
}
</Col>
</Row>
</Card>
@ -369,9 +454,9 @@ class ProjectInfo extends React.PureComponent {
<Menu.Item key="project-outline">项目大纲</Menu.Item>
<Menu.Item key="project-evaluation">评价方案</Menu.Item>
{type === 'teacher' ? <Menu.Item key="student-admin">学生管理</Menu.Item>
{project.created ? <Menu.Item key="student-admin">学生管理</Menu.Item>
: null}
{type === 'student' ? <Menu.Item key="student-evidence">证据收集</Menu.Item>
{project.learning ? <Menu.Item key="student-evidence">证据收集</Menu.Item>
: null}
</Menu>
<div style={{
@ -392,7 +477,6 @@ class ProjectInfo extends React.PureComponent {
}
{menu === 'student-admin' ? <StudentAdmin project={project}/> : null}
{menu === 'student-evidence' ? <StudentEvidence project={project}/> : null}
</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 969 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 436 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 630 KiB

View File

@ -1,6 +1,5 @@
import React, {useEffect, useState} from 'react';
import QueueAnim from 'rc-queue-anim';
import {Card, Col, Divider, Empty, Image, Input, Pagination, Row, Select, Tag} from 'antd';
import {Card, Col, Divider, Empty, Image, Input, Pagination, Row, Select, Spin, Tag} from 'antd';
import {EyeOutlined, TeamOutlined} from '@ant-design/icons';
import {Link} from 'react-router-dom';
@ -20,6 +19,9 @@ const topColResponsiveProps = {
function ProjectList(obj) {
const [learningProjectList, setLearningProjectList] = useState([]);
const [loadProjects, setLoadProjects] = useState(false)
const [page, setPage] = useState(1);
const [size, setSize] = useState(10);
@ -44,8 +46,9 @@ function ProjectList(obj) {
}
const updateProjectList = (p, size, subject, skill, text) => {
setLoadProjects(true)
let q = {
page: p - 1,
from: (p - 1)*size,
size: size,
orderBy: 'create_at',
orderType: 'desc',
@ -55,6 +58,7 @@ function ProjectList(obj) {
}
ProjectListApi.getUserProjectList(mode, q)
.then((res) => {
setLoadProjects(false)
if (res.data.projects === null) {
setLearningProjectList([])
} else {
@ -90,7 +94,7 @@ function ProjectList(obj) {
updateProjectList(page, size, selectedSubjects.toString(), selectedSkills.toString(), v)
};
return (
<QueueAnim delay={100} className="queue-simple">
<div>
<Card bordered={false} style={{backgroundColor: 'white', borderRadius: '4px', textAlign: 'left'}}>
<Search
size="large"
@ -142,8 +146,9 @@ function ProjectList(obj) {
</Row>
</Card>
<div key="1" style={{marginTop: '10px'}}>
<Row gutter={[20, 20]}>
<div style={{marginTop: '10px', textAlign: 'center'}}>
<Spin spinning={loadProjects} />
<Row gutter={[20, 20]} style={{textAlign: 'left'}}>
{
learningProjectList.map((item, index) => (
<Col key={index.toString()} {...topColResponsiveProps}>
@ -162,7 +167,7 @@ function ProjectList(obj) {
borderTopLeftRadius: '10px',
borderTopRightRadius: '10px',
}}
fallback={require("../../assets/empty.png").default}
fallback={"https://cdn.open-ct.com/task-resources//openpbl-empty-project.png"}
/>
}
>
@ -231,7 +236,7 @@ function ProjectList(obj) {
</div>
<br/>
</div>
</QueueAnim>
</div>
);
}

View File

@ -21,7 +21,6 @@ class AuthCallback extends React.Component {
AuthApi.login(params.get('code'), params.get('state'))
.then((res) => {
if (res.data.code === 200) {
localStorage.setItem("type", res.data.data.tag)
message.success("登录成功,跳转主页");
window.location.href = "/home"
} else {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.7 KiB

View File

@ -1,10 +1,8 @@
import React from "react";
import {Avatar, Badge, Button, Col, Dropdown, Layout, Menu, Row} from "antd";
import {Avatar, Badge, Button, Col, Dropdown, Layout, Menu, Row, Tag, Image, message} from "antd";
import {Link, Redirect, Route, Switch} from "react-router-dom";
import {BellOutlined, LogoutOutlined, SettingOutlined} from '@ant-design/icons';
import './index.less'
import * as Auth from "../../User/Auth/Auth"
import AuthApi from "../../../api/AuthApi"
import Home from "../../Home";
@ -20,11 +18,14 @@ import SurveyEditPage from "../../Project/CreateProject/Survey/SurveyEditPage";
import PreviewSection from "../../Project/PreviewProject/PreviewSection";
const logo = "https://cdn.open-ct.com/logo/openct_logo_1082x328.png"
class HeaderLayout extends React.Component {
state = {
current: 'home',
account: null,
messageCount: 0,
menu: 'home'
}
componentDidMount() {
@ -34,19 +35,41 @@ class HeaderLayout extends React.Component {
this.setState({
account: res.data.data
})
localStorage.setItem("type", res.data.data.tag)
} else {
localStorage.setItem("type", "")
}
})
.catch((e) => {
console.log(e)
})
.catch((e) => {console.log(e)})
this.changeMenu()
}
changeMenu = (e) => {
if (e !== undefined ) {
this.setState({menu: e.key})
return
}
const p = this.props.location.pathname
if (p.startsWith('/home')) {
this.setState({menu: 'home'})
} else if (p.startsWith("/my-project")) {
this.setState({menu: 'my-project'})
} else if (p.startsWith("/public-project")) {
this.setState({menu: 'public-project'})
}
}
renderHomeIfLoggedIn(component) {
if (this.state.account === null) {
message.warn('请先登录')
return <Redirect to={'/home'} />
} else if (this.state.account === undefined) {
return null
} else {
return component
}
}
handleRightDropdownClick(e) {
let account = this.state.account;
console.log(account)
if (e.key === 'my-account') {
window.open(Auth.getMyProfileUrl(account));
} else if (e.key === 'logout') {
@ -56,13 +79,10 @@ class HeaderLayout extends React.Component {
this.setState({
account: null
})
localStorage.setItem("type", "")
window.location.href = '/'
}
})
.catch(e => {
console.log(e)
})
.catch(e => {console.log(e)})
}
}
@ -80,7 +100,7 @@ class HeaderLayout extends React.Component {
</Menu>
)
return (
<Dropdown overlay={menu} placement="bottomRight">
<Dropdown overlay={menu} placement="bottomRight" trigger="click">
<div style={{cursor: 'pointer'}}>
<Avatar size="large" src={this.state.account.avatar}/>&nbsp;
<span>{this.state.account.name}</span>
@ -98,26 +118,36 @@ class HeaderLayout extends React.Component {
);
} else {
return (
this.renderRightDropdown()
<>
<span style={{float: 'left'}}>
<Tag>{this.state.account.tag}</Tag>
</span>
{this.renderRightDropdown()}
</>
)
}
}
render() {
const {current, messageCount} = this.state;
const {menu, messageCount} = this.state;
return (
<Layout style={{minHeight: '100vh', textAlign: 'left'}}>
<Layout.Header style={{backgroundColor: 'white'}}>
<Layout.Header style={{backgroundColor: 'white', paddingLeft: '4px', paddingRight: '4px'}}>
<Row>
<Col xxl={15} xl={11} lg={8} md={6} sm={6} xs={10}>
<Col xxl={14} xl={10} lg={8} md={6} sm={6} xs={10}>
<Link to="/home">
<div className="logo">
<span style={{fontSize: '25px', color: 'black', float: 'left', marginLeft: '80px'}}>OpenCT</span>
</div>
<Image height={50} width={200} style={{margin: '7px'}} src={logo} preview={false}/>
</Link>
</Col>
<Col xxl={6} xl={10} lg={12} md={14} sm={12} xs={6}>
<Menu theme="light" mode="horizontal" defaultSelectedKeys={[current]} style={{border: 0}}>
<Col xxl={6} xl={10} lg={10} md={10} sm={10} xs={3}>
<Menu
theme="light"
mode="horizontal"
style={{border: 0}}
defaultSelectedKeys={['home']}
selectedKeys={[menu]}
onClick={e=>this.changeMenu(e)}
>
<Menu.Item key="home">
<Link to="/home">
首页
@ -140,7 +170,7 @@ class HeaderLayout extends React.Component {
</Menu.Item>
</Menu>
</Col>
<Col xxl={3} xl={3} lg={4} md={4} sm={6} xs={8}>
<Col xxl={4} xl={4} lg={6} md={8} sm={8} xs={11}>
{
<>
<span style={{float: 'left', marginRight: '20px'}}>
@ -169,20 +199,20 @@ class HeaderLayout extends React.Component {
<Redirect to="/home"/>
)}/>
<Route exact path="/home" component={Home}/>
<Route exact path="/public-project" component={Project}/>
<Route path="/my-project" component={MyProject}/>
<Route path="/message" component={Message}/>
<Route exact path="/home" render={(props)=><Home account={this.state.account} {...props} />}/>
<Route exact path="/public-project" render={(props)=>this.renderHomeIfLoggedIn(<Project account={this.state.account} {...props} />)} />
<Route path="/my-project" render={(props)=>this.renderHomeIfLoggedIn(<MyProject account={this.state.account} {...props} />)} />
<Route path="/message" render={(props)=>this.renderHomeIfLoggedIn(<Message account={this.state.account} {...props} />)}/>
<Route exact path="/project/:id/info" component={ProjectInfo}/>
<Route exact path="/project/:id/info/edit" component={EditInfo}/>
<Route exact path="/project/:id/outline/edit" component={EditOutlined}/>
<Route exact path="/project/:id/info" render={(props)=>this.renderHomeIfLoggedIn(<ProjectInfo account={this.state.account} {...props} />)}/>
<Route exact path="/project/:id/info/edit" render={(props)=>this.renderHomeIfLoggedIn(<EditInfo account={this.state.account} {...props} />)}/>
<Route exact path="/project/:id/outline/edit" render={(props)=>this.renderHomeIfLoggedIn(<EditOutlined account={this.state.account} {...props} />)}/>
<Route exact path="/project/:pid/student/:sid/evidence" component={Evidence}/>
<Route exact path="/project/:pid/student/:sid/evidence" render={(props)=>this.renderHomeIfLoggedIn(<Evidence account={this.state.account} {...props} />)}/>
<Route exact path="/project/:pid/section/:sid/edit" component={SectionEditPage}/>
<Route exact path="/project/:pid/section/:sid/task/:tid/survey/edit" component={SurveyEditPage}/>
<Route exact path="/project/:pid/section/:sid/preview" component={PreviewSection}/>
<Route exact path="/project/:pid/section/:sid/edit" render={(props)=>this.renderHomeIfLoggedIn(<SectionEditPage account={this.state.account} {...props} />)}/>
<Route exact path="/project/:pid/section/:sid/task/:tid/survey/edit" render={(props)=>this.renderHomeIfLoggedIn(<SurveyEditPage account={this.state.account} {...props} />)}/>
<Route exact path="/project/:pid/section/:sid/preview" render={(props)=>this.renderHomeIfLoggedIn(<PreviewSection account={this.state.account} {...props} />)}/>
</Switch>
</Layout.Content>
<Layout.Footer style={{textAlign: 'center'}}>OpenPBL</Layout.Footer>
@ -191,4 +221,4 @@ class HeaderLayout extends React.Component {
}
}
export default HeaderLayout;
export default HeaderLayout

View File

@ -1,6 +0,0 @@
.logo {
background: url("../../assets/logo.svg");
background-size: contain;
height: 64px;
width: 64px;
}

View File

@ -1930,14 +1930,6 @@
dependencies:
"@types/node" "*"
"@types/hoist-non-react-statics@^3.3.0":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
dependencies:
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
"@types/html-minifier-terser@^5.0.0":
version "5.1.1"
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50"
@ -2005,35 +1997,11 @@
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.2.1.tgz#374e31645d58cb18a07b3ecd8e9dede4deb2cccd"
integrity sha512-DxZZbyMAM9GWEzXL+BMZROWz9oo6A9EilwwOMET2UVu2uZTqMWS5S69KVtuVKaRjCUpcrOXRalet86/OpG4kqw==
"@types/prop-types@*":
version "15.7.4"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
"@types/q@^1.5.1":
version "1.5.4"
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==
"@types/react-redux@^7.1.16":
version "7.1.18"
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.18.tgz#2bf8fd56ebaae679a90ebffe48ff73717c438e04"
integrity sha512-9iwAsPyJ9DLTRH+OFeIrm9cAbIj1i2ANL3sKQFATqnPWRbg+jEFXyZOKHiQK/N86pNRXbb4HRxAxo0SIX1XwzQ==
dependencies:
"@types/hoist-non-react-statics" "^3.3.0"
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"
"@types/react@*":
version "17.0.14"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.14.tgz#f0629761ca02945c4e8fea99b8177f4c5c61fb0f"
integrity sha512-0WwKHUbWuQWOce61UexYuWTGuGY/8JvtUe/dtQ6lR4sZ3UiylHotJeWpf3ArP9+DSGUoLY3wbU59VyMrJps5VQ==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/resolve@0.0.8":
version "0.0.8"
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194"
@ -2041,11 +2009,6 @@
dependencies:
"@types/node" "*"
"@types/scheduler@*":
version "0.16.2"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
"@types/source-list-map@*":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
@ -4465,11 +4428,6 @@ cssstyle@^2.2.0:
dependencies:
cssom "~0.3.6"
csstype@^3.0.2:
version "3.0.8"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.8.tgz#d2266a792729fb227cd216fb572f43728e1ad340"
integrity sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==
cyclist@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
@ -6297,7 +6255,7 @@ hoist-non-react-statics@1.x:
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
integrity sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs=
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
hoist-non-react-statics@^3.1.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@ -11088,7 +11046,7 @@ react-github-button@^0.1.11:
dependencies:
prop-types "^15.5.10"
react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@ -11139,18 +11097,6 @@ react-pdf@^5.3.2:
pdfjs-dist "2.6.347"
prop-types "^15.6.2"
react-redux@^7.2.4:
version "7.2.4"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.4.tgz#1ebb474032b72d806de2e0519cd07761e222e225"
integrity sha512-hOQ5eOSkEJEXdpIKbnRyl04LhaWabkDPV+Ix97wqQX3T3d2NQ8DUblNXXtNMavc7DpswyQM6xfaN4HQDKNY2JA==
dependencies:
"@babel/runtime" "^7.12.1"
"@types/react-redux" "^7.1.16"
hoist-non-react-statics "^3.3.2"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-is "^16.13.1"
react-refresh@^0.8.3:
version "0.8.3"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
@ -11378,13 +11324,6 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"
redux@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.0.tgz#eb049679f2f523c379f1aff345c8612f294c88d4"
integrity sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==
dependencies:
"@babel/runtime" "^7.9.2"
regenerate-unicode-properties@^8.2.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec"