|
|
|
|
@ -15,14 +15,52 @@
|
|
|
|
|
</lx-header>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<xy-table :table-item="table" :list="data" :total="total"
|
|
|
|
|
<xy-table :table-item="table" :list="data" :total="total"
|
|
|
|
|
:auths="[]"
|
|
|
|
|
@pageSizeChange="e => {select.page_size = e;select.page = 1;getList()}"
|
|
|
|
|
@pageIndexChange="e => {select.page = e;getList()}">
|
|
|
|
|
<template v-slot:btns>
|
|
|
|
|
<div></div>
|
|
|
|
|
@pageIndexChange="e => {select.page = e;getList()}">
|
|
|
|
|
<template v-slot:btns>
|
|
|
|
|
<el-table-column fixed="right" label="操作" width="180" header-align="center">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<el-button type="primary" size="medium" @click="showRecord(scope.row)">查看记录</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</template>
|
|
|
|
|
</xy-table>
|
|
|
|
|
<el-dialog
|
|
|
|
|
title="答题记录"
|
|
|
|
|
:visible.sync="recordVisible"
|
|
|
|
|
width="700px"
|
|
|
|
|
:close-on-click-modal="false">
|
|
|
|
|
<div v-if="currentRecord && currentRecord.length > 0" class="record-list">
|
|
|
|
|
<div
|
|
|
|
|
v-for="(question, index) in currentRecord"
|
|
|
|
|
:key="index"
|
|
|
|
|
class="record-item">
|
|
|
|
|
<div class="record-header">
|
|
|
|
|
<span class="record-index">{{ index + 1 }}.</span>
|
|
|
|
|
<span class="record-title">{{ question.title }}</span>
|
|
|
|
|
<span class="record-type">({{ getQuestionType(question.type) }})</span>
|
|
|
|
|
<span class="record-answer">正确答案:{{ getCorrectAnswer(question) }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="record-options" v-if="question.answer && question.answer.length">
|
|
|
|
|
<span
|
|
|
|
|
v-for="(option, optIdx) in question.answer"
|
|
|
|
|
:key="optIdx"
|
|
|
|
|
:class="['option-chip', getOptionClass(index, option)]">
|
|
|
|
|
{{ getOptionLabel(optIdx) }}. {{ option.content }}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="record-options" v-else>
|
|
|
|
|
暂无选项
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-else style="text-align: center; color: #999;">暂无答题记录</div>
|
|
|
|
|
<span slot="footer" class="dialog-footer">
|
|
|
|
|
<el-button @click="recordVisible = false">关闭</el-button>
|
|
|
|
|
</span>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
@ -40,6 +78,9 @@
|
|
|
|
|
},
|
|
|
|
|
total: 0,
|
|
|
|
|
data: [],
|
|
|
|
|
recordVisible: false,
|
|
|
|
|
currentRecord: [],
|
|
|
|
|
currentAnswers: [],
|
|
|
|
|
table: [{
|
|
|
|
|
label: '序号',
|
|
|
|
|
type: "index",
|
|
|
|
|
@ -51,53 +92,53 @@
|
|
|
|
|
sortable: false,
|
|
|
|
|
prop: 'user_id',
|
|
|
|
|
width: 120
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '姓名',
|
|
|
|
|
sortable: false,
|
|
|
|
|
prop: 'name',
|
|
|
|
|
width: 120
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '身份证',
|
|
|
|
|
sortable: false,
|
|
|
|
|
prop: 'idcard',
|
|
|
|
|
// width: 120
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '联系方式',
|
|
|
|
|
sortable: false,
|
|
|
|
|
prop: 'mobile',
|
|
|
|
|
width: 120
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '学习类型',
|
|
|
|
|
sortable: false,
|
|
|
|
|
prop: 'type',
|
|
|
|
|
width: 120,
|
|
|
|
|
formatter:(cell, data, value)=>{
|
|
|
|
|
if(value==1){
|
|
|
|
|
return '普通访客'
|
|
|
|
|
}else if(value==2){
|
|
|
|
|
return '施工人员'
|
|
|
|
|
}else if(value==3){
|
|
|
|
|
return '物流司机'
|
|
|
|
|
}else{
|
|
|
|
|
return '未知'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '学习时间',
|
|
|
|
|
sortable: false,
|
|
|
|
|
prop: 'updated_at',
|
|
|
|
|
width: 180
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '有效期',
|
|
|
|
|
sortable: false,
|
|
|
|
|
prop: 'expire_day',
|
|
|
|
|
width: 180
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '姓名',
|
|
|
|
|
sortable: false,
|
|
|
|
|
prop: 'name',
|
|
|
|
|
width: 120
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '身份证',
|
|
|
|
|
sortable: false,
|
|
|
|
|
prop: 'idcard',
|
|
|
|
|
// width: 120
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '联系方式',
|
|
|
|
|
sortable: false,
|
|
|
|
|
prop: 'mobile',
|
|
|
|
|
width: 120
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '学习类型',
|
|
|
|
|
sortable: false,
|
|
|
|
|
prop: 'type',
|
|
|
|
|
width: 120,
|
|
|
|
|
formatter:(cell, data, value)=>{
|
|
|
|
|
if(value==1){
|
|
|
|
|
return '普通访客'
|
|
|
|
|
}else if(value==2){
|
|
|
|
|
return '施工人员'
|
|
|
|
|
}else if(value==3){
|
|
|
|
|
return '物流司机'
|
|
|
|
|
}else{
|
|
|
|
|
return '未知'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '学习时间',
|
|
|
|
|
sortable: false,
|
|
|
|
|
prop: 'updated_at',
|
|
|
|
|
width: 180
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '有效期',
|
|
|
|
|
sortable: false,
|
|
|
|
|
prop: 'expire_day',
|
|
|
|
|
width: 180
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
@ -112,6 +153,70 @@
|
|
|
|
|
console.log(res)
|
|
|
|
|
this.data = res.data
|
|
|
|
|
this.total = res.total
|
|
|
|
|
},
|
|
|
|
|
showRecord(row) {
|
|
|
|
|
this.currentRecord = Array.isArray(row.ask) ? row.ask : []
|
|
|
|
|
this.currentAnswers = Array.isArray(row.content) ? row.content : []
|
|
|
|
|
this.recordVisible = true
|
|
|
|
|
},
|
|
|
|
|
getQuestionType(type) {
|
|
|
|
|
if (type === 1) {
|
|
|
|
|
return '单选'
|
|
|
|
|
}
|
|
|
|
|
if (type === 2) {
|
|
|
|
|
return '多选'
|
|
|
|
|
}
|
|
|
|
|
return '未知'
|
|
|
|
|
},
|
|
|
|
|
getCorrectAnswer(question) {
|
|
|
|
|
if (!question.answer || !question.answer.length) {
|
|
|
|
|
return '-'
|
|
|
|
|
}
|
|
|
|
|
const correct = question.answer
|
|
|
|
|
.map((option, index) => option.result === 1 ? `${this.getOptionLabel(index)}. ${option.content}` : null)
|
|
|
|
|
.filter(Boolean)
|
|
|
|
|
return correct.length ? correct.join(';') : '-'
|
|
|
|
|
},
|
|
|
|
|
getOptionLabel(index) {
|
|
|
|
|
return String.fromCharCode(65 + index)
|
|
|
|
|
},
|
|
|
|
|
getOptionClass(questionIndex, option) {
|
|
|
|
|
const answered = this.isQuestionAnswered(questionIndex)
|
|
|
|
|
const isCorrect = option.result === 1
|
|
|
|
|
const isSelected = this.isUserSelected(questionIndex, option.content)
|
|
|
|
|
if (answered && isCorrect) {
|
|
|
|
|
return 'is-correct'
|
|
|
|
|
}
|
|
|
|
|
if (answered && isSelected && !isCorrect) {
|
|
|
|
|
return 'is-wrong'
|
|
|
|
|
}
|
|
|
|
|
return ''
|
|
|
|
|
},
|
|
|
|
|
isUserSelected(questionIndex, optionContent) {
|
|
|
|
|
if (!this.currentAnswers || !this.currentAnswers.length) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
const selection = this.currentAnswers[questionIndex]
|
|
|
|
|
if (Array.isArray(selection)) {
|
|
|
|
|
return selection.includes(optionContent)
|
|
|
|
|
}
|
|
|
|
|
if (typeof selection === 'string') {
|
|
|
|
|
return selection.split(',').map(item => item.trim()).includes(optionContent)
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
},
|
|
|
|
|
isQuestionAnswered(questionIndex) {
|
|
|
|
|
if (!this.currentAnswers || !this.currentAnswers.length) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
const selection = this.currentAnswers[questionIndex]
|
|
|
|
|
if (Array.isArray(selection)) {
|
|
|
|
|
return selection.length > 0
|
|
|
|
|
}
|
|
|
|
|
if (typeof selection === 'string') {
|
|
|
|
|
return selection.trim() !== ''
|
|
|
|
|
}
|
|
|
|
|
return Boolean(selection)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
@ -151,4 +256,68 @@
|
|
|
|
|
line-height: 21px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
.record-list {
|
|
|
|
|
max-height: 60vh;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.record-item {
|
|
|
|
|
padding: 10px 0;
|
|
|
|
|
border-bottom: 1px solid #f0f0f0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.record-item:last-child {
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.record-header {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
align-items: baseline;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
color: #333;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.record-index {
|
|
|
|
|
margin-right: 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.record-title {
|
|
|
|
|
margin-right: 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.record-type {
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
color: #666;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.record-answer {
|
|
|
|
|
color: #0f9674;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.record-options {
|
|
|
|
|
margin-top: 6px;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
gap: 6px 12px;
|
|
|
|
|
line-height: 22px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.option-chip {
|
|
|
|
|
padding: 2px 6px;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
background: #f5f5f5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.option-chip.is-correct {
|
|
|
|
|
background: #e8f8f0;
|
|
|
|
|
color: #0f9674;
|
|
|
|
|
border: 1px solid #0f9674;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.option-chip.is-wrong {
|
|
|
|
|
background: #fdecec;
|
|
|
|
|
color: #d93025;
|
|
|
|
|
border: 1px solid #d93025;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|