Files
learning-system-portal/src/views/exam/ExamList.vue

1489 lines
58 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="u-page">
<el-container>
<el-header style="padding: 2px 20px 10px 10px;">
<div style="padding-bottom: 10px">
<div style="display: flex; ">
<!-- <el-cascader
:options="resOwnerListMap"
v-model="ownership"
placeholder="资源归属"
clearable
:props="resourceProps"></el-cascader> -->
<div style="display: flex; justify-content: flex-start">
<div style="padding-right:5px">
<el-select clearable v-model="params.published" placeholder="状态" style="width: 110px">
<el-option label="已发布" :value="true"></el-option>
<el-option label="未发布" :value="false"></el-option>
</el-select>
</div>
<div style="padding: 0px 5px">
<el-input placeholder="关键词" v-model="params.keyWord" clearable></el-input>
</div>
<div style="padding: 0px 5px">
<el-button @click="search()" icon="el-icon-search" type="primary" >搜索</el-button>
</div>
<div style="padding: 0px 5px;"><el-button icon="el-icon-refresh-right" type="primary" @click="reset">重置</el-button></div>
<div style="margin-left:5px">
<el-button icon="el-icon-plus" type="primary" @click="addExam">新建考试</el-button>
</div>
</div>
</div>
</div>
</el-header>
<el-container >
<el-main >
<el-table style="" :data="pageData.list" border stripe>
<el-table-column label="序号" type="index" width="50"></el-table-column>
<!-- <el-table-column label="考试编号" prop="title"></el-table-column> -->
<el-table-column label="考试名称" prop="content" width="200">
<template slot-scope="scope">
<span class="previewStyle" @click="viewExamInfo(scope.row)">{{scope.row.testName}}</span>
</template>
</el-table-column>
<!-- <el-table-column label="资源归属" width="200">
<template slot-scope="scope">
<span v-if="scope.row.resOwner1 != ''">{{resOwnerName(scope.row.resOwner1)}}</span>
<span v-if="scope.row.resOwner2 != ''">/{{resOwnerName(scope.row.resOwner2)}}</span>
<span v-if="scope.row.resOwner3 != ''">/{{resOwnerName(scope.row.resOwner3)}}</span>
</template>
</el-table-column> -->
<el-table-column label="随机模式" prop="likeNumber">
<template slot-scope="scope">
{{ scope.row.randomMode === 1 ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column label="状态" prop="collectNumber">
<template slot-scope="scope">
{{ scope.row.published ? '已发布' : '未发布' }}
</template>
</el-table-column>
<el-table-column label="上下架" prop="collectNumber">
<template slot-scope="scope">
<!-- {{ scope.row.enabled ? '已上架' : '已下架' }} -->
<span v-if="scope.row.enabled">已上架</span>
<span v-else style="color:red">已下架</span>
</template>
</el-table-column>
<el-table-column label="创建人" prop="sysCreateBy"></el-table-column>
<el-table-column label="操作" width="250px" fixed="right">
<template slot-scope="scope">
<!-- v-if="scope.row.collectNumber === 0" -->
<el-button type="text" v-if="!scope.row.published" @click="releaseData(scope.row,true)">发布</el-button>
<!-- // 成绩控制需要结束状态 -->
<el-button type="text" v-if="scope.row.published" @click="viewResults(scope.row)">成绩</el-button>
<el-button type="text" v-if="scope.row.published" @click="pushResults(scope.row)">推送</el-button>
<!-- <el-button type="text" v-if="scope.row.published" @click="creatQrCode(scope.row)">二维码</el-button> -->
<el-button type="text" v-if="scope.row.published" @click="releaseData(scope.row,false)">取消发布</el-button>
<el-dropdown type="text" style="margin-left:10px">
<el-button type="text" > 更多 <i class="el-icon-arrow-down el-icon--right"></i> </el-button>
<el-dropdown-menu slot="dropdown">
<!-- <el-dropdown-item command="a">查看</el-dropdown-item> -->
<el-dropdown-item command="b" @click.native="editData(scope.row)">编辑</el-dropdown-item>
<el-dropdown-item command="b" @click.native="editPaper(scope.row)">修改试卷</el-dropdown-item>
<el-dropdown-item command="c" @click.native="deleteData(scope.row)">删除</el-dropdown-item>
<el-dropdown-item command="a" @click.native="creatQrCode(scope.row)">二维码</el-dropdown-item>
<div v-if="scope.row.published">
<el-dropdown-item command="d" v-if="scope.row.enabled == false" @click.native="enableddata(scope.row,true)">上架</el-dropdown-item>
<el-dropdown-item command="e" v-if="scope.row.enabled == true" @click.native="open(scope.row,false)">下架</el-dropdown-item>
</div>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<div v-if="pageData.list.length > 0" style="text-align: center;margin-top:60px">
<el-pagination background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="params.pageIndex"
:page-sizes="[10, 20, 30, 40]"
:page-size="params.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pageData.count">
</el-pagination>
</div>
<el-dialog :title="isEdit ? '编辑考试' : '新建考试'" width="980px"
:visible.sync="showAddDialog"
:close-on-click-modal="false"
custom-class="g-dialog">
<div style="padding: 0px 10px;">
<el-form size="small" label-width="80px" :model="examForm" ref="examForm" :rules="examRules">
<el-row :gutter="10">
<el-col :span="12">
<!-- <el-form-item label="资源归属">
<el-cascader
:options="resOwnerListMap"
v-model="resourceList"
placeholder="资源归属"
clearable
:props="resourceProps">
</el-cascader>
</el-form-item> -->
</el-col>
<el-col :span="12" >
<el-form-item label="模式" prop="testType">
<el-select :disabled="swichpublished" v-model="examForm.testType">
<el-option label="测试模式" :value="1"></el-option>
<el-option label="练习模式" :value="2"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24" >
<el-form-item label="考试名称" prop="testName">
<el-input :disabled="swichpublished" v-model="examForm.testName" maxlength="50" show-word-limit placeholder="请输入名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="考试描述">
<el-input :disabled="swichpublished" v-model="examForm.testRemark" maxlength="200" show-word-limit type="textarea" placeholder="请输入考试描述"></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="考前描述">
<el-input
v-model="examForm.testFront" :disabled="swichpublished"
type="textarea"
maxlength="200"
show-word-limit
placeholder="请输入考前描述"></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="考后描述">
<el-input v-model="examForm.testUp" :disabled="swichpublished" type="textarea" maxlength="200" show-word-limit placeholder="请输入考后描述"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="试卷" prop="paperId">
<el-select :disabled="swichpublished" v-model="examForm.paperId" placeholder="请选择" @change="changePaper">
<el-option
v-for="item in questDirOptions"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="考试时长">
<!-- <el-input v-model="examForm.testDuration" placeholder="20-120">
<template slot="append"> 分钟 </template>
</el-input> -->
<el-input-number :disabled="swichpublished" v-model="examForm.testDuration" controls-position="right" :min="10" :max="120" placeholder="分钟"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="显示解析">
<el-radio-group :disabled="swichpublished" v-model="examForm.showAnalysis">
<el-radio :label="true">允许查看</el-radio>
<el-radio :label="false">不允许查看</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="显示答案">
<el-radio-group :disabled="swichpublished" v-model="examForm.showAnswer">
<el-radio :label="true">允许查看</el-radio>
<el-radio :label="false">不允许查看</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="随机模式">
<el-radio-group :disabled="swichpublished" v-model="examForm.randomMode" @change="changeRandomMode">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item v-if="examForm.randomMode" label="随机数量" required>
<el-input-number :disabled="swichpublished" v-model="examForm.randomCount" controls-position="right" :min="1" :max="qnum"></el-input-number>
<span style="margin-left:10px;" v-if="qnum==0">先选择试卷</span>
<span style="margin-left:10px;" v-if="qnum>0">试卷有 {{qnum}} 道试题</span>
<!-- <el-input v-model="examForm.randomCount"><template slot="append"> 不能大于{{qnum}} </template></el-input> -->
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="尝试次数">
<!-- <el-input v-model="examForm.times" placeholder="0代表不限制"></el-input> -->
<el-input-number v-model="examForm.times" controls-position="right" :min="0" :max="10" placeholder="0代表不限制"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="试题排列">
<el-radio-group :disabled="swichpublished" v-model="examForm.arrange">
<el-radio :label="1" style="margin-right: 15px">试题乱序</el-radio>
<el-radio :label="2" style="margin-right: 15px">选项乱序</el-radio>
<el-radio :label="3" style="margin-right: 15px">全部乱序</el-radio>
<el-radio :label="4" style="margin-right: 15px">不乱序</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="评分模式">
<el-radio-group :disabled="swichpublished" v-model="examForm.scoringType">
<el-radio :label="1">最高一次</el-radio>
<el-radio :label="2">最后一次</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="范围">
<el-radio-group :disabled="swichpublished" v-model="examForm.rangeType">
<el-radio :label="1">独立使用</el-radio>
<el-radio :label="2" disabled>课程内部</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item v-if="examForm.rangeType === 1" label="及格线">
<!-- <el-input placeholder="20-120" v-model="examForm.passLine">
</el-input> -->
<el-input-number :disabled="swichpublished" v-model="examForm.passLine" controls-position="right" :min="20" :max="120" placeholder="20-120"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item required label="入场时间" v-if="examForm.rangeType === 1">
<!-- <el-date-picker
value-format="yyyy-MM-dd HH:mm:ss"
v-model="examForm.entranceTime"
type="datetime"
placeholder="选择日期时间">
</el-date-picker> -->
<el-date-picker style="width: 100%;"
v-model="examDateTime"
value-format="yyyy-MM-dd HH:mm:ss"
type="datetimerange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="saveForm()" type="primary">提交</el-button>
</div>
</el-dialog>
<el-dialog title="考试信息" :visible.sync="examInfoShow" width="1000px" custom-class="g-dialog">
<div>
<!-- <div v-if="!exam.onlyQuestion"> -->
<div>
<el-form size="medium" label-width="150px">
<el-row :gutter="10">
<!-- <el-col :span="12">
<el-form-item label="资源归属">
{{ resOwnerName(detailInfo.resOwner1) }}/{{resOwnerName(detailInfo.resOwner2)}}{{ detailInfo.resOwner3 ? '/' : ''}}{{ resOwnerName(detailInfo.resOwner3) }}
</el-form-item>
</el-col> -->
<el-col :span="12" >
<el-form-item label="模式">
<span v-if="detailInfo.testType == 1">测试模式</span>
<span v-if="detailInfo.testType == 2">练习模式</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="24">
<el-form-item label="考试名称" prop="testName">
<span>{{ detailInfo.testName }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="24">
<el-form-item label="考试描述">
<el-input v-model="detailInfo.testRemark" type="textarea" disabled>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="24">
<el-form-item label="考前描述">
<el-input v-model="detailInfo.testFront" type="textarea" disabled></el-input>
</el-form-item
></el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="24">
<el-form-item label="考后描述">
<el-input
v-model="detailInfo.testUp"
type="textarea"
disabled></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="试卷">
<div v-for="item in questDirOptions" :key="item.id">
<span v-if="item.id == detailInfo.paperId">
{{ item.name }}
</span>
</div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="考试时长">
{{ detailInfo.testDuration
}}<template slot="append"> 分钟 </template>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="显示解析">
<span v-if="detailInfo.showAnalysis == true">允许查看</span>
<span v-if="detailInfo.showAnalysis == false">不允许查看</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="显示答案">
<span v-if="detailInfo.showAnswer == true">允许查看</span>
<span v-if="detailInfo.showAnswer == false">不允许查看</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="随机模式">
<span v-if="detailInfo.randomMode == true"></span>
<span v-if="detailInfo.randomMode == false"></span>
</el-form-item>
</el-col>
<el-col :span="12" v-if="detailInfo.randomMode">
<el-form-item label="随机数量">{{detailInfo.randomCount}}</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="尝试次数">{{
detailInfo.times
}}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="试题排列">
<span v-if="detailInfo.arrange == 1">试题乱序</span>
<span v-if="detailInfo.arrange == 2">选项乱序</span>
<span v-if="detailInfo.arrange == 3">全部乱序</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="评分模式">
<span v-if="detailInfo.scoringType == 1">最高一次</span>
<span v-if="detailInfo.scoringType == 2">最后一次</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="范围">
<span v-if="detailInfo.rangeType == 1">独立使用</span>
<span v-if="detailInfo.rangeType == 2">课程内部</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item v-if="detailInfo.rangeType === 1" label="及格线">
{{ detailInfo.passLine }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="entranceTime" label="入场时间" v-if="detailInfo.rangeType === 1">
{{ detailInfo.entranceTime }}-{{detailInfo.deadlineTime}}
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="examInfoShow = false"> </el-button>
</span>
</el-dialog>
<el-dialog title="二维码" center :close-on-click-modal="false" :visible.sync="qrcodeShow" @close="closeCode" width="25%">
<div style=" height: 250px; display: flex; flex-direction: column; justify-content: space-evenly; align-items: center;">
<div id="qrcode" ref="qrcode"></div>
<el-input v-model="qrcode" id="text"></el-input>
<el-button type="primary" @click="myCopy()" size="mini">复制链接</el-button>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="qrcodeShow = false"> </el-button>
<el-button type="primary" @click="qrcodeShow = false"> </el-button>
</span>
</el-dialog>
<el-dialog title="考试成绩" append-to-body :visible.sync="viewResultsShow" width="80%" custom-class="g-dialog">
<div style="padding-bottom: 10px">
<div style="display: flex; justify-content: space-between">
<div>
<!-- <el-button icon="el-icon-plus" type="primary"
>全部导出</el-button> -->
</div>
<div style="display: flex; justify-content: flex-start">
<!-- <div style="padding: 0px 5px">
<el-select
v-model="params.top1"
placeholder="组织部门"
clearable
style="width: 110px">
<el-option label="组织部" value="0"></el-option>
<el-option label="策划部" value="1"></el-option>
</el-select>
</div> -->
<!-- <div style="padding: 0px 5px">
<el-select
v-model="params.top2"
placeholder="状态"
clearable
style="width: 110px">
<el-option label="未开始" value="3"></el-option>
<el-option label="已完成" value="1"></el-option>
<el-option label="进行中" value="2"></el-option>
</el-select>
</div> -->
<!-- <div style="padding: 0px 5px">
<el-input
placeholder="分数"
clearable
v-model="params.word"></el-input>
</div> -->
<div style="padding: 0px 5px">
<el-input
placeholder="姓名"
clearable
v-model="answerData.word"></el-input>
</div>
<div style="padding: 0px 5px">
<el-button icon="el-icon-search" type="primary" @click="getResults(true)">搜索</el-button>
<el-button icon="el-icon-download" type="primary" @click="exportsList()">导出成绩</el-button>
</div>
</div>
</div>
</div>
<el-table style="100%" :data="answerData.data" border stripe>
<el-table-column label="姓名" prop="name">
<template slot-scope="scope">
<el-link href="#">{{ scope.row.name }}</el-link>
</template>
</el-table-column>
<!-- <el-table-column label="邮箱" prop="emil">
<template slot-scope="scope">
<el-link href="#">{{ scope.row.emil }}</el-link>
</template>
</el-table-column>
<el-table-column label="手机号" prop="phone"></el-table-column> -->
<el-table-column label="工号" prop="ucode">
</el-table-column>
<el-table-column label="状态">
<template slot-scope="scope">
{{ scope.row.status == 9 ? '已完成' : '未开始' }}
</template>
</el-table-column>
<el-table-column label="完成时间" prop="lastTime">
<template slot-scope="scope">
{{ scope.row.lastTime }}
</template>
</el-table-column>
<el-table-column label="成绩" prop="score">
<template slot-scope="scope">
{{ toScoreTow(scope.row.score) }}
</template>
</el-table-column>
<el-table-column label="操作" width="150px">
<template slot-scope="scope">
<el-button type="text" icon="el-icon-delete" @click="viewUserPaper(scope.row)">查看</el-button>
<!-- <el-button
type="text"
icon="el-icon-delete"
@click="deleteUserExam(scope.row)"
>删除</el-button> -->
</template>
</el-table-column>
</el-table>
<div style="text-align: center;margin-top:70px">
<el-pagination background
@size-change="handleSizeAnswerChange"
@current-change="handleCurrentAnswerChange"
:current-page="answerData.pageIndex"
:page-sizes="[10, 20, 30, 40]"
:page-size="answerData.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="answerData.count">
</el-pagination>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="viewResultsShow = false">关闭</el-button>
</span>
</el-dialog>
<el-dialog
title="查看试卷"
append-to-body
:close-on-click-modal="false"
:visible.sync="viewUserPapereShow"
width="70%"
custom-class="g-dialog">
<div style="padding: 10px; font-size: 20px" class="upaper">
<div v-for="(ditem,didx) in answerData.paperDetail" :key="didx" class="upaper-item">
<div class="upaper-item-q">
<div> {{didx +1}}.{{getTypeName(ditem.type)}}{{ditem.title}}</div>
<div v-if="ditem.images" class="qimg"><img class="qimg-fit" :src="imageBaseUrl+ditem.images"/> </div>
</div>
<div class="upaper-item-opts" style="padding-left: 20px;">
<div v-for="(opt,optIdx) in ditem.optionList" :key="optIdx" class="upaper-item-opt" :class="{'upaper-item-opt-user':ditem.userOptIdxs.indexOf(optIdx)>-1}">
<div>
<div>{{toLetter(optIdx+1)}}, {{opt.content}}</div>
<div v-if="opt.images" class="qimg"><img class="qimg-fit" :src="imageBaseUrl+opt.images"/> </div>
</div>
<div>
<span v-if="ditem.userOptIdxs.indexOf(optIdx)>-1 && ditem.correctOptIdxs.indexOf(optIdx)>-1" style="color: #00aa00;font-size: 25px; "></span>
<span v-if="ditem.userOptIdxs.indexOf(optIdx)>-1 && ditem.correctOptIdxs.indexOf(optIdx)==-1" style="color: #ff0000;font-size: 25px; ">×</span>
</div>
</div>
</div>
<div class="upaper-item-answer" style="display: flex;">
<div class="upaper-item-answer-cell">
<span v-if="ditem.result" style="color: #00aa00; ">回答正确</span>
<span v-else style="color: #ff0000; ">回答错误</span>
</div>
<div v-if="ditem.type !=3" style="display:flex">
<div class="upaper-item-answer-cell" >
<span class="response-tit">正确答案</span>
<span v-for="op in ditem.correctOptIdxs" :key="op">{{toLetter(op+1)}}</span>
</div>
<div class="upaper-item-answer-cell">
<span class="response-tit">我的答案</span>
<span v-for="op in ditem.userOptIdxs" :key="op">{{toLetter(op+1)}}</span>
</div>
</div>
<div v-else style="display:flex"><!--判断题的问题-->
<div class="upaper-item-answer-cell" >
<span class="response-tit">正确答案</span>
<span>{{ditem.correctOptIdxs[0]=='true' ? '正确':'错误'}}</span>
</div>
<div class="upaper-item-answer-cell">
<span class="response-tit">我的答案</span>
<span>{{ditem.userOptIdxs[0]=='' ? '': ditem.userOptIdxs[0]=='true'? '正确':'错误'}}</span>
</div>
</div>
</div>
<div style="padding-top: 15px;font-size:16px">解析{{ditem.analysis}}</div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="viewUserPapereShow = false">关闭</el-button>
</span>
</el-dialog>
<el-dialog
:title="pushData.dlgTitle"
append-to-body
:close-on-click-modal="false"
:visible.sync="pushData.pushResultsShow"
width="800px"
custom-class="g-dialog">
<el-table :data="pushData.data" style="width: 100%" >
<el-table-column label="选择" align="center" width="50">
<template slot-scope="scope">
<el-radio v-model="pushData.id" @change="handleRowChange(scope.row)" :label="scope.row.id">{{''}}</el-radio>
</template>
</el-table-column>
<el-table-column prop="name" label="名称" >
<template slot="header" slot-scope="scope">
<el-input v-model="pushData.keyword" size="mini" placeholder="输入名称搜索">
<el-button @click="getUserGroup" slot="append" icon="el-icon-search"></el-button>
</el-input>
</template>
<template slot-scope="scope">
<a>{{scope.row.name}}</a>
</template>
</el-table-column>
<el-table-column prop="sysCreateTime" label="创建日期" align="center"></el-table-column>
<el-table-column prop="users" label="人数" width="50px" align="center"></el-table-column>
<el-table-column prop="status" label="状态" width="80px" align="center">
<template slot-scope="scope">
<span v-if="scope.row.status == 1">已发布</span>
<span v-if="scope.row.status == 0">未发布</span>
</template>
</el-table-column>
<el-table-column prop="type" label="类型" width="80px" align="center">
<template slot-scope="scope">
<span v-if="scope.row.type == 1">普通受众</span>
<span v-if="scope.row.type == 2">自动受众</span>
</template>
</el-table-column>
</el-table>
<div style="margin-top:10px">
<span style="float:right">
<el-button :loading="pushLoading" @click="pushClick()" type="primary">提交推送</el-button>
<el-button @click=" pushData.pushResultsShow= false">关闭</el-button>
</span>
<el-pagination
background
@size-change="handleSizePushChange"
@current-change="handleCurrentPushChange"
:current-page="pushData.pageIndex"
:page-sizes="[10, 20, 30, 40]"
:page-size="pushData.pageSize"
layout="total, prev, pager, next"
:total="pushData.count">
</el-pagination>
</div>
<div v-if="pushData.recordDetail.length>0" style="border-top: 1px solid #e2e2e2;margin-top:10px;padding-top:5px">
<div style="font-size:14px;margin-bottom:10px;color:#717171; ">已推送记录:</div>
<el-table :data="pushData.recordDetail" >
<el-table-column prop="sysCreateTime" label="推送日期" align="center"></el-table-column>
<el-table-column prop="groupName" label="受众" align="center"></el-table-column>
</el-table>
</div>
</el-dialog>
<div style="height: 100px"></div>
</el-main>
</el-container>
</el-container>
<editPaper ref="comEditPaper"></editPaper>
</div>
</template>
<script>
// import { resourceAttribution } from '../../data/resource'
import QRCode from 'qrcodejs2'
import apiTest from '@/api/modules/test.js'
import { sysTypeList, resOwnerListMap, courseType } from '../../utils/tools.js'
import apiPaper from '@/api/modules/paper.js';
import apiTestPaper from '@/api/modules/testPaper.js'
import { mapGetters,mapActions} from 'vuex';
import {examType,numberToLetter} from '@/utils/tools.js';
import usergroupApi from "@/api/modules/usergroup";
import pushRecordApi from "@/api/modules/pushRecord";
import {toScoreTow} from '@/utils/tools.js'
import apiUserBasic from '@/api/boe/userbasic.js';
import editPaper from "@/components/Exam/EditPaper";
export default {
name: 'articleItems',
components:{editPaper},
computed: {
...mapGetters(['resOwnerMap','sysTypeMap']),
},
data() {
return {
swichpublished:false,
imageBaseUrl:process.env.VUE_APP_FILE_BASE_URL,
toScoreTow,
qnum:0,//这里默认是30吧
examDateTime:[],
answerData:{
paperDetail:[],
word: '',
row:{},
pageSize:10,
pageIndex:1,
count:0,
data:[],
},
pushLoading:false,
pushData:{
dlgTitle:'推送考试',
keyword:'',
id:'',
pushResultsShow:false,
recordDetail:[],
row:{},// 考试数据
user:{},// 选择的手众数据
pageSize:10,
pageIndex:1,
count:0,
data:[],//受众list
},
toLetter:numberToLetter,
getTypeName:examType,
resOwnerListMap:[],
questDirOptions: [],
resourceList: [],
ownership: [],
resourceProps: {
value: 'code',
label: 'name',
},
qrcodeShow: false,
qrcode: '',
examInfoShow: false,
isEdit: false,
viewUserPapereShow: false,
viewResultsShow: false,
params: {published:null,keyWord:'', pageIndex: 1, pageSize: 10 },
// data: resourceAttribution,
pageData: {
list: [],
},
examRules: {
testName: [
{ required: true, message: '请填写考试名称', trigger: 'blur' },
],
testType: [{ required: true, message: '请选择模式', trigger: 'blur' }],
paperId: [{ required: true, message: '请选择试卷', trigger: 'blur' }]
},
showAddDialog: false,
examForm: {
rangeType:1,
showAnalysis:true,
showAnswer:true,
scoringType:2,
randomMode:true,
randomCount:1,
arrange:1,
testDuration:30,
entranceTime:'',
deadlineTime:'',
times:0,
},
detailInfo: {},
}
},
mounted() {
this.getResOwnerTree().then(rs=>{
this.resOwnerListMap=rs;
});
this.loadData()
},
methods: {
editPaper(row){
if(!row.paperId){
this.$message.error("此考试还未选择试卷");
return;
}
this.$refs.comEditPaper.show(row.paperId);
},
open(row,flag) {
this.$confirm('确定要下架此考试吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.enableddata(row,flag);
this.$message({ type: 'success', message: '下架成功!' });
}).catch(() => {
this.$message({ type: 'info', message: '已取消下架' });
});
},
exportsList(){
if(this.answerData.data.length == 0){
return this.$message.warning('暂无导出数据!')
}
apiTest.exports({testId: this.answerData.row.id}).then(res=>{
if(res.status){
this.$message.error(res.message)
} else {
const link = document.createElement('a');// 创建a标签
let blob = new Blob([res],{type: 'application/vnd.ms-excel;charset=UTF-8'}); // 设置文件类型
link.style.display = "none";
link.href = URL.createObjectURL(blob); // 创建URL
link.setAttribute("download", "成绩.xls");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
})
},
changePaper(e) {
this.questDirOptions.forEach(item=>{
if(item.id == e) {
if(item.qnum){
this.qnum = item.qnum;
}else{
this.qnum =0;
}
}
})
},
pushClick(){
if(!this.pushData.user.id) {
this.$message.warning('请选择受众小组')
return;
}
let params = {
testId:this.pushData.row.id,
testName:this.pushData.row.testName,
groupId:this.pushData.user.id,
groupName:this.pushData.user.name,
duration:this.pushData.row.testDuration,
startTime:this.pushData.row.entranceTime
}
this.pushLoading=true;
let $this=this;
pushRecordApi.pushExecute(params).then(res=>{
setTimeout(function(){ $this.pushLoading=false; },1000);
if(res.status ==200 && res.result) {
this.$message.success('推送成功!')
this.pushData.pushResultsShow = false;
} else {
this.$message.error(res.message)
}
})
},
handleRowChange(row) {
this.pushData.user = row;
},
// 推送
pushResults(row){
this.pushData.dlgTitle='推送【'+row.testName+'】';
this.pushData.row = row;
this.pushData.pushResultsShow = true;
this.getUserGroup();
this.getFindPage();
this.pushLoading=false;
},
getUserGroup(){
let params = {
keyword:this.pushData.keyword,
page:this.pushData.pageIndex,
pageSize:this.pushData.pageSize
}
// usergroupApi.list(params).then((res) => {
// if (res.status == 200) {
// this.pushData.data = res.result.list;
// this.pushData.count = res.result.count;
// }
// });
//从接口中获取受众数据,22/11/28
apiUserBasic.getUserAudiences(params).then(res=>{
if(res.status==200){
let list=[];
// this.pushData.count = res.result.totalElement;
// res.result.audienceList.forEach(crowd=>{
// list.push({
// id:crowd.id,
// kid:crowd.kid,
// name:crowd.audienceName,
// sysCreateTime:crowd.createAt,
// audienceType:crowd.audienceType,
// users:crowd.totalMember,
// type:crowd.type,
// status:crowd.status
// })
// });
this.pushData.count = res.result.total;
res.result.list.forEach(crowd=>{
list.push({
id:crowd.id,
kid:'',
name:crowd.audienceName,
sysCreateTime:crowd.createAt,
audienceType:crowd.type,
users:crowd.totalMember,
type:crowd.type,
status:crowd.status
})
});
this.pushData.data=list;
//计算总页面
}
})
},
getFindPage(){// 考试推送记录
pushRecordApi.pushList(this.pushData.row.id).then(res=>{
if(res.status == 200) {
this.pushData.recordDetail = res.result;
}
})
},
handleSizePushChange(val){
this.pushData.pageSize = val
this.pushData.pageIndex = 1
this.getUserGroup()
},
handleCurrentPushChange(val) {
this.pushData.pageIndex = val
this.getUserGroup();
},
myCopy(){
var ele = document.getElementById("text");
ele.select();
document.execCommand("Copy");
},
search(){
this.params.pageIndex = 1;
this.loadData();
},
reset(){
this.params.keyWord = ''
this.params.published = ''
this.ownership = ''
this.params.pageIndex = 1;
this.loadData();
},
...mapActions({
getResOwnerTree:'resOwner/getResOwnerTree',
loadResOwners:'resOwner/loadResOwners',
getSysTypeTree:'sysType/getSysTypeTree',
loadSysTypes:'sysType/loadSysTypes'
}),
resOwnerName(code){
if(code==''){return '';}
return this.resOwnerMap.get(code);
},
sysTypeName(code){
if(code==''){return '';}
return this.sysTypeMap.get(code);
},
findPapers() {
let params={
pageSize:200,
name:''
}
apiPaper.querypaper(params).then((res) => {
if (res.status === 200) {
this.questDirOptions = res.result;
if(this.examForm.paperId){
this.changePaper(this.examForm.paperId);
}
} else {
this.$message.error(res.message)
}
})
},
// 新建
saveForm() {
this.examForm.resOwner1 = this.resourceList[0]
this.examForm.resOwner2 = this.resourceList[1]
this.examForm.resOwner3 = this.resourceList[2]
if(this.examDateTime.length > 0) {
this.examForm.entranceTime = this.examDateTime[0]
this.examForm.deadlineTime = this.examDateTime[1]
} else {
this.$message.warning('请填写入场时间!')
return
}
if(this.examForm.randomMode == true && this.examForm.randomCount == '') {
this.$message.warning('请填写随机数量!')
return;
}
if(this.examForm.times == '') {
this.examForm.times = 0;
}
if(this.examForm.rangeType == 2) {
this.examForm.passLine = ''
this.examForm.entranceTime = ''
this.examForm.deadlineTime = ''
}
this.$refs.examForm.validate((valid) => {
if (valid) {
if (this.examForm.id) {
if(this.examForm.randomCount==1){
this.$message.warning('随机试题数必须大于1')
return;
}
apiTest.update(this.examForm).then((res) => {
if (res.status === 200) {
this.$message.success('保存成功!')
this.showAddDialog = false
this.loadData()
} else {
this.$message.error(res.message)
}
})
} else {
apiTest.save(this.examForm).then((res) => {
if (res.status === 200) {
this.$message.success('保存成功!')
this.showAddDialog = false
this.loadData()
} else {
this.$message.error(res.message)
}
})
}
}
})
},
addExam() {
this.swichpublished=false;
this.examDateTime=[];
this.examForm = {
rangeType:1,
showAnalysis:true,
showAnswer:true,
scoringType:2,
randomMode:true,
arrange:1,
testDuration:30,
entranceTime:'',
deadlineTime:'',
paperId:'',
times:0,
}
this.resourceList = []
this.showAddDialog = true
if(this.questDirOptions.length==0){
this.findPapers();//获取试卷列表
}
},
editData(row) {
this.swichpublished = row.published;
if(this.questDirOptions.length==0){
this.findPapers();//获取试卷列表
}
this.isEdit = true
this.showAddDialog = true
this.examDateTime=[];
apiTest.detail(row.id).then((res) => {
if (res.status === 200) {
this.examForm = res.result
if(res.result.entranceTime){
this.examDateTime.push(res.result.entranceTime);
this.examDateTime.push(res.result.deadlineTime);
}
if (res.result.resOwner3) {
this.resourceList = [
res.result.resOwner1,
res.result.resOwner2,
res.result.resOwner3,
]
} else {
this.resourceList = [res.result.resOwner1, res.result.resOwner2]
}
//试卷处理
this.changePaper(res.result.paperId);
} else {
this.$message.error(res.message)
}
})
},
deleteData(row) {
this.$confirm('此操作将永久删除该考试, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
apiTest.del(row.id).then((res) => {
if (res.status === 200) {
this.$message.success('删除成功!')
this.loadData()
} else {
this.$message.error(res.message)
}
})
})
.catch(() => {
this.$message({
type: 'info',
message: '已取消删除',
})
})
},
enableddata(row,flag){
//console.log(row,flag)
let query = {
id:row.id,
enabled:flag
}
//console.log(query)
apiTest.enabled(query).then(res =>{
if(res.status == 200){
row.enabled=flag;
}else{
this.$message({ type: 'error', message: res.message})
}
})
},
releaseData(row,num) {
let publish = num;
this.$confirm(`正在${publish? '':'取消'}发布考试, 是否继续?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
apiTest.pulish(row.id,publish).then((res) => {
if (res.status === 200) {
this.$message({
type: 'success',
message: `${publish? '':'取消'}发布成功!`,
})
this.loadData()
} else {
this.$message.error(res.message)
}
})
})
.catch((err) => {
this.$message({
type: 'info',
message: '已取消操作',
})
})
},
creatQrCode(row) {
this.qrcodeShow = true
//正式环境直接根据域名计算
let urlPre=window.location.protocol+'//'+window.location.host;
//this.qrcode = urlPre+'/mobile/pages/exam/exam?id=' + row.id
let returnUrl=encodeURIComponent(urlPre+'/mobile/pages/login/loading?returnUrl=/pages/exam/exam?id=' + row.id);
this.qrcode =urlPre+'/m?returnUrl='+returnUrl;
//通过配置来写
//let urlPre=process.env.VUE_APP_BOE_MOBILE_URL;
//this.qrcode = urlPre+'/mobile/pages/exam/exam?id=' + row.id
// 使用$nextTick确保数据渲染
this.$nextTick(() => {
this.crateQrcode()
})
},
// 生成二维码
crateQrcode() {
this.qr = new QRCode('qrcode', {
width: 150,
height: 150, // 高度
text: this.qrcode, // 二维码内容
// render: 'canvas' // 设置渲染方式(有两种方式 table和canvas默认是canvas
// background: '#f0f'
// foreground: '#ff0'
})
},
// 关闭弹框,清除已经生成的二维码
closeCode() {
this.$refs.qrcode.innerHTML = ''
},
viewExamInfo(data) {
if(this.questDirOptions.length==0){
this.findPapers();
}
apiTest.detail(data.id).then(res=>{
if (res.status === 200) {
this.detailInfo = res.result;
} else {
this.$message.error(res.message);
}
})
this.examInfoShow = true
},
loadData() {
this.params.resOwner1 = this.ownership[0]
this.params.resOwner2 = this.ownership[1]
this.params.resOwner3 = this.ownership[2]
apiTest.querylist(this.params).then((res) => {
if (res.status === 200) {
this.pageData.list = res.result.list
this.pageData.count = res.result.count
} else {
this.$message.error(res.message)
}
})
},
viewUserPaper(row) {
this.viewUserPapereShow = true;
this.getPaperDetail(row.id);
},
getPaperDetail(id){
apiTestPaper.getAnswerDetail(id).then(res=>{
if(res.status === 200) {
let answerJson = JSON.parse(res.result.answerJson);
let paperJson = JSON.parse(res.result.paperJson);
let answer = [];
for(let key in answerJson){
answer.push(key);
paperJson.forEach((item,index) => {
if(item.id == key) {
if(item.type==1){
item.userAnswer='';
}else if(item.type==2){
item.userAnswer=[];
}else{
item.userAnswer=''
}
item.correctOptIdxs=[];
item.userOptIdxs=[];
if(item.type==1){
item.userAnswer=answerJson[key];
}else if(item.type==2){
item.userAnswer.push(...answerJson[key].split(','));
}else{
item.userAnswer=answerJson[key]
}
}
item.result=true;
});
}
this.answerData.paperDetail = paperJson;
this.answerData.paperDetail.forEach((item,index)=>{
if(item.type ==3) {
item.correctOptIdxs.push(item.answer);
item.userOptIdxs.push(item.userAnswer);
}
item.optionList.forEach((opt,idx)=>{
//填充正确答案
if(opt.isAnswer){
item.correctOptIdxs.push(idx);
}
if(item.type==1){ //单选或判断
if(opt.id==item.userAnswer){
item.userOptIdxs.push(idx);
}
}else if(item.type==2){ //多选
if(item.userAnswer.indexOf(opt.id)>-1){
item.userOptIdxs.push(idx);
}
}
});
//判断答案是否正确
if(item.correctOptIdxs.toString()==item.userOptIdxs.toString()){
item.result=true;
}else{
item.result=false;
}
})
}
})
},
// deleteUserExam(row) {
// this.$confirm('此操作将数据永久删除, 是否继续?', '提示', {
// confirmButtonText: '确定',
// cancelButtonText: '取消',
// type: 'warning',
// })
// .then(() => {})
// .catch(() => {
// this.$message({
// type: 'info',
// message: '已取消删除',
// })
// })
// },
viewResults(row) {
this.viewResultsShow = true;
this.answerData.row=row;
this.getResults();
},
getResults(flag) {
if(flag){
this.answerData.pageIndex=1;
}
let params = {
testId: this.answerData.row.id,// 考试 的id
aid:'',// 答卷人ID
name:this.answerData.word,//答卷人
testName:this.answerData.row.testName, //考试名称
pageIndex:this.answerData.pageIndex,
pageSize:this.answerData.pageSize,
}
apiTestPaper.findAnswers(params).then(res=>{
if(res.status ==200) {
this.answerData.data = res.result.list;
this.answerData.count = res.result.count;
}
})
},
//导入考试成绩
exportAnswers(){
},
handleSizeAnswerChange(val){
this.answerData.pageSize = val
this.answerData.pageIndex = 1
this.getResults()
},
handleCurrentAnswerChange(val) {
this.answerData.pageIndex = val
this.getResults();
},
handleSizeChange(val) {
this.params.pageSize = val
this.params.pageIndex = 1
this.loadData()
},
handleCurrentChange(val) {
this.params.pageIndex = val
this.loadData()
},
filterCollectNumber(value, row) {
return row.tag === value
},
filterLikeNumber(value, row) {
return row.tag === value
},
setTop(item) {
let msg = '已设置置顶'
if (item.isTop) {
item.isTop = false
msg = '已取消置顶'
} else {
item.isTop = true
}
this.$message({ message: msg, type: 'success', offset: 50 })
},
setEssence(item) {
//没有了
let msg = '已设置精华'
if (item.isEssence) {
item.isEssence = false
msg = '已取消精华'
} else {
item.isEssence = true
}
this.$message({ message: msg, type: 'success', offset: 50 })
},
delItem(item) {
this.$confirm('您确定要删除所选文章吗?', '删除提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
// this.items.splice(idx, 1);
this.$message({ type: 'success', message: '删除成功!', offset: 50 })
})
.catch(() => {
this.$message({ type: 'info', message: '已取消删除', offset: 50 })
})
},
changeRandomMode() {
if (this.examForm.randomMode == 0) {
this.examForm.randomCount = null
}
},
},
}
</script>
<style lang="scss" scoped>
.upaper{
text-align: left;
.upaper-item{
border-bottom: 1px solid #dadada;
padding: 10px;
.upaper-item-q{
padding: 8px 0px;
}
.upaper-item-opts{
padding: 8px 0px;
line-height: 20px;
.upaper-item-opt{
min-height: 50px;
border-radius: 4px;
display: flex;
background-color: #FFFFFF;
justify-content: space-between;
padding: 10px 20px;
}
.upaper-item-opt-user{
background-color: #fff3e5;
}
}
.upaper-item-answer{
display: flex;
.upaper-item-answer-cell{
margin-right: 20px;
}
}
}
}
.el-aside {
padding: 0px 2px 10px 0px;
}
.el-main {
padding: 0px 10px;
}
.article-status1 {
padding: 3px;
border: 1px dotted #1ea0fa;
color: #1ea0fa;
}
.article-status2 {
padding: 3px;
border: 1px dotted #00aa00;
color: #00aa00;
}
.article-status3 {
padding: 3px;
border: 1px dotted #ff0000;
color: #ff0000;
}
.article-list {
margin: 5px 0;
border: 1px solid #dddddd;
padding: 10px;
}
.article-info {
.article-info-title {
font-size: 16px;
font-weight: 400;
height: 40px;
line-height: 40px;
.article-info-date {
width: 150px;
height: 40px;
line-height: 40px;
float: right;
font-weight: 200;
color: #999999;
i {
margin-right: 5px;
}
}
}
.article-info-summary {
height: 65px;
color: #999999;
}
.article-info-tools {
height: 30px;
.article-info-tools-auth {
float: left;
font-size: 13px;
color: #999999;
img {
margin-right: 10px;
width: 30px;
border: 1px solid #eee;
border-radius: 50%;
vertical-align: middle;
}
}
.article-info-tools-btns {
float: right;
.article-info-tools-btn {
margin: 0 0 0 15px;
}
}
}
}
.case-row-btn {
line-height: 25px;
button {
height: 20px;
padding: 3px 20px;
}
}
</style>