yujialong 9 months ago
parent 7d02d3baba
commit 53e4c92d1e
  1. 39
      package-lock.json
  2. 2
      package.json
  3. 1
      src/api/index.js
  4. 7
      src/layouts/header/index.vue
  5. 13
      src/libs/util.js
  6. 11
      src/pages/achievement/info/course.vue
  7. 5
      src/pages/achievement/info/project.vue
  8. 8
      src/pages/assessment/add/index.vue
  9. 22
      src/pages/assessment/list/index.vue
  10. 3
      src/pages/match/add/step2.vue
  11. 656
      src/pages/match/manage/matchArchList copy.vue
  12. 27
      src/pages/match/manage/matchRank.vue
  13. 5
      src/pages/match/manage/matchReport.vue
  14. 178
      src/pages/project/add/index.vue
  15. 1
      src/setting.js

39
package-lock.json generated

@ -3665,6 +3665,11 @@
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
}, },
"decimal.js": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
"integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA=="
},
"decode-uri-component": { "decode-uri-component": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
@ -12430,6 +12435,35 @@
} }
} }
}, },
"umy-table": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/umy-table/-/umy-table-1.1.8.tgz",
"integrity": "sha512-yqPMFwZ6MUNqI73KamsNKBTbHRA7VuVZDEWobaySghtf4n/s7INuTNQoADB/ROVK57WOXr99Xpnol0aMqGlASA==",
"requires": {
"async-validator": "~1.8.1",
"deepmerge": "^1.2.0",
"normalize-wheel": "^1.0.1",
"resize-observer-polyfill": "^1.5.0",
"throttle-debounce": "^1.0.1",
"vuedraggable": "^2.23.2",
"xe-utils": "^3.0.0-beta.12"
}
},
"umy-ui": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/umy-ui/-/umy-ui-1.1.6.tgz",
"integrity": "sha512-wX0S29B5sFn8q0MvU9PEl8DGZeQmZXOJlLrwaCJ2UHiIQZCANWgXMBjjQgpaequ1gRZ8BekEu7Sn7hJccm9YMQ==",
"requires": {
"async-validator": "~1.8.1",
"deepmerge": "^1.2.0",
"normalize-wheel": "^1.0.1",
"resize-observer-polyfill": "^1.5.0",
"throttle-debounce": "^1.0.1",
"umy-table": "1.1.8",
"vuedraggable": "^2.23.2",
"xe-utils": "^3.0.0-beta.12"
}
},
"unc-path-regex": { "unc-path-regex": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
@ -13584,6 +13618,11 @@
"async-limiter": "~1.0.0" "async-limiter": "~1.0.0"
} }
}, },
"xe-utils": {
"version": "3.5.22",
"resolved": "https://registry.npmjs.org/xe-utils/-/xe-utils-3.5.22.tgz",
"integrity": "sha512-rhWuM2fVXsdrqUtyjRAsYTDLvVzYSSZqg/uCRyDqcw96AweB1AWsnTJZyl9g68ejnP0xhxfSoNBSrIcOeX1yxA=="
},
"xml2js": { "xml2js": {
"version": "0.6.2", "version": "0.6.2",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",

@ -12,6 +12,7 @@
"ali-oss": "^6.18.1", "ali-oss": "^6.18.1",
"axios": "^0.18.0", "axios": "^0.18.0",
"babel-polyfill": "^6.26.0", "babel-polyfill": "^6.26.0",
"decimal.js": "^10.4.3",
"echarts": "^4.8.0", "echarts": "^4.8.0",
"element-theme": "^2.0.1", "element-theme": "^2.0.1",
"element-ui": "^2.13.0", "element-ui": "^2.13.0",
@ -22,6 +23,7 @@
"postcss-px2rem": "^0.3.0", "postcss-px2rem": "^0.3.0",
"px2rem-loader": "^0.1.9", "px2rem-loader": "^0.1.9",
"sortablejs": "^1.14.0", "sortablejs": "^1.14.0",
"umy-ui": "^1.1.6",
"vue": "^2.6.10", "vue": "^2.6.10",
"vue-codemirror": "^4.0.6", "vue-codemirror": "^4.0.6",
"vue-cropperjs": "^3.0.0", "vue-cropperjs": "^3.0.0",

@ -12,6 +12,7 @@ export default {
deleteProfile : `users/users/userInfo/deleteProfile`, deleteProfile : `users/users/userInfo/deleteProfile`,
refreshPageNotification : `nakadai/message/refreshPageNotification`, refreshPageNotification : `nakadai/message/refreshPageNotification`,
getCurrentTime : `competition/competition/management/getCurrentTime`, getCurrentTime : `competition/competition/management/getCurrentTime`,
heartbeatDetection : `nakadai/message/heartbeatDetection`,
getPlayAuth: `${uploadURL}oss/manage/getPlayAuth`, // 获取播放凭证 getPlayAuth: `${uploadURL}oss/manage/getPlayAuth`, // 获取播放凭证

@ -104,6 +104,7 @@ export default {
this.getSystemDetail(); this.getSystemDetail();
this.getUserDetail(); this.getUserDetail();
this.getNotice() this.getNotice()
this.heartbeatDetection()
}, },
methods: { methods: {
...mapMutations("user", [ ...mapMutations("user", [
@ -169,6 +170,12 @@ export default {
// socket // socket
this.socket.onmessage = this.getMessage; this.socket.onmessage = this.getMessage;
}, },
//
heartbeatDetection () {
setInterval(async () => {
await this.$get(this.api.heartbeatDetection)
}, 58 * 1000)
},
// //
getNotice () { getNotice () {

@ -208,7 +208,18 @@ const util = {
}); });
} }
return result; return result;
} },
// 获取当前时间
getNow () {
return new Promise(async (resolve, reject) => {
const { data } = await axios.get(Setting.apiBaseURL + api.getCurrentTime, {
headers: {
token: _local.get(Setting.tokenKey)
}
})
resolve(new Date(data.currentTime))
})
},
}; };
export default util; export default util;

@ -57,11 +57,11 @@
<div class="wrong"> <div class="wrong">
<div class="line"> <div class="line">
<span class="jud-name">错误率最高{{ max.projectName }}</span> <span class="jud-name">错误率最高{{ max.projectName }}</span>
<span>参加考试{{ permissions ? peopleNum || 0 : max.quantityAfterWeightRemoval }}&emsp;&emsp;{{ curTab == 1 ? `${max.itemErrorCount || 0}人做错,` : '' }}错误率{{ max.errorRate || 0 }}%</span> <span>参加考试{{ permissions ? (max.numberOfParticipants || 0) : (max.quantityAfterWeightRemoval || 0) }}&emsp;&emsp;{{ curTab == 1 ? `${max.itemErrorCount || 0}人做错,` : '' }}错误率{{ max.errorRate || 0 }}%</span>
</div> </div>
<div class="line"> <div class="line">
<span class="jud-name">错误率最低{{ min.projectName }}</span> <span class="jud-name">错误率最低{{ min.projectName }}</span>
<span>参加考试{{ permissions ? peopleNum || 0 : min.quantityAfterWeightRemoval }}&emsp;&emsp;{{ curTab == 1 ? `${min.itemErrorCount || 0}人做错,` : '' }}错误率{{ min.errorRate || 0 }}%</span> <span>参加考试{{ permissions ? (min.numberOfParticipants || 0) : (min.quantityAfterWeightRemoval || 0) }}&emsp;&emsp;{{ curTab == 1 ? `${min.itemErrorCount || 0}人做错,` : '' }}错误率{{ min.errorRate || 0 }}%</span>
</div> </div>
</div> </div>
<div class="chart" <div class="chart"
@ -364,8 +364,8 @@ export default {
e.errorRate = (+e.errorRate).toFixed(2) e.errorRate = (+e.errorRate).toFixed(2)
}) })
this.errorAnalysis = err || [] this.errorAnalysis = err || []
this.max = err[0] || {} this.max = err.length ? err[0] : {}
this.min = err[err.length - 1] || {} this.min = err.length ? err[err.length - 1] : {}
this.errorChart() this.errorChart()
const { row } = this.$store.state.achievement const { row } = this.$store.state.achievement
row && this.$nextTick(() => { row && this.$nextTick(() => {
@ -403,6 +403,7 @@ export default {
}, },
// //
tabChange () { tabChange () {
this.permissions = +this.curTab
this.$router.push({ this.$router.push({
path: 'course', path: 'course',
query: { query: {
@ -563,7 +564,6 @@ export default {
for (const i in this.stageNumber) { for (const i in this.stageNumber) {
data[+(i.replace('num', '')) - 1] = this.stageNumber[i] data[+(i.replace('num', '')) - 1] = this.stageNumber[i]
} }
console.log("🚀 ~ getChart ~ data:", data)
let myChart = echarts.init(document.getElementById("chart")); let myChart = echarts.init(document.getElementById("chart"));
myChart.setOption({ myChart.setOption({
title: { text: "实验分数分布图" }, title: { text: "实验分数分布图" },
@ -592,7 +592,6 @@ export default {
// //
errorChart () { errorChart () {
const data = this.errorAnalysis const data = this.errorAnalysis
console.log("🚀 ~ file: course.vue:585 ~ errorChart ~ data:", data)
const maxFontLength = data.length > 13 ? 6 : 10 const maxFontLength = data.length > 13 ? 6 : 10
const option = { const option = {
tooltip: { tooltip: {

@ -602,7 +602,8 @@ export default {
} }
}, },
axisLabel: { axisLabel: {
interval: 0, // rotate: 45,
interval: data.length > 40 ? 20 : 0,
textStyle: { textStyle: {
color: '#333', color: '#333',
}, },
@ -642,7 +643,7 @@ export default {
series: [{ series: [{
name: '错误率', name: '错误率',
type: 'bar', type: 'bar',
barWidth: 25, barWidth: data.length > 40 ? 15 : 25,
axisLabel: { axisLabel: {
margin: 10, margin: 10,
textStyle: { textStyle: {

@ -548,8 +548,10 @@ export default {
} }
}, },
getData () { // getData () { //
this.$get(`${this.api.getDetailById}?id=${this.form.id}`).then(res => { this.$get(`${this.api.getDetailById}?id=${this.form.id}`).then(({ data }) => {
this.form = res.data; this.form = data;
this.startTime = data.startTime
this.stopTime = data.stopTime
this.formatDuration(); this.formatDuration();
this.getschoolCourse(); this.getschoolCourse();
}).catch(err => { }).catch(err => {
@ -625,7 +627,7 @@ export default {
if (this.updateTime) { if (this.updateTime) {
this.$confirm(`编辑的内容未保存,是否保存?`, '提示', { this.$confirm(`编辑的内容未保存,是否保存?`, '提示', {
type: 'warning', type: 'warning',
closeOnClickModal: false closeOnClickModal: false
}).then(() => { }).then(() => {
this.save() this.save()
}).catch(() => { }).catch(() => {

@ -223,7 +223,7 @@
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import util from "@/libs/util"; import Util from "@/libs/util";
export default { export default {
data () { data () {
return { return {
@ -299,6 +299,7 @@ export default {
multipleSelection: [], // multipleSelection: [], //
listLoading: false,// listLoading: false,//
ticker: null, // ticker: null, //
now: '',
}; };
}, },
computed: { computed: {
@ -310,7 +311,7 @@ export default {
"form.month": function (val) { "form.month": function (val) {
if (val) { if (val) {
let unit = 24 * 60 * 60 * 1000; let unit = 24 * 60 * 60 * 1000;
this.date = [util.formatDate("yyyy-MM-dd", new Date(new Date().getTime() - unit * 30 * val)), util.formatDate("yyyy-MM-dd", new Date(new Date().getTime() + unit))]; this.date = [Util.formatDate("yyyy-MM-dd", new Date(new Date().getTime() - unit * 30 * val)), Util.formatDate("yyyy-MM-dd", new Date(new Date().getTime() + unit))];
} else { } else {
this.date = []; this.date = [];
} }
@ -342,6 +343,9 @@ export default {
this.getCourse(); this.getCourse();
}, },
methods: { methods: {
async getNow () {
this.now = await Util.getNow()
},
pickerInput () { pickerInput () {
this.form.month = '6' this.form.month = '6'
}, },
@ -457,12 +461,12 @@ export default {
this.$router.push(`add?id=${row.id}`); this.$router.push(`add?id=${row.id}`);
}, },
show (row) { show (row) {
this.$router.push(`/achievement/project?id=${row.id}&projectName=${row.projectName}&permissions=1&classId=${row.classId}`) this.$router.push(`/achievement/project?id=${row.id}&projectName=${row.projectName}&permissions=1&classId=${row.classId}&mallId=${row.mallId}`)
}, },
start (row) { start (row) {
this.$post(`${this.api.enableAssessment}?id=${row.id}`).then(async res => { this.$post(`${this.api.enableAssessment}?id=${row.id}`).then(async res => {
await this.$post(`${this.api.refreshPageNotification}?content=3-${row.id}`) await this.$post(`${this.api.refreshPageNotification}?content=3-${row.id}`)
util.successMsg("启动成功!"); Util.successMsg("启动成功!");
this.getData(1); this.getData(1);
}).catch(err => { }).catch(err => {
console.log(err); console.log(err);
@ -475,11 +479,11 @@ export default {
}).then(() => { }).then(() => {
let data = { let data = {
id: row.id, id: row.id,
endTime: util.formatDate("yyyy-MM-dd hh:mm:ss", new Date()), endTime: Util.formatDate("yyyy-MM-dd hh:mm:ss", new Date()),
status: 2 status: 2
}; };
this.$post(`${this.api.collectPaper}?id=${row.id}`).then(async res => { this.$post(`${this.api.collectPaper}?id=${row.id}`).then(async res => {
util.successMsg("提前结束成功!"); Util.successMsg("提前结束成功!");
this.getData(); this.getData();
await this.$post(`${this.api.refreshPageNotification}?content=3-${row.id}`) await this.$post(`${this.api.refreshPageNotification}?content=3-${row.id}`)
}).catch(err => { }).catch(err => {
@ -493,7 +497,7 @@ export default {
type: "warning" type: "warning"
}).then(() => { }).then(() => {
this.$post(this.api.deleteAssessment, [row.id]).then(res => { this.$post(this.api.deleteAssessment, [row.id]).then(res => {
util.successMsg("删除成功"); Util.successMsg("删除成功");
this.getData(); this.getData();
}).catch(res => { }).catch(res => {
}); });
@ -512,7 +516,7 @@ export default {
this.$post(this.api.deleteAssessment, ids).then(res => { this.$post(this.api.deleteAssessment, ids).then(res => {
this.multipleSelection = []; this.multipleSelection = [];
this.$refs.table.clearSelection(); this.$refs.table.clearSelection();
util.successMsg("删除成功"); Util.successMsg("删除成功");
this.getData(); this.getData();
}).catch(res => { }).catch(res => {
}); });
@ -522,7 +526,7 @@ export default {
}).catch(() => { }).catch(() => {
}); });
} else { } else {
util.errorMsg("请先选择数据 !"); Util.errorMsg("请先选择数据 !");
} }
}, },
handleSelectionChange (val) { handleSelectionChange (val) {

@ -460,9 +460,6 @@ export default {
} else { // 稿 } else { // 稿
form.competitionStageList = form.competitionStageList.filter(e => e.stageName) form.competitionStageList = form.competitionStageList.filter(e => e.stageName)
} }
// for (const e of form.competitionStageList) {
// if (!e.teamNumLimitOpt) e.teamNumLimit = 0
// }
this.$parent.showLoad() this.$parent.showLoad()
this.pass = 1 this.pass = 1
if (form.ruleId) { if (form.ruleId) {

@ -0,0 +1,656 @@
<template>
<div>
<el-card shadow="hover"
class="m-b-20 head-card">
<div class="flex-between m-b-20">
<el-page-header @back="$router.back()"
content="成绩管理"></el-page-header>
</div>
</el-card>
<el-card v-if="method != 2"
shadow="hover"
class="m-b-20">
<div class="stat">
<div class="nums">
<div class="item">
<p class="name">已参加/应参加人数</p>
<p class="val">{{ isNaN(statData.totalNumber) ? '' : statData.attendance + '/' + statData.totalNumber }}</p>
</div>
<div class="item">
<p class="name">实验平均分</p>
<p class="val">{{ avgScore }}</p>
</div>
</div>
<div class="chart"
id="chart"></div>
</div>
</el-card>
<el-card shadow="hover"
class="m-b-20">
<div v-if="showFile"
class="tabs m-b-20">
<a class="item"
v-for="(item, i) in tabs"
:key="i"
:class="{active: i === active}"
@click="tabChange(i)">{{ item }}</a>
</div>
<div class="flex-between m-b-20">
<div>
<el-input size="small"
placeholder="请输入学校/学生姓名"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
style="width: 300px"></el-input>
</div>
<div v-if="!active">
<el-button v-if="method == 2"
type="primary"
@click="batchImport">上传成绩</el-button>
<el-button type="primary"
@click="delAllData">批量删除</el-button>
<el-button type="primary"
@click="exportData">导出</el-button>
</div>
<div v-else>
<el-button type="primary"
:loading="loading"
@click="exportData1">{{ loading ? '正在导出' : '批量导出' }}</el-button>
</div>
</div>
<template v-if="!active">
<el-table :data="list"
class="table"
ref="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
row-key="reportId">
<el-table-column type="selection"
width="55"
align="center"
:reserve-selection="true"></el-table-column>
<el-table-column type="index"
width="60"
label="序号"
align="center">
<template slot-scope="scope">
{{ scope.$index + (page - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="schoolName"
label="学校"
min-width="150"
align="center"></el-table-column>
<el-table-column v-if="competitionType"
prop="teamName"
label="团队名称"
min-width="100"
align="center"></el-table-column>
<el-table-column prop="userName"
label="学生姓名"
min-width="100"
align="center"></el-table-column>
<el-table-column prop="workNumber"
label="学号"
min-width="100"
align="center"></el-table-column>
<el-table-column prop="score"
label="分数"
width="90"
align="center"></el-table-column>
<el-table-column prop="timeSum"
label="耗时"
width="90"
align="center">
<template slot-scope="scope">
{{ scope.row.timeSum ? scope.row.timeSum + 'min' : '--' }}
</template>
</el-table-column>
<el-table-column prop="submitTime"
label="提交时间"
min-width="150"
align="center">
<template slot-scope="scope">
{{ scope.row.submitTime || '--' }}
</template>
</el-table-column>
<el-table-column label="操作"
align="center"
width="160">
<template slot-scope="scope">
<el-button :disabled="!scope.row.reportId"
type="text"
@click="show(scope.row)">{{ scope.row.reportId ? '查看成绩报告' : '未参加' }}</el-button>
<el-button v-if="scope.row.reportId"
type="text"
@click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background
layout="total, prev, pager, next"
:total="total"
@current-change="handleCurrentChange"
:current-page="page">
</el-pagination>
</div>
</template>
<template v-else>
<el-table :data="list1"
class="table"
:key="2"
stripe
header-align="center"
@selection-change="handleSelectionChange1"
row-key="reportId">
<el-table-column type="selection"
width="55"
align="center"
:reserve-selection="true"></el-table-column>
<el-table-column type="index"
width="60"
label="序号"
align="center">
<template slot-scope="scope">
{{ scope.$index + (page1 - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="schoolName"
label="学校"
align="center"></el-table-column>
<el-table-column v-if="competitionType"
prop="teamName"
label="团队名称"
align="center"></el-table-column>
<el-table-column prop="userName"
label="学生姓名"
align="center"></el-table-column>
<el-table-column prop="workNumber"
label="学号"
align="center"></el-table-column>
<el-table-column prop="fileName"
label="文件名"
align="center"></el-table-column>
<el-table-column prop="fileSize"
label="文件大小"
align="center"></el-table-column>
<el-table-column prop="fileType"
label="文件类型"
align="center"></el-table-column>
<el-table-column prop="fileFormat"
label="文件格式"
align="center"></el-table-column>
<el-table-column prop="createTime"
label="提交时间"
width="150"
align="center">
</el-table-column>
<el-table-column label="操作"
align="center"
width="200">
<template slot-scope="scope">
<el-button v-if="!isCompress(scope.row.fileFormat)"
type="text"
@click="preview(scope.row)">预览文件</el-button>
<el-button type="primary"
size="mini"
:loading="scope.row.loading"
@click="exportFile(scope.row)">导出文件</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background
layout="total, prev, pager, next"
:total="total1"
@current-change="handleCurrentChange1"
:current-page="page1">
</el-pagination>
</div>
</template>
</el-card>
<el-dialog title="批量导入"
:visible.sync="importVisible"
width="24%"
:close-on-click-modal="false">
<div style="text-align: center">
<div style="margin-bottom: 10px;">
<el-button type="primary"
@click="download">模板下载<i class="el-icon-download el-icon--right"></i></el-button>
</div>
<el-upload ref="importStaff"
name="file"
accept=".xls,.xlsx"
:on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="this.api.batchImportGrades"
:file-list="uploadList"
:headers="headers"
:data="{
competitionId: this.id,
stageId: this.stageId,
systemId: 0
}">
<el-button type="primary"
class="ml20">上传文件<i class="el-icon-upload2 el-icon--right"></i></el-button>
</el-upload>
<el-link v-if="uploadFaild"
type="primary"
@click="showFaild">部分数据导入失败查看失败原因</el-link>
</div>
<span slot="footer"
class="dialog-footer">
<el-button size="small"
@click="importVisible = false"> </el-button>
<el-button size="small"
type="primary"
@click="uploadSure"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Setting from "@/setting";
import util from "@/libs/util";
import * as echarts from "echarts";
import axios from 'axios';
import Zip from '@/libs/zip'
export default {
data () {
return {
id: +this.$route.query.id,
stageId: +this.$route.query.stageId,
method: +this.$route.query.method,
competitionType: +this.$route.query.competitionType,
showFile: this.$route.query.showFile === 'true',
isCompress: util.isCompress,
keyword: "",
searchTimer: null,
list: [],
multipleSelection: [],
page: 1,
pageSize: 10,
total: 0,
list1: [],
multipleSelection1: [],
page1: 1,
total1: 0,
avgScore: 0, //
importVisible: false,
uploadList: [],
uploadFaild: false,
exportCode: '',
headers: {
token: util.local.get(Setting.tokenKey)
},
statData: {},
tabs: ['成绩列表', '文件列表'],
active: 0,
loading: false
};
},
watch: {
keyword: function (val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.initData();
}, 500);
}
},
mounted () {
this.getData()
},
methods: {
getData () {
//
if (this.active) {
this.$post(this.api.cCompetitionStageFileList, {
pageNum: this.page1,
pageSize: this.pageSize,
competitionId: this.id,
stageId: this.stageId,
keyWord: this.keyword,
}).then(({ data }) => {
data.records.forEach(e => {
e.loading = false
e.fileType = '其他'
if (util.isVideo(e.fileFormat)) {
e.fileType = '视频'
} else if (util.isAudio(e.fileFormat)) {
e.fileType = '音频'
} else if (util.isImg(e.fileFormat)) {
e.fileType = '图片'
} else if (util.isDoc(e.fileFormat)) {
e.fileType = '文档'
} else if (util.isCompress(e.fileFormat)) {
e.fileType = '压缩包'
} else if (e.fileType === 'pdf') {
e.fileType = 'pdf'
}
})
this.list1 = data.records
this.total1 = data.total
}).catch(res => { })
} else { //
this.$post(this.api.stageGradeManagementList, {
pageNum: this.page,
pageSize: this.pageSize,
competitionId: this.id,
keyWord: this.keyword,
stageId: this.stageId,
isNakadai: 1
}).then(({ data, page }) => {
this.total = page.total
this.list = page.records
this.statData = data
this.avgScore = (+data.avgScore).toFixed(2)
this.getChart()
}).catch(res => { })
}
},
initData () {
this.page = 1
this.getData()
},
//
show (row) {
this.$router.push(`/match/report?reportId=${row.reportId}`)
},
// ()
exportData () {
//
if (this.multipleSelection.length) {
axios.post(this.api.exportExperimentalResultsInBatch, this.multipleSelection, {
headers: this.headers,
responseType: 'blob'
}).then((res) => {
util.downloadFileDirect(`赛事成绩.xls`, new Blob([res.data]))
}).catch(res => { })
} else if (this.list.length) {
axios.post(this.api.allExperimentalResultsAreDerived, {
pageNum: 1,
pageSize: 10000,
competitionId: this.id,
isNakadai: 1,
stageId: this.stageId,
}, {
headers: this.headers,
responseType: 'blob'
}).then((res) => {
util.downloadFileDirect(`赛事成绩.xls`, new Blob([res.data]))
}).catch(res => { })
}
// let { list } = this
// if (this.multipleSelection.length) {
// list = this.multipleSelection
// }
// axios.post(this.api.exportExperimentalResultsInBatch, list, {
// headers: this.headers,
// responseType: 'blob'
// }).then((res) => {
// util.downloadFileDirect(`.xls`, new Blob([res.data]))
// }).catch(res => { })
},
// ()
exportData1 () {
this.loading = true
let list = this.list1
if (this.multipleSelection1.length) {
list = this.multipleSelection1
}
Zip('批量导出', list, () => {
this.loading = false
})
},
handleDelete (row) { //
this.$confirm("确定要删除吗?", "提示", {
type: "warning"
}).then(() => {
this.$post(this.api.batchDeleteContestGrade, {
ids: [this.method == 2 ? row.scoreId : row.reportId],
competitionId: this.id,
stageId: row.stageId
}).then(res => {
util.successMsg("删除成功");
this.getData();
}).catch(res => {
});
}).catch(() => {
});
},
delAllData () { //
if (this.multipleSelection.length) {
this.$confirm("该项目下的所有成绩报告将会删除,是否继续?", "提示", {
type: "warning"
}).then(() => {
let ids = this.multipleSelection.map(item => {
return this.method == 2 ? item.scoreId : item.reportId
});
this.$post(this.api.batchDeleteContestGrade, {
ids,
competitionId: this.id,
stageId: this.stageId
}).then(res => {
this.multipleSelection = [];
this.$refs.table.clearSelection();
util.successMsg("删除成功");
this.getData();
}).catch(res => {
});
}).catch(() => {
});
} else {
util.errorMsg("请先选择数据 !");
}
},
handleSelectionChange (val) { //
this.multipleSelection = val;
},
handleCurrentChange (val) { //
this.page = val;
this.getData();
},
handleSelectionChange1 (val) { //
this.multipleSelection1 = val;
},
handleCurrentChange1 (val) { //
this.page1 = val;
this.getData();
},
getChart () { // 线
const data = []
const { statData } = this
for (let i = 1; i <= 10; i++) {
data.push(statData['num' + i])
}
let myChart = echarts.init(document.getElementById("chart"));
myChart.setOption({
title: { text: "实验分数分布图" },
tooltip: {},
xAxis: {
name: "分数",
type: "category",
boundaryGap: false,
interval: 10,
data: ["0-10", "11-20", "21-30", "31-40", "41-50", "51-60", "61-70", "71-80", "81-90", "91-100"]
},
yAxis: {
name: "人数",
type: "value",
interval: 10
},
series: [{
data,
type: "line",
areaStyle: {},
color: ["#8191fd"]
}]
});
},
//
batchImport () {
this.importVisible = true
this.uploadList = []
this.uploadFaild = false
},
//
download () {
location.href = this.api.gradeImport
},
//
handleExceed (files, fileList) {
util.warningMsg(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
)
},
//
showFaild () {
axios.get(`${this.api.performanceExportFailure}?exportCode=${this.exportCode}`, {
headers: this.headers,
responseType: 'blob'
}).then((res) => {
util.downloadFileDirect(`批量导入成绩管理失败数据导出.xls`, new Blob([res.data]))
}).catch(res => { })
},
uploadSuccess (res, file, fileList) {
this.uploadFaild = false
if (res.status === 200) {
if (res.data.exportCode) {
this.exportCode = res.data.exportCode
this.uploadFaild = true
util.errorMsg(`本次上传有${res.data.failureNum}个错误信息录入`)
}
} else {
res.message ? util.errorMsg(res.message) : util.errorMsg("上传失败,请检查数据")
}
},
uploadError (err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
})
},
beforeRemove (file, fileList) {
return this.$confirm(`确定移除 ${file.name}`)
},
handleRemove (file, fileList) {
this.uploadList = fileList
this.uploadFaild = false
},
uploadSure () {
this.importVisible = false
this.getData()
},
// tab
tabChange (i) {
this.active = i
this.getData()
},
//
preview (item) {
window.open((util.isDoc(item.fileFormat) ? 'https://view.officeapps.live.com/op/view.aspx?src=' : '') + item.filePath)
},
//
exportFile (item) {
item.loading = true
const url = item.filePath
var x = new XMLHttpRequest()
x.open("GET", url, true)
x.responseType = "blob"
x.onload = function (e) {
var url = window.URL.createObjectURL(x.response)
var a = document.createElement("a")
a.href = url
a.download = item.userName + '-' + item.fileName
a.click()
item.loading = false
}
x.send()
},
}
};
</script>
<style lang="scss" scoped>
/deep/ .head-card {
.el-card__body {
padding-bottom: 0px;
.el-tabs__header {
margin-bottom: 1px;
.el-tabs__nav-wrap::after {
display: none;
}
.el-tabs__item {
font-size: 18px;
}
}
}
}
.stat {
display: flex;
.nums {
display: flex;
align-items: center;
margin-right: 20px;
.item:nth-child(1) {
background-image: url('../../../assets/img/total.png');
}
.item:nth-child(2) {
background-image: url('../../../assets/img/avg.png');
}
.item {
width: 300px;
min-height: 145px;
padding: 30px 30px;
margin: 0 10px;
box-sizing: border-box;
border-radius: 8px;
background-size: 100% 100%;
background-repeat: no-repeat;
p {
font-size: 18px;
color: #ffffff;
}
.val {
margin-top: 10px;
color: #ffffff;
font-size: 36px;
}
}
}
.chart {
flex: 1;
height: 300px;
}
}
</style>

@ -35,7 +35,12 @@
class="ml20" class="ml20"
@click="batchImport">上传文件</el-button> @click="batchImport">上传文件</el-button>
</div> </div>
<div> <div style="display: inline-flex;align-items: center">
<el-input style="width: 220px;margin-right: 15px"
placeholder="请输入团队名称/队长/学校"
prefix-icon="el-icon-search"
v-model="keyword"
clearable></el-input>
<el-button v-if="!published" <el-button v-if="!published"
type="primary" type="primary"
@click="cancelPublish(1)">发布排名</el-button> @click="cancelPublish(1)">发布排名</el-button>
@ -269,6 +274,8 @@ export default {
method: this.$route.query.method, method: this.$route.query.method,
competitionType: +this.$route.query.competitionType, competitionType: +this.$route.query.competitionType,
rule: +this.$route.query.rule, rule: +this.$route.query.rule,
searchTimer: null,
keyword: '',
teamCalculationMethods: [ teamCalculationMethods: [
{ {
id: 0, id: 0,
@ -330,6 +337,14 @@ export default {
isPointWeight: false isPointWeight: false
}; };
}, },
watch: {
keyword: function (val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.getRank();
}, 500);
}
},
mounted () { mounted () {
this.getStage() this.getStage()
}, },
@ -351,7 +366,8 @@ export default {
pageSize: this.pageSize, pageSize: this.pageSize,
competitionId: this.id, competitionId: this.id,
isOverallRanking: this.active ? 0 : 1, isOverallRanking: this.active ? 0 : 1,
stageId: this.active || this.stageId stageId: this.active || this.stageId,
keyword: this.keyword
}).then(({ message, publishStatus }) => { }).then(({ message, publishStatus }) => {
// isRelease 01 // isRelease 01
this.published = publishStatus this.published = publishStatus
@ -370,7 +386,8 @@ export default {
competitionId: this.id, competitionId: this.id,
publicationType: this.type, publicationType: this.type,
locationStageId: this.stageId, locationStageId: this.stageId,
stageIds: ids.splice(0, ids.length - 1) stageIds: ids.splice(0, ids.length - 1),
keyword: this.keyword
}).then(({ page, publishStatus, total }) => { }).then(({ page, publishStatus, total }) => {
this.published = publishStatus this.published = publishStatus
this.list = page this.list = page
@ -378,7 +395,7 @@ export default {
this.getPublishTime() this.getPublishTime()
}).catch(res => { }) }).catch(res => { })
} else { // } else { //
this.$post(`${this.api.stageRaceRanking}?competitionId=${this.id}&stageId=${this.active}&pageNum=${this.page}&pageSize=${this.pageSize}&publicationType=${this.type}`).then(({ page, total, publishStatus }) => { this.$post(`${this.api.stageRaceRanking}?competitionId=${this.id}&stageId=${this.active}&pageNum=${this.page}&pageSize=${this.pageSize}&publicationType=${this.type}&keyword=${this.keyword}`).then(({ page, total, publishStatus }) => {
this.published = publishStatus this.published = publishStatus
this.list = page this.list = page
this.total = total this.total = total
@ -605,7 +622,7 @@ export default {
whetherToPublish ? whetherToPublish ?
this.$confirm('排名已经发布,是否直接覆盖?', '提示', { this.$confirm('排名已经发布,是否直接覆盖?', '提示', {
type: 'success', type: 'success',
closeOnClickModal: false closeOnClickModal: false
}).then(() => { }).then(() => {
this.publishSubmit() this.publishSubmit()
}).catch(() => { }) : }).catch(() => { }) :

@ -173,6 +173,11 @@
</template> </template>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="quesScore"
label="分值"
:key="6"
width="80"
align="center"></el-table-column>
<el-table-column prop="score" <el-table-column prop="score"
label="得分" label="得分"
width="80" width="80"

@ -9,8 +9,10 @@
content="项目配置"></el-page-header> content="项目配置"></el-page-header>
<div v-if="!isDetail"> <div v-if="!isDetail">
<el-button type="success" <el-button type="success"
:loading="submiting === 0"
@click="save(0)">保存为草稿</el-button> @click="save(0)">保存为草稿</el-button>
<el-button type="primary" <el-button type="primary"
:loading="submiting === 1"
@click="save(1)">确定并发布</el-button> @click="save(1)">确定并发布</el-button>
</div> </div>
</div> </div>
@ -137,34 +139,38 @@
@click="batchDeleteProjectJudgment" @click="batchDeleteProjectJudgment"
style="margin-bottom: 10px">批量删除</el-button> style="margin-bottom: 10px">批量删除</el-button>
<div class="draggable"> <div class="draggable">
<el-table ref="projectJudgementTable" <u-table ref="projectJudgementTable"
:data="projectJudgmentData" :data="projectJudgmentData"
class="table" class="table"
stripe stripe
header-align="center" header-align="center"
@selection-change="handleSelectionProjectJudgment" use-virtual
row-key="judgmentId" :max-height="400"
v-loading="listLoading"> :row-height="168"
<el-table-column type="selection" :border="false"
width="55" @selection-change="handleSelectionProjectJudgment"
align="center"></el-table-column> row-key="judgmentId"
<el-table-column prop="sort" v-loading="listLoading">
label="序号" <u-table-column type="selection"
width="80" width="55"
align="center"> align="center"></u-table-column>
<u-table-column prop="sort"
label="序号"
width="80"
align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.sort }} {{ scope.row.sort }}
</template> </template>
</el-table-column> </u-table-column>
<el-table-column prop="name" <u-table-column prop="name"
label="判分指标" label="判分指标"
align="center"></el-table-column> align="center"></u-table-column>
<el-table-column prop="name" <u-table-column prop="name"
label="判分点名称" label="判分点名称"
align="center"></el-table-column> align="center"></u-table-column>
<el-table-column label="实验要求" <u-table-column label="实验要求"
align="center" align="center"
width="600"> width="600">
<template slot-scope="scope"> <template slot-scope="scope">
<quill :border="true" <quill :border="true"
:readonly="true" :readonly="true"
@ -174,27 +180,27 @@
:height="150" :height="150"
:index="2" /> :index="2" />
</template> </template>
</el-table-column> </u-table-column>
<el-table-column prop="score" <u-table-column prop="score"
label="分数" label="分数"
align="center" align="center"
width="120"> width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<!--type="number" @blur="updateProjectJudgment"--> <!--type="number" @blur="updateProjectJudgment"-->
<el-input v-model.trim="scope.row.score" <el-input v-model.trim="scope.row.score"
@input="scoreChange(scope.row, scope.$index,$event)"></el-input> @input="scoreChange(scope.row, scope.$index,$event)"></el-input>
</template> </template>
</el-table-column> </u-table-column>
<el-table-column label="操作" <u-table-column label="操作"
width="100" width="100"
align="center"> align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<!--<el-button :disabled="isDetail" type="text" style="margin-right: 10px" @click="toJudgePoint('edit', scope.row)">自定义</el-button>--> <!--<el-button :disabled="isDetail" type="text" style="margin-right: 10px" @click="toJudgePoint('edit', scope.row)">自定义</el-button>-->
<el-button type="text" <el-button type="text"
@click="delJudgePoint(scope.$index)">删除</el-button> @click="delJudgePoint(scope.$index)">删除</el-button>
</template> </template>
</el-table-column> </u-table-column>
</el-table> </u-table>
</div> </div>
</el-card> </el-card>
@ -241,39 +247,42 @@
clearable></el-input> clearable></el-input>
</div> </div>
</div> </div>
<el-table v-loading="visibleLoading" <u-table v-loading="visibleLoading"
:data="judgementData" :data="judgementData"
ref="judgementTable" ref="judgementTable"
class="table" class="table"
stripe stripe
header-align="center" header-align="center"
max-height="400" use-virtual
@selection-change="handleSelectionJudgment" :row-height="45"
:row-key="rowKey"> :max-height="400"
<el-table-column type="selection" :border="false"
width="55" @selection-change="handleSelectionJudgment"
align="center" :row-key="rowKey">
:reserve-selection="true"></el-table-column> <u-table-column type="selection"
<el-table-column prop="id" width="55"
label="序号" align="center"
align="center" :reserve-selection="true"></u-table-column>
width="100"> <u-table-column prop="id"
label="序号"
align="center"
width="100">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.$index + 1 }} {{ scope.$index + 1 }}
</template> </template>
</el-table-column> </u-table-column>
<el-table-column prop="name" <u-table-column prop="name"
label="判分点名称" label="判分点名称"
align="center"></el-table-column> align="center"></u-table-column>
<el-table-column label="操作" <u-table-column label="操作"
align="center" align="center"
width="100"> width="100">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button size="mini" <el-button size="mini"
@click="toJudgePoint('view', scope.row)">查看</el-button> @click="toJudgePoint('view', scope.row)">查看</el-button>
</template> </template>
</el-table-column> </u-table-column>
</el-table> </u-table>
<div slot="footer" <div slot="footer"
class="dialog-footer"> class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button> <el-button @click="dialogVisible = false"> </el-button>
@ -290,10 +299,13 @@ import util from "@/libs/util";
import { mapState, mapActions } from "vuex"; import { mapState, mapActions } from "vuex";
import quill from "@/components/quill"; import quill from "@/components/quill";
import Sortable from "sortablejs"; import Sortable from "sortablejs";
import { UTable, UTableColumn } from 'umy-ui'
import Decimal from 'decimal.js'
export default { export default {
components: { components: {
quill quill,
UTable,
UTableColumn
}, },
data () { data () {
return { return {
@ -350,21 +362,22 @@ export default {
...mapState("project", [ ...mapState("project", [
"projectFields", "lastSystemId" "projectFields", "lastSystemId"
]), ]),
handDistributionScore: function () { handDistributionScore: {
//100 get () {
let score = 0; //100
this.projectJudgmentData.forEach(e => { let score = 0;
score += parseInt(e.score); this.projectJudgmentData.forEach(e => {
}); score = Decimal(e.score).add(Decimal(score))
if (isNaN(score)) { });
return 0; if (isNaN(score)) {
} return 0;
if (score > 100) { }
// util.errorMsg(res.message); if (score > 100) {
util.errorMsg("分配的数值已超过100"); this.$message.error("分配的数值已超过100");
} }
console.log("chuli"); return score;
return score; },
set (val) { }
} }
}, },
watch: { watch: {
@ -555,11 +568,11 @@ export default {
return true; return true;
}, },
save (state) { // save (state) { //
if (this.submiting) return false if (this.submiting === 0 || this.submiting === 1) return false
if (!this.judgmentRelease(state)) { // if (!this.judgmentRelease(state)) { //
return; return;
} }
this.submiting = true this.submiting = state
this.setSystemId(this.projectManage.systemId); this.setSystemId(this.projectManage.systemId);
this.projectManage.state = state; this.projectManage.state = state;
let { systemId } = this.projectManage; let { systemId } = this.projectManage;
@ -628,11 +641,12 @@ export default {
}); });
// this.updateProjectJudgment(); // this.updateProjectJudgment();
} }
this.handDistributionScore = res.sum || 0
}); });
} }
}, },
scoreChange (row, i) { scoreChange (row, i) {
row.score = row.score.replace(/[^\d]/g, '') row.score = row.score.replace(/[^\d\.]/g, '')
this.projectJudgmentData.splice(i, 1, row); this.projectJudgmentData.splice(i, 1, row);
}, },
delJudgePoint (index) { // delJudgePoint (index) { //

@ -22,7 +22,6 @@ let uploadURL = `https://izhixinyun.com/`
let title = '教师管理端' let title = '教师管理端'
if (isPro) { if (isPro) {
bankPath = `https://www.huorantech.cn/banksystem`
// 职站生产 // 职站生产
uploadURL = `https://www.huorantech.cn/` uploadURL = `https://www.huorantech.cn/`
jumpPath = `https://www.huorantech.cn/judgmentPoint/` jumpPath = `https://www.huorantech.cn/judgmentPoint/`

Loading…
Cancel
Save