feat: preview questionnaire
This commit is contained in:
parent
6b8e2da89b
commit
eef35b3f7d
|
@ -16,9 +16,9 @@ func (p *ProjectController) GetSectionTasks() {
|
|||
sid := p.GetString(":sid")
|
||||
tasks, err := models.GetSectionTasks(sid)
|
||||
if err != nil {
|
||||
p.Data["json"] = map[string][]models.Task{"tasks": nil}
|
||||
p.Data["json"] = map[string][]models.TaskDetail{"tasks": nil}
|
||||
} else {
|
||||
p.Data["json"] = map[string][]models.Task{"tasks": tasks}
|
||||
p.Data["json"] = map[string][]models.TaskDetail{"tasks": tasks}
|
||||
}
|
||||
p.ServeJSON()
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ type Question struct {
|
|||
QuestionCount string `json:"question" xorm:"text"`
|
||||
}
|
||||
type SurveyDetail struct {
|
||||
Survey `xorm:"extends"`
|
||||
Survey `json:"survey" xorm:"extends"`
|
||||
Questions []Question `json:"questions" xorm:"extends"`
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,12 @@ type Task struct {
|
|||
TaskType string `json:"taskType" xorm:"index"`
|
||||
}
|
||||
|
||||
type TaskDetail struct {
|
||||
Task `xorm:"extends"`
|
||||
SurveyDetail `xorm:"extends"`
|
||||
|
||||
}
|
||||
|
||||
func (t *Task) GetEngine() *xorm.Session {
|
||||
return adapter.Engine.Table(t)
|
||||
}
|
||||
|
@ -40,11 +46,26 @@ func (t *Task) Delete() (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func GetSectionTasks(sid string) (t []Task, err error) {
|
||||
func GetSectionTasks(sid string) (t []TaskDetail, err error) {
|
||||
err = (&Task{}).GetEngine().
|
||||
Where("section_id = ?", sid).
|
||||
Asc("task_order").
|
||||
Find(&t)
|
||||
var s Survey
|
||||
var qs []Question
|
||||
for i := 0; i < len(t); i ++ {
|
||||
if t[i].TaskType == "survey" {
|
||||
_, err = (&Survey{}).GetEngine().
|
||||
Where("task_id = ?", t[i].Id).
|
||||
Get(&s)
|
||||
err = (&Question{}).GetEngine().
|
||||
Where("survey_id = ?", s.Id).
|
||||
Asc("question_order").
|
||||
Find(&qs)
|
||||
t[i].Survey = s
|
||||
t[i].Questions = qs
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -39,8 +39,9 @@
|
|||
"web-vitals": "^1.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"analyze": "source-map-explorer 'build/static/js/*.js'",
|
||||
"start": "craco start",
|
||||
"build": "craco --max_old_space_size=2048 build",
|
||||
"build": "craco build",
|
||||
"test": "craco test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
|
|
|
@ -1,26 +1,72 @@
|
|||
import React, {useEffect, useState} from "react";
|
||||
import {Card, PageHeader} from "antd";
|
||||
import {Card, PageHeader, Input, Upload, message, Button, Collapse, Spin, Radio, Divider} from "antd";
|
||||
import DocumentTitle from 'react-document-title';
|
||||
|
||||
import {InboxOutlined} from '@ant-design/icons'
|
||||
import SectionApi from "../../../api/SectionApi";
|
||||
import "./section-edit.less"
|
||||
import "./preview.less"
|
||||
import TaskApi from "../../../api/TaskApi";
|
||||
import FillSurvey from "./component/FillSurvey";
|
||||
|
||||
|
||||
function PreviewResource(obj) {
|
||||
const sid = obj.match.params.sid
|
||||
const pid = obj.match.params.pid
|
||||
const [section, setSection] = useState({resource:{}})
|
||||
const [tasks, setTasks] = useState([])
|
||||
|
||||
useEffect(()=>{
|
||||
getSectionResource()
|
||||
getTasks()
|
||||
}, [])
|
||||
const getSectionResource = () => {
|
||||
SectionApi.getSectionDetail(sid)
|
||||
.then(res=>{
|
||||
setSection(res.data.section)
|
||||
})
|
||||
.catch(e=>{console.log(e)})
|
||||
}, [])
|
||||
|
||||
}
|
||||
const getTasks = () => {
|
||||
TaskApi.getSectionTasks(sid)
|
||||
.then(res=>{
|
||||
if (res.data.tasks === null) {
|
||||
setTasks([])
|
||||
} else {
|
||||
let t = res.data.tasks
|
||||
for (let i = 0; i < t.length; i++) {
|
||||
if (t[i].questions !== undefined && t[i].questions != null) {
|
||||
for (let j = 0; j < t[i].questions.length; j++) {
|
||||
t[i].questions[j].questionOptions = t[i].questions[j].questionOptions.split(",")
|
||||
}
|
||||
}
|
||||
}
|
||||
setTasks(t)
|
||||
}
|
||||
})
|
||||
.catch(e=>{console.log(e)})
|
||||
}
|
||||
const back = e => {
|
||||
window.location.href = '/project/edit/section/' + pid + '/' + sid
|
||||
}
|
||||
|
||||
const props = {
|
||||
name: 'file',
|
||||
multiple: true,
|
||||
action: '',
|
||||
onChange(info) {
|
||||
const { status } = info.file;
|
||||
if (status !== 'uploading') {
|
||||
console.log(info.file, info.fileList);
|
||||
}
|
||||
if (status === 'done') {
|
||||
message.success(`${info.file.name} 上传成功`);
|
||||
} else if (status === 'error') {
|
||||
message.error(`${info.file.name} 上传失败`);
|
||||
}
|
||||
},
|
||||
onDrop(e) {
|
||||
console.log('Dropped files', e.dataTransfer.files);
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<DocumentTitle title="Project">
|
||||
|
@ -31,7 +77,7 @@ function PreviewResource(obj) {
|
|||
title="返回"
|
||||
subTitle="我的项目"
|
||||
/>
|
||||
<div style={{ padding: '20px', margin: 'auto', maxWidth: '1200px'}}>
|
||||
<div style={{ padding: '20px', margin: 'auto'}}>
|
||||
<Card>
|
||||
<h2 style={{ fontWeight: 'bold' }}>{section.sectionName}</h2>
|
||||
</Card>
|
||||
|
@ -39,18 +85,45 @@ function PreviewResource(obj) {
|
|||
<div dangerouslySetInnerHTML={{__html: section.resource.content}}/>
|
||||
</Card>
|
||||
<Card className="resource-card">
|
||||
<p className="card-title">文件</p>
|
||||
<p className="card-title">文件资源</p>
|
||||
<p>{section.resource.fileTitle}</p>
|
||||
<p>{section.resource.fileIntroduce}</p>
|
||||
</Card>
|
||||
{section.resource.hasHomeWork ?
|
||||
<Card className="resource-card">
|
||||
{tasks.map((item, index)=>(
|
||||
<Card className="resource-card" key={index.toString()}>
|
||||
<p className="card-title">学生任务</p>
|
||||
<p>{section.resource.homeWorkTitle}</p>
|
||||
<p>{section.resource.homeWorkIntroduce}</p>
|
||||
</Card>
|
||||
: null}
|
||||
<p className="task-title">{item.taskTitle}</p>
|
||||
<p>{item.taskIntroduce}</p>
|
||||
{item.taskType === 'file' ?
|
||||
<div>
|
||||
<Upload.Dragger {...props}>
|
||||
<p className="ant-upload-drag-icon">
|
||||
<InboxOutlined />
|
||||
</p>
|
||||
<p className="ant-upload-text">点击或拖动文件上传</p>
|
||||
<p className="ant-upload-hint">hint
|
||||
</p>
|
||||
</Upload.Dragger>
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
{item.taskType === 'comment' ?
|
||||
<div>
|
||||
<Input.TextArea />
|
||||
<Button type="primary" style={{float: 'right', marginTop: '10px'}}>提交</Button>
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
{item.taskType === 'survey' ?
|
||||
<FillSurvey
|
||||
item={item}
|
||||
/>
|
||||
: null
|
||||
}
|
||||
</Card>
|
||||
))
|
||||
}
|
||||
</div><br/>
|
||||
</div>
|
||||
</DocumentTitle>
|
||||
)
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
import React from "react";
|
||||
import {Button, Checkbox, Divider, Input, Radio} from "antd";
|
||||
|
||||
import Question from "../Question"
|
||||
import "../preview.less"
|
||||
import "../section-edit.less"
|
||||
|
||||
const blank = Question.blank
|
||||
|
||||
function FillSurvey(obj) {
|
||||
|
||||
const submitSurvey = e => {
|
||||
|
||||
}
|
||||
return (
|
||||
<div className="survey">
|
||||
<h2 style={{textAlign: 'center'}}>{obj.item.survey.surveyTitle}</h2>
|
||||
<Divider />
|
||||
<div style={{marginLeft: '20px', marginRight: '20px'}}>
|
||||
{obj.item.questions.map((subItem, subIndex)=>(
|
||||
<div key={subIndex.toString()}>
|
||||
{subItem.questionType==='singleChoice' ?
|
||||
<div style={{textAlign: "left", marginTop: '10px'}}>
|
||||
<p>{subItem.questionTitle}</p>
|
||||
<Radio.Group>
|
||||
{subItem.questionOptions.map((optItem, optIndex) => (
|
||||
<div style={{marginTop: '10px'}} key={optIndex.toString()}>
|
||||
<Radio value={optIndex}>
|
||||
{optItem}
|
||||
</Radio>
|
||||
</div>
|
||||
))}
|
||||
</Radio.Group>
|
||||
</div>
|
||||
: null}
|
||||
{subItem.questionType==='multipleChoice' ?
|
||||
<div style={{textAlign: "left", marginTop: '10px'}}>
|
||||
<p>{subItem.questionTitle}</p>
|
||||
{subItem.questionOptions.map((optItem, optIndex) => (
|
||||
<div style={{marginTop: '10px'}} key={optIndex.toString()}>
|
||||
<Checkbox>
|
||||
{optItem}
|
||||
</Checkbox>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
: null}
|
||||
{subItem.questionType==='blankFill' ?
|
||||
<div style={{textAlign: "left", marginTop: '10px'}}>
|
||||
<p>{subItem.questionTitle}</p>
|
||||
{subItem.questionOptions.map((optItem, optIndex) => (
|
||||
<div style={{marginTop: '10px'}} key={optIndex.toString()}>
|
||||
{optItem === blank ?
|
||||
<span style={{float: 'left', margin: '5px'}}>
|
||||
<Input style={{borderBottom: '2px solid black'}} bordered={false}/>
|
||||
</span>
|
||||
:
|
||||
<span style={{float: 'left', margin: '5px'}}>{optItem}</span>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
: null}
|
||||
|
||||
{subItem.questionType==='briefAnswer' ?
|
||||
<div style={{textAlign: "left", marginTop: '10px'}}>
|
||||
<p>{subItem.questionOptions[0]}</p>
|
||||
<Input.TextArea/>
|
||||
</div>
|
||||
: null}
|
||||
|
||||
<Divider/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Button type="primary" onClick={{submitSurvey}} style={{float: 'right', marginTop: '10px'}}>提交</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default FillSurvey
|
|
@ -0,0 +1,7 @@
|
|||
.survey{
|
||||
max-width: 1200px;
|
||||
padding: 20px;
|
||||
margin: auto;
|
||||
background-color: rgba(244, 231, 174, 0.07);
|
||||
border-radius: 10px;
|
||||
}
|
|
@ -9,5 +9,6 @@
|
|||
}
|
||||
.task-title{
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,9 +88,9 @@ function MultipleChoice(obj) {
|
|||
<Radio.Group>
|
||||
{obj.item.questionOptions.map((subItem, subIndex) => (
|
||||
<div style={{marginTop: '10px'}} key={subIndex.toString()}>
|
||||
<Radio value={subIndex}>
|
||||
<Checkbox>
|
||||
{subItem}
|
||||
</Radio>
|
||||
</Checkbox>
|
||||
</div>
|
||||
))}
|
||||
</Radio.Group>
|
||||
|
|
Loading…
Reference in New Issue