Compare commits

...

33 Commits

  1. 6
      src/App.vue
  2. 44
      src/assets/css/main.css
  3. BIN
      src/assets/img/ach1.png
  4. BIN
      src/assets/img/ach2.png
  5. 1
      src/assets/img/right.svg
  6. 1
      src/assets/img/shrink.svg
  7. 1
      src/assets/img/tag-active.svg
  8. 1
      src/assets/img/tag.svg
  9. 1
      src/assets/img/wrong.svg
  10. 14
      src/components/Header.vue
  11. 11
      src/components/Sidebar.vue
  12. 35
      src/components/upload/config.js
  13. 50
      src/const/ques.js
  14. 34
      src/const/testPaper.js
  15. 38
      src/libs/route/addRoutes.js
  16. 37
      src/libs/util.js
  17. 54
      src/router/index.js
  18. 6
      src/setting.js
  19. 21
      src/utils/api.js
  20. 2
      src/utils/editor.js
  21. 5
      src/views/Home.vue
  22. 152
      src/views/Login.vue
  23. 100
      src/views/course/AddCurriculum.vue
  24. 4
      src/views/course/contentSettings.vue
  25. 72
      src/views/customer/AddCustomer.vue
  26. 779
      src/views/devLogin.vue
  27. 21
      src/views/match/add/index.vue
  28. 355
      src/views/match/add/set.vue
  29. 186
      src/views/match/add/step1.vue
  30. 14
      src/views/match/add/step2.vue
  31. 70
      src/views/match/add/step3.vue
  32. 211
      src/views/match/add/template.vue
  33. 203
      src/views/match/list/index.vue
  34. 16
      src/views/match/manage/index.vue
  35. 111
      src/views/match/manage/matchArch.vue
  36. 930
      src/views/match/manage/matchArchList.vue
  37. 32
      src/views/match/manage/matchInfo.vue
  38. 99
      src/views/match/manage/matchRank.vue
  39. 449
      src/views/match/manage/matchReport.vue
  40. 27
      src/views/match/manage/matchSignup.vue
  41. 675
      src/views/match/manage/otherArchList.vue
  42. 1059
      src/views/match/manage/theoryReport.vue
  43. 413
      src/views/match/manage/trialReport.vue
  44. 75
      src/views/order/AddOrder.vue
  45. 1247
      src/views/parner/staff.vue
  46. 50
      src/views/review/index.vue
  47. 2
      src/views/serve/Configure.vue
  48. 318
      src/views/serve/projectAdd.vue
  49. 1879
      src/views/setting/info.vue
  50. 318
      src/views/system/staff.vue
  51. 2
      src/views/theoreticalCourse/contentSettings/index.vue
  52. 581
      src/views/theoreticalCourse/preview/index.vue
  53. 17
      src/views/theoryExam/index.vue

@ -1,6 +1,6 @@
<template> <template>
<div id="app"> <div id="app">
<el-radio-group v-if="Setting.isDev" v-model="ip" @change="ipChange"> <el-radio-group v-if="Setting.isDev" class="ip" v-model="ip" @change="ipChange">
<el-radio :label="0">刘榕ip</el-radio> <el-radio :label="0">刘榕ip</el-radio>
<el-radio :label="1">陈赓ip</el-radio> <el-radio :label="1">陈赓ip</el-radio>
<el-radio :label="2">测试服ip</el-radio> <el-radio :label="2">测试服ip</el-radio>
@ -20,6 +20,10 @@ export default {
}; };
}, },
created () { created () {
window.exitSystem = () => {
sessionStorage.removeItem('token')
location.reload()
}
//sessionStorage //sessionStorage
if (sessionStorage.getItem("store")) { if (sessionStorage.getItem("store")) {
this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem("store")))) this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem("store"))))

@ -19,6 +19,12 @@ body {
font-size: 14px; font-size: 14px;
} }
.ip {
z-index: 1;
position: fixed;
top: 0;
left: 0;
}
a { a {
text-decoration: none; text-decoration: none;
} }
@ -458,7 +464,7 @@ li {
} }
} }
.el-tooltip__popper { .el-tooltip__popper {
max-width: 500px !important; max-width: 100% !important;
} }
.no-atTheMoment > .el-picker-panel__footer > .el-button--text:first-child { .no-atTheMoment > .el-picker-panel__footer > .el-button--text:first-child {
display: none; display: none;
@ -485,3 +491,39 @@ li {
.edui-default { .edui-default {
line-height: normal; line-height: normal;
} }
.html-parse {
table {
display: table;
margin-bottom: 10px;
border-collapse: collapse;
th,
td {
padding: 5px 10px;
border: 1px solid #DDD;
}
}
ol {
padding-left: 30px;
li {
list-style-type: decimal;
}
}
ul {
padding-left: 30px;
li {
list-style-type: disc;
}
}
}
.files-tip {
li {
line-height: 1.8;
cursor: pointer;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1723792589398" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5839" width="20" height="20" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M874 150C674.09-50 349.91-50 150 150s-200 524.09 0 724 524.09 200 724 0 200-524.09 0-724zM760.57 440.57l-256 256a80 80 0 0 1-113.14 0l-128-128a80 80 0 0 1 113.14-113.14L448 526.86l199.43-199.43a80 80 0 0 1 113.14 113.14z" fill="#2abd8c" p-id="5840"></path></svg>

After

Width:  |  Height:  |  Size: 593 B

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1723535697263" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5903" width="18" height="18" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M877.5 565.9l-367.6-340-367.6 340c-22.5 14.5-52.5 14.5-67.5 0-15-21.7-15-50.7 0-65.1L495 117.5c0-7.2 7.5-7.2 15-7.2s7.5 0 15 7.2l420.2 383.3c22.5 21.7 15 50.6 0 65.1-22.7 14.5-52.7 14.5-67.7 0zM494.8 450.1c0-7.2 7.5-7.2 15-7.2s15 0 15 7.2L945 833.4c22.5 21.7 15 50.6 0 65.1-22.5 14.4-52.5 14.4-67.5 0L509.8 558.6 142.2 905.8c-22.5 14.5-52.5 14.5-67.5 0-15-21.7-15-50.7 0-65.1l420.1-390.6z m0 0" fill="#666666" p-id="5904"></path></svg>

After

Width:  |  Height:  |  Size: 766 B

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1723619200843" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7128" width="18" height="18" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M695.7 118.6H326.9c-58.2 0-105.4 47.2-105.4 105.4v579.6c0 58.2 47.2 105.4 105.4 105.4l184.4-184.4L695.7 909c58.2 0 105.4-47.2 105.4-105.4V224c0-58.2-47.1-105.4-105.4-105.4z" fill="#d81e06" p-id="7129"></path></svg>

After

Width:  |  Height:  |  Size: 545 B

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1723619200843" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7128" width="18" height="18" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M695.7 118.6H326.9c-58.2 0-105.4 47.2-105.4 105.4v579.6c0 58.2 47.2 105.4 105.4 105.4l184.4-184.4L695.7 909c58.2 0 105.4-47.2 105.4-105.4V224c0-58.2-47.1-105.4-105.4-105.4z" fill="#bfbfbf" p-id="7129"></path></svg>

After

Width:  |  Height:  |  Size: 545 B

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1723792667165" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7415" width="20" height="20" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M480 64C217.6 64 0 281.6 0 544s217.6 480 480 480 480-217.6 480-480S742.4 64 480 64z m204.8 614.4c19.2 19.2 19.2 44.8 0 64-19.2 19.2-44.8 19.2-64 0L486.4 608 345.6 748.8c-19.2 19.2-51.2 19.2-70.4 0-19.2-19.2-19.2-51.2 0-70.4L416 537.6 281.6 403.2c-19.2-19.2-19.2-44.8 0-64 19.2-19.2 44.8-19.2 64 0L480 473.6l140.8-140.8c19.2-19.2 51.2-19.2 70.4 0 19.2 19.2 19.2 51.2 0 70.4L550.4 544l134.4 134.4z" fill="#e75050" p-id="7416"></path></svg>

After

Width:  |  Height:  |  Size: 768 B

@ -10,7 +10,7 @@
<span class="user-avator">{{ userName }}</span> <span class="user-avator">{{ userName }}</span>
</div> </div>
<el-divider class="ml20" direction="vertical"></el-divider> <el-divider class="ml20" direction="vertical"></el-divider>
<el-button type="text" class="ml20" @click="loginout">退出</el-button> <el-button type="text" class="ml20" @click="logout">退出</el-button>
</div> </div>
</div> </div>
</div> </div>
@ -21,6 +21,7 @@ import Setting from '@/setting'
export default { export default {
data () { data () {
return { return {
timer: null,
Setting, Setting,
userName: '', userName: '',
}; };
@ -34,9 +35,10 @@ export default {
this.$router.push('/person') this.$router.push('/person')
} }
}, },
loginout () { async logout () {
localStorage.removeItem('ms_username'); await this.$post(this.api.logout)
localStorage.removeItem('token'); localStorage.removeItem('ms_username')
localStorage.removeItem('token')
sessionStorage.clear() sessionStorage.clear()
location.reload() location.reload()
}, },
@ -80,8 +82,8 @@ export default {
}, },
// //
heartbeatDetection () { heartbeatDetection () {
setInterval(async () => { this.timer = setInterval(async () => {
await this.$get(this.api.heartbeatDetection) sessionStorage.getItem('token') ? await this.$get(this.api.heartbeatDetection) : clearInterval(this.timer)
}, 58 * 1000) }, 58 * 1000)
}, },

@ -89,7 +89,7 @@ export default {
title: '系统配置' title: '系统配置'
}, },
{ {
icon: 'el-icon-s-check', icon: 'el-icon-box',
index: '/parner', index: '/parner',
title: '合伙管理' title: '合伙管理'
}, },
@ -99,15 +99,20 @@ export default {
title: '合伙运营' title: '合伙运营'
}, },
{ {
icon: 'el-icon-s-shop', icon: 'el-icon-shopping-cart-2',
index: '/shop', index: '/shop',
title: '商城管理' title: '商城管理'
}, },
{ {
icon: 'el-icon-s-shop', icon: 'el-icon-data-board',
index: '/theoryExam', index: '/theoryExam',
title: '考试平台' title: '考试平台'
}, },
{
icon: 'el-icon-document-copy',
index: '/review',
title: '评阅平台'
},
], ],
menus: [], menus: [],
onRoutes: this.$route.path onRoutes: this.$route.path

@ -1,31 +1,22 @@
/** /**
* 阿里云oss配置 * 阿里云oss配置
* */ * */
import { get } from '@/utils/http'
import api from '@/utils/api'
import CryptoJS from 'crypto-js'
import JSEncrypt from 'jsencrypt'
const A = (key, encryptedData) => {
const keyHex = CryptoJS.enc.Base64.parse(key)
const decrypted = CryptoJS.AES.decrypt(encryptedData, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
})
return decrypted.toString(CryptoJS.enc.Utf8)
}
const R = (encryptedKey, privateKey) => {
const decrypt = new JSEncrypt()
decrypt.setPrivateKey(privateKey)
const decryptedKey = decrypt.decrypt(encryptedKey)
return decryptedKey
}
import router from '@/router/index'
import { Message } from 'element-ui'
export default async function () { export default async function () {
try { try {
const res = await get(api.encrypt) let RE = localStorage.getItem('osc')
const RE = A(R(res.encryptedKey, res.privateKey), res.encryptedData).split('/') if (RE) {
RE = JSON.parse(RE)
} else {
sessionStorage.removeItem('token')
Message.error('登录过期,请重新登录!')
setTimeout(() => {
router.replace('/login')
}, 1500)
return false
}
return { return {
// oss账号信息 // oss账号信息
config: { config: {

@ -0,0 +1,50 @@
export default {
difficults: [
{
id: 'basic',
name: '基础',
coefficient: 0.2, // 难度系数,试卷里计算试卷难度专用
theme: 'success',
},
{
id: 'easy',
name: '普通',
coefficient: 0.4,
theme: '',
},
{
id: 'medium',
name: '较难',
coefficient: 0.6,
theme: 'warning',
},
{
id: 'hard',
name: '难',
coefficient: 0.8,
theme: 'danger',
},
],
questionTypes: [
{
id: 'single_choice',
name: '单选题'
},
{
id: 'multiple_choice',
name: '多选题'
},
{
id: 'judgement',
name: '判断题'
},
{
id: 'fill_blank',
name: '填空题'
},
{
id: 'essay',
name: '问答题'
},
],
}

@ -0,0 +1,34 @@
export default {
difficults: [
{
id: 1,
name: '简单'
},
{
id: 2,
name: '普通'
},
{
id: 3,
name: '较难'
},
{
id: 4,
name: '难'
},
],
paperTypes: [
{
id: 0,
name: '练习'
},
{
id: 1,
name: '考核'
},
{
id: 2,
name: '竞赛'
},
],
}

@ -3,27 +3,27 @@ import generateBtnPermission from '../auth/generateBtnPermission';
const newRoutes = [] const newRoutes = []
function createMeta(item){ function createMeta (item) {
let meta = { title: item.name } let meta = { title: item.name }
return meta return meta
} }
function createRoute(data){ function createRoute (data) {
data.map(e => { data.map(e => {
if(e.path){ if (e.path) {
let meta = createMeta(e) let meta = createMeta(e)
newRoutes.push({ newRoutes.push({
path: e.path, path: e.path,
meta meta
}) })
} }
// 递归生成路由集合 // 递归生成路由集合
e.children && e.children.length && createRoute(e.children) e.children && e.children.length && createRoute(e.children)
}) })
} }
export default function(data,path){ export default function (data, path) {
generateBtnPermission(data) generateBtnPermission(data)
createRoute(data) createRoute(data)
store.commit('addRoutes',newRoutes) store.commit('addRoutes', newRoutes)
} }

@ -172,6 +172,43 @@ const util = {
resolve(new Date(data.currentTime)) resolve(new Date(data.currentTime))
}) })
}, },
// 阿拉伯数字转化为中文数字
arabicToChinese (num) {
const arr1 = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
const arr2 = ['', '十', '百', '千', '万', '亿', '点', ''];
const a = `${num}`.replace(/(^0*)/g, '').split('.');
let k = 0;
let re = '';
for (let i = a[0].length - 1; i >= 0; i--) {
switch (k) {
case 0:
re = arr2[7] + re;
break;
case 4:
if (!new RegExp(`0{4}//d{${a[0].length - i - 1}}$`).test(a[0])) re = arr2[4] + re;
break;
case 8:
re = arr2[5] + re;
arr2[7] = arr2[5];
k = 0;
break;
default:
}
if (k % 4 == 2 && a[0].charAt(i + 2) != 0 && a[0].charAt(i + 1) == 0) re = arr1[0] + re;
if (a[0].charAt(i) != 0) re = arr1[a[0].charAt(i)] + arr2[k % 4] + re;
k++;
}
return num > 9 && num < 20 ? re.slice(1) : re;
},
// 阿拉伯数字转化为英文字母
numToLetter (num) {
let result = ''
if (num > 26) {
result += numberToLetter((num / 26) >> 0 - 1)
}
result += String.fromCharCode(65 + (num % 26))
return result
},
} }
export default util export default util

@ -19,143 +19,123 @@ let router = new Router({
{ {
path: '/customer', path: '/customer',
component: () => import('../views/customer/customer.vue'), component: () => import('../views/customer/customer.vue'),
// meta: { title: '客户管理' }
}, },
{ {
path: '/addcustomer', path: '/addcustomer',
component: () => import('../views/customer/AddCustomer.vue'), component: () => import('../views/customer/AddCustomer.vue'),
// meta: { title: '新增客户' }
}, },
{ {
path: '/bmOrder', path: '/bmOrder',
component: () => import('../views/customer/Order.vue'), component: () => import('../views/customer/Order.vue'),
// meta: { title: '新增客户' }
}, },
{ {
path: '/user', path: '/user',
component: () => import('../views/user/User.vue'), component: () => import('../views/user/User.vue'),
// meta: { title: '用户管理' }
}, },
{ {
path: '/adduser', path: '/adduser',
component: () => import('../views/user/AddUser.vue'), component: () => import('../views/user/AddUser.vue'),
// meta: { title: '新增用户' }
}, },
{ {
path: '/info', path: '/info',
component: () => import('../views/user/Info.vue'), component: () => import('../views/user/Info.vue'),
// meta: { title: '新增用户' }
}, },
{ {
path: '/order', path: '/order',
component: () => import('../views/order/Order.vue'), component: () => import('../views/order/Order.vue'),
// meta: { title: '订单管理' }
}, },
{ {
path: '/addorder', path: '/addorder',
component: () => import('../views/order/AddOrder.vue'), component: () => import('../views/order/AddOrder.vue'),
// meta: { title: '新增订单' }
}, },
{ {
path: '/selectClient', path: '/selectClient',
component: () => import('../views/order/selectClient.vue'), component: () => import('../views/order/selectClient.vue'),
// meta: { title: '选择订单客户' }
}, },
{ {
path: '/configure', path: '/configure',
component: () => import('../views/serve/Configure.vue'), component: () => import('../views/serve/Configure.vue'),
// meta: { title: '服务配置' }
}, },
{ {
path: '/backstage', path: '/backstage',
component: () => import('../views/serve/backstage'), component: () => import('../views/serve/backstage'),
// meta: { title: '服务配置' }
}, },
{ {
path: '/addModel', path: '/addModel',
component: () => import('../views/serve/addModel'), component: () => import('../views/serve/addModel'),
// meta: { title: '服务配置' }
}, },
{ {
path: '/addconfigure', path: '/addconfigure',
component: () => import('../views/serve/AddConfigure.vue'), component: () => import('../views/serve/AddConfigure.vue'),
// meta: { title: '新增配置' }
}, },
{ {
path: '/projectList', path: '/projectList',
component: () => import('../views/serve/projectList.vue'), component: () => import('../views/serve/projectList.vue'),
// meta: { title: '项目管理' }
}, },
{ {
path: '/projectAdd', path: '/projectAdd',
component: () => import('../views/serve/projectAdd.vue'), component: () => import('../views/serve/projectAdd.vue'),
// meta: { title: '项目配置' }
}, },
{ {
path: '/curriculum', path: '/curriculum',
component: () => import('../views/course/Curriculum.vue'), component: () => import('../views/course/Curriculum.vue'),
// meta: { title: '课程管理' }
}, },
{ {
path: '/addcurriculum', path: '/addcurriculum',
component: () => import('../views/course/AddCurriculum.vue'), component: () => import('../views/course/AddCurriculum.vue'),
// meta: { title: '新建课程' }
}, },
{ {
path: '/contentSettings', path: '/contentSettings',
component: () => import('../views/course/contentSettings.vue'), component: () => import('../views/course/contentSettings.vue'),
// meta: { title: '内容设置' }
}, },
{ {
path: '/addlink', path: '/addlink',
component: () => import('../views/course/AddLink.vue'), component: () => import('../views/course/AddLink.vue'),
// meta: { title: '添加环节' }
}, },
{ {
path: '/data', path: '/data',
component: () => import('../views/data/Data.vue'), component: () => import('../views/data/Data.vue'),
// meta: { title: '数据管理' }
}, },
{ {
path: '/match', path: '/match',
component: () => import('../views/match/list'), component: () => import('../views/match/list'),
// meta: { title: '数据管理' }
}, },
{ {
path: '/addMatch', path: '/addMatch',
component: () => import('../views/match/add'), component: () => import('../views/match/add'),
// meta: { title: '数据管理' }
}, },
{ {
path: '/matchManage', path: '/matchManage',
component: () => import('../views/match/manage'), component: () => import('../views/match/manage'),
// meta: { title: '数据管理' }
}, },
{ {
path: '/noticeDetail', path: '/noticeDetail',
component: () => import('../views/match/manage/noticeDetail'), component: () => import('../views/match/manage/noticeDetail'),
// meta: { title: '数据管理' }
}, },
{ {
path: '/matchArchList', path: '/otherArchList',
component: () => import('../views/match/manage/matchArchList'), component: () => import('../views/match/manage/otherArchList'),
// meta: { title: '数据管理' }
}, },
{ {
path: '/matchRank', path: '/matchRank',
component: () => import('../views/match/manage/matchRank'), component: () => import('../views/match/manage/matchRank'),
// meta: { title: '数据管理' }
}, },
{ {
path: '/matchReport', path: '/trialReport',
component: () => import('../views/match/manage/matchReport'), component: () => import('../views/match/manage/trialReport'),
// meta: { title: '数据管理' } },
{
path: '/matchArchList',
component: () => import('../views/match/manage/matchArchList'),
},
{
path: '/theoryReport',
component: () => import('../views/match/manage/theoryReport'),
}, },
{ {
path: '/matchInfo', path: '/matchInfo',
component: () => import('../views/match/manage/matchInfo'), component: () => import('../views/match/manage/matchInfo'),
// meta: { title: '数据管理' }
}, },
{ {
path: `/theoreticalCourse`, path: `/theoreticalCourse`,
@ -190,32 +170,26 @@ let router = new Router({
{ {
path: '/system', path: '/system',
component: () => import('../views/system'), component: () => import('../views/system'),
// meta: { title: '数据管理' }
}, },
{ {
path: '/manageLog', path: '/manageLog',
component: () => import('../views/system/manageLog'), component: () => import('../views/system/manageLog'),
// meta: { title: '数据管理' }
}, },
{ {
path: '/addLog', path: '/addLog',
component: () => import('../views/system/addLog'), component: () => import('../views/system/addLog'),
// meta: { title: '数据管理' }
}, },
{ {
path: '/permission', path: '/permission',
component: () => import('../views/customer/Permission.vue'), component: () => import('../views/customer/Permission.vue'),
// meta: { title: '应用权限', permission: true }
}, },
{ {
path: '/person', path: '/person',
component: () => import('../views/setting'), component: () => import('../views/setting'),
// meta: { title: '个人中心' }
}, },
{ {
path: '/parner', path: '/parner',
component: () => import('../views/parner'), component: () => import('../views/parner'),
// meta: { title: '个人中心' }
}, },
{ {
path: '/parnerOperation', path: '/parnerOperation',
@ -245,6 +219,10 @@ let router = new Router({
path: '/theoryExam', path: '/theoryExam',
component: () => import('../views/theoryExam'), component: () => import('../views/theoryExam'),
}, },
{
path: '/review',
component: () => import('../views/review'),
},
{ {
path: '/404', path: '/404',
component: () => import('../views/404.vue'), component: () => import('../views/404.vue'),

@ -5,7 +5,7 @@ const url = location.host;
const isDev = process.env.NODE_ENV === 'development' // 开发环境 const isDev = process.env.NODE_ENV === 'development' // 开发环境
const isPro = url.includes('huorantech.cn') //正式服 const isPro = url.includes('huorantech.cn') //正式服
let jumpPath = `${location.origin}/judgmentPoint/` let jumpPath = `${location.origin}/panfen/`
let sandPath = `http://121.37.12.51/sandbox` // 沙盘地址 let sandPath = `http://121.37.12.51/sandbox` // 沙盘地址
let host = `${location.origin}/` let host = `${location.origin}/`
if (isDev) { if (isDev) {
@ -18,7 +18,7 @@ if (isDev) {
host = ips[+localStorage.getItem('ip')] host = ips[+localStorage.getItem('ip')]
} else if (isPro) { } else if (isPro) {
sandPath = `https://izhixinyun.com/sandbox` sandPath = `https://izhixinyun.com/sandbox`
jumpPath = 'https://judgment.huorantech.cn/' // jumpPath = 'https://judgment.huorantech.cn/'
} }
@ -51,7 +51,7 @@ const Setting = {
isDev, isDev,
isPro, isPro,
// 是否使用动态路由 // 是否使用动态路由
dynamicRoute: false, dynamicRoute: true,
/** /**
* @description 默认密码 * @description 默认密码
*/ */

@ -13,9 +13,11 @@ export default {
refreshPageNotification: `nakadai/message/refreshPageNotification`, refreshPageNotification: `nakadai/message/refreshPageNotification`,
heartbeatDetection: `nakadai/message/heartbeatDetection`, heartbeatDetection: `nakadai/message/heartbeatDetection`,
getCurrentTime: `competition/competition/management/getCurrentTime`, getCurrentTime: `competition/competition/management/getCurrentTime`,
getToken: `users/users/user/getToken`,
logout: `users/users/user/logout`,
// 阿里云文件/视频管理 // 阿里云文件/视频管理
getPlayAuth: `${uploadURL}oss/manage/getPlayAuth`, // 获取播放凭证 getPlayAuth: `nakadai/nakadai/oss/getPlayAuth`, // 获取播放凭证
encrypt: `nakadai/data/encrypt`, encrypt: `nakadai/data/encrypt`,
staffTemplate: `https://occupationlab.com/template/%E6%89%B9%E9%87%8F%E5%AF%BC%E5%85%A5%E5%91%98%E5%B7%A5%E6%A8%A1%E6%9D%BF.xlsx`, // 后台账号模板 staffTemplate: `https://occupationlab.com/template/%E6%89%B9%E9%87%8F%E5%AF%BC%E5%85%A5%E5%91%98%E5%B7%A5%E6%A8%A1%E6%9D%BF.xlsx`, // 后台账号模板
@ -37,6 +39,7 @@ export default {
getOrderOtherTime: `nakadai/nakadai/orderOther/getOrderOtherTime`, getOrderOtherTime: `nakadai/nakadai/orderOther/getOrderOtherTime`,
refreshCache: `data/data/myDate/refreshCache`, refreshCache: `data/data/myDate/refreshCache`,
getPartnerTeamRates: `nakadai/nakadai/partner-team/getPartnerTeamRates`, getPartnerTeamRates: `nakadai/nakadai/partner-team/getPartnerTeamRates`,
getCustomerOrderRecord: `nakadai/nakadai/order/getCustomerOrderRecord`,
// 客户管理 // 客户管理
delCustomers: `nakadai/nakadai/customer/delCustomers`, delCustomers: `nakadai/nakadai/customer/delCustomers`,
@ -103,8 +106,8 @@ export default {
editProjectDraft: `occupationlab/occupationlab/projectManage/editProjectDraft`, // 修改项目管理 editProjectDraft: `occupationlab/occupationlab/projectManage/editProjectDraft`, // 修改项目管理
copyProjectManage: `occupationlab/occupationlab/projectManage/copyProjectManage`, // 复制项目管理 copyProjectManage: `occupationlab/occupationlab/projectManage/copyProjectManage`, // 复制项目管理
// 判分点 // 判分点
getBcJudgmentPoint: `${jumpApi}judgment/judgment/bcJudgmentPoint/getBcJudgmentPoint`, // 获取编程类判分点列表(分页) getBcJudgmentPoint: `${host}judgment/judgment/bcJudgmentPoint/getBcJudgmentPoint`, // 获取编程类判分点列表(分页)
getLcJudgmentPoint: `${jumpApi}judgment/judgment/lcJudgmentPoint/queryAllJudgmentPoint`, // 获取流程类判分点列表(分页) getLcJudgmentPoint: `${host}judgment/judgment/lcJudgmentPoint/queryAllJudgmentPoint`, // 获取流程类判分点列表(分页)
addProjectJudgment: `occupationlab/occupationlab/projectJudgment/addProjectJudgment`, // 添加项目管理、判分点中间表 addProjectJudgment: `occupationlab/occupationlab/projectJudgment/addProjectJudgment`, // 添加项目管理、判分点中间表
updateProjectJudgment: `occupationlab/occupationlab/projectJudgment/updateProjectJudgment`, // 判分点中间表批量更新 updateProjectJudgment: `occupationlab/occupationlab/projectJudgment/updateProjectJudgment`, // 判分点中间表批量更新
deleteProjectJudgment: `occupationlab/occupationlab/projectJudgment/deleteProjectJudgment`, // 判分点中间表批量删除 deleteProjectJudgment: `occupationlab/occupationlab/projectJudgment/deleteProjectJudgment`, // 判分点中间表批量删除
@ -338,6 +341,14 @@ export default {
checkTeamStatus: `competition/teamAbnormalInformation/checkTeamStatus`, checkTeamStatus: `competition/teamAbnormalInformation/checkTeamStatus`,
queryAbnormalTeam: `competition/teamAbnormalInformation/queryAbnormalTeam`, queryAbnormalTeam: `competition/teamAbnormalInformation/queryAbnormalTeam`,
viewEventAllocationInformation: `competition/competitionAutomaticAllocationRecord/viewEventAllocationInformation`, viewEventAllocationInformation: `competition/competitionAutomaticAllocationRecord/viewEventAllocationInformation`,
getCompetitionProjectByMiddleGround: `occupationlab/occupationlab/projectManage/getCompetitionProjectByMiddleGround`,
libraryList: `exam/exam/paperLibrary/libraryList`,
examPaperList: `exam/exam/paper/examPaperList`,
copyExamPaper: `exam/exam/paper/copyExamPaper`,
getDetailedExamScores: `exam/exam/paper/getDetailedExamScores`,
exportExamPaperReport: `exam/exam/paper/exportExamPaperReport`,
exportLabReport: `occupationlab/occupationlab/achievement/exportLabReport`,
exportBankExperimentReport: `occupationlab/occupationlab/achievement/exportBankExperimentReport`,
// 赛事内容 // 赛事内容
addCompetitionContent: `competition/competition/content/addCompetitionContent`, addCompetitionContent: `competition/competition/content/addCompetitionContent`,
@ -405,9 +416,12 @@ export default {
batchDeleteContestGrade: `competition/competition/performance/batchDeleteContestGrade`, batchDeleteContestGrade: `competition/competition/performance/batchDeleteContestGrade`,
batchImportGrades: `${host}competition/competition/performance/batchImportGrades`, batchImportGrades: `${host}competition/competition/performance/batchImportGrades`,
exportExperimentalResultsInBatch: `${host}competition/competition/performance/exportExperimentalResultsInBatch`, exportExperimentalResultsInBatch: `${host}competition/competition/performance/exportExperimentalResultsInBatch`,
exportExamPaperReports: `${host}exam/exam/paper/exportExamPaperReports`,
batchExportReportsAsZip: `${host}occupationlab/occupationlab/achievement/batchExportReportsAsZip`,
performanceExportFailure: `${host}competition/competition/performance/exportFailure`, performanceExportFailure: `${host}competition/competition/performance/exportFailure`,
rankExportFailure: `${host}competition/competition/rank/exportFailure`, rankExportFailure: `${host}competition/competition/rank/exportFailure`,
batchImportRanking: `${host}competition/competition/rank/batchImportRanking`, batchImportRanking: `${host}competition/competition/rank/batchImportRanking`,
getPaperUploadFileZip: `${host}exam/exam/paper/question/userAnswer/getPaperUploadFileZip`,
stageGradeManagementList: `competition/competition/performance/stageGradeManagementList`, stageGradeManagementList: `competition/competition/performance/stageGradeManagementList`,
stageRaceRanking: `competition/competition/rank/stageRaceRanking`, stageRaceRanking: `competition/competition/rank/stageRaceRanking`,
overallStandingsInThePointsRace: `competition/competition/rank/overallStandingsInThePointsRace`, overallStandingsInThePointsRace: `competition/competition/rank/overallStandingsInThePointsRace`,
@ -433,6 +447,7 @@ export default {
getCompetitionStageRankingTime: `competition/competitionReleaseTime/getCompetitionStageRankingTime`, getCompetitionStageRankingTime: `competition/competitionReleaseTime/getCompetitionStageRankingTime`,
frontOfficeCompetitionRanking: `competition/competition/rank/frontOfficeCompetitionRanking`, frontOfficeCompetitionRanking: `competition/competition/rank/frontOfficeCompetitionRanking`,
cCompetitionStageFileList: `competition/cCompetitionStageFile/listByEntity`, cCompetitionStageFileList: `competition/cCompetitionStageFile/listByEntity`,
getPaperUploadFile: `exam/exam/paper/question/userAnswer/getPaperUploadFile`,
derive: `${host}competition/cCompetitionStageFile/deriveAll`, derive: `${host}competition/cCompetitionStageFile/deriveAll`,
allExperimentalResultsAreDerived: `${host}competition/competition/performance/allExperimentalResultsAreDerived`, allExperimentalResultsAreDerived: `${host}competition/competition/performance/allExperimentalResultsAreDerived`,
derivedRanking: `${host}competition/competition/rank/derivedRanking`, derivedRanking: `${host}competition/competition/rank/derivedRanking`,

@ -5,7 +5,7 @@ export default {
//skin:'oxide-dark', //skin:'oxide-dark',
language: 'zh_CN', language: 'zh_CN',
language_url: './styles/tinymce/langs/zh_CN.js', language_url: './styles/tinymce/langs/zh_CN.js',
plugins: 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount imagetools textpattern help emoticons autosave autoresize', plugins: 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount imagetools textpattern help emoticons autoresize',
toolbar: 'code undo redo restoredraft | cut copy pastetext | forecolor backcolor headings fontsize lineHeight bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify | \ toolbar: 'code undo redo restoredraft | cut copy pastetext | forecolor backcolor headings fontsize lineHeight bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify | \
styleselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \ styleselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \
table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | indent2em', table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | indent2em',

@ -4,8 +4,7 @@
<v-sidebar></v-sidebar> <v-sidebar></v-sidebar>
<div class="content-box"> <div class="content-box">
<div class="content"> <div class="content">
<transition name="move" <transition name="move" mode="out-in">
mode="out-in">
<!-- <keep-alive> --> <!-- <keep-alive> -->
<router-view></router-view> <router-view></router-view>
<!-- </keep-alive> --> <!-- </keep-alive> -->
@ -32,7 +31,7 @@ export default {
vSidebar, vSidebar,
}, },
created () { created () {
this.autoLogout() // this.autoLogout()
}, },
methods: { methods: {
// ,退 // ,退

@ -39,7 +39,7 @@
<el-form v-show="activeIndex === '2'" :model="phoneOrEmail" :rules="phoneOrEmailrules" ref="phoneOrEmail" <el-form v-show="activeIndex === '2'" :model="phoneOrEmail" :rules="phoneOrEmailrules" ref="phoneOrEmail"
label-width="0px" style="margin-top: 20px"> label-width="0px" style="margin-top: 20px">
<el-form-item prop="account"> <el-form-item prop="account">
<el-input @blur="phoneBlur" v-model="phoneOrEmail.account" placeholder="请输入电话/邮箱"></el-input> <el-input @blur="phoneBlur" v-model="phoneOrEmail.workNumber" placeholder="请输入电话/邮箱"></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<el-input type="password" placeholder="请输入密码" v-model="phoneOrEmail.password"> <el-input type="password" placeholder="请输入密码" v-model="phoneOrEmail.password">
@ -80,6 +80,21 @@
<el-button type="primary" @click="phoneSubmit"> </el-button> <el-button type="primary" @click="phoneSubmit"> </el-button>
</span> </span>
</el-dialog> </el-dialog>
<el-dialog title="请选择您要登录的用户" :visible.sync="userVisible" :close-on-click-modal="false" custom-class="user-dia"
width="500px">
<p class="tips">该手机号已绑定以下用户信息</p>
<ul class="users">
<li :class="{ isEnable: !user.isEnable }" v-for="(user, i) in users" :key="i" @click="chooseUser(user)">
<span>{{ user.schoolName }}{{ user.userName }}{{ user.workNumber }}{{
user.isEnable
? ''
: '(已禁用)' }}</span>
<i class="el-icon-right"></i>
</li>
</ul>
</el-dialog>
<v-footer class="footer" ref="footer"></v-footer> <v-footer class="footer" ref="footer"></v-footer>
</div> </div>
</template> </template>
@ -88,6 +103,8 @@
import vFooter from '../components/Footer' import vFooter from '../components/Footer'
import Setting from '@/setting' import Setting from '@/setting'
import addRoutes from '@/libs/route/addRoutes' import addRoutes from '@/libs/route/addRoutes'
import CryptoJS from 'crypto-js'
import JSEncrypt from 'jsencrypt'
export default { export default {
data: function () { data: function () {
var regPhoneOrEmail = (rule, value, callback) => {// var regPhoneOrEmail = (rule, value, callback) => {//
@ -115,7 +132,6 @@ export default {
platform: 3, platform: 3,
random: '', random: '',
distinguish: 1, distinguish: 1,
type: 2
}, },
rules: { rules: {
account: [{ required: true, message: '请输入账号', trigger: 'blur' }], account: [{ required: true, message: '请输入账号', trigger: 'blur' }],
@ -127,16 +143,15 @@ export default {
showPhoneVerify: true,// - showPhoneVerify: true,// -
PhoneVerificationIMG: '',// PhoneVerificationIMG: '',//
phoneOrEmail: { phoneOrEmail: {
account: '', workNumber: '',
password: '', password: '',
code: '', code: '',
platform: 3, platform: 3,
random: '', random: '',
distinguish: 2, distinguish: 1,
type: 2
}, },
phoneOrEmailrules: { phoneOrEmailrules: {
account: [{ validator: regPhoneOrEmail, trigger: 'blur' }], workNumber: [{ validator: regPhoneOrEmail, trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }], password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
code: [{ required: true, message: '请输入验证码', trigger: 'blur' }], code: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
}, },
@ -147,8 +162,11 @@ export default {
phoneDisabled: false, phoneDisabled: false,
phoneBtnText: '发送验证码', phoneBtnText: '发送验证码',
phoneTimer: '', phoneTimer: '',
phoneOpener: '' phoneOpener: '',
userVisible: false,
users: [],
}; };
}, },
components: { components: {
@ -182,23 +200,24 @@ export default {
let param = val === 'phone' ? this.phoneOrEmail : this.param let param = val === 'phone' ? this.phoneOrEmail : this.param
this.$refs[ref].validate(valid => { this.$refs[ref].validate(valid => {
if (valid) { if (valid) {
this.$post(this.api.logins, param).then(res => { this.$post(this.api.logins, param).then(({ status, data, message }) => {
const { message } = res localStorage.removeItem('examPath')
sessionStorage.setItem('token', res.data.token) localStorage.removeItem('reviewPath')
this.$get(`${this.api.getUserRolesPermissionMenu}?platformId=${Setting.platformId}`).then(res => { this.getOss()
const list = res.permissionMenu if (status == 200) {
addRoutes(res.permissionMenu[0].children) const accounts = data.userAccounts
this.$store.commit('setDataPer', res.dataPermissionList) //
this.$message.success(message); if (accounts instanceof Array) {
this.$router.push({ this.users = accounts
path: list[0].children[0].path this.userVisible = true
}); } else {
localStorage.setItem('ms_username', this.param.username); sessionStorage.setItem('token', data.token)
}).catch(err => { this.setLogin()
if (err.status === 500) {
sessionStorage.clear()
} }
}) } else {
param.code = ''
this.$message.error(message)
}
}).catch(err => { }).catch(err => {
if (err.status === 30001) { if (err.status === 30001) {
this.phoneVisible = true this.phoneVisible = true
@ -212,7 +231,54 @@ export default {
return false; return false;
} }
}); });
},
// oss
async getOss () {
const A = (key, encryptedData) => {
const keyHex = CryptoJS.enc.Base64.parse(key)
const decrypted = CryptoJS.AES.decrypt(encryptedData, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
})
return decrypted.toString(CryptoJS.enc.Utf8)
}
const R = (encryptedKey, privateKey) => {
const decrypt = new JSEncrypt()
decrypt.setPrivateKey(privateKey)
const decryptedKey = decrypt.decrypt(encryptedKey)
return decryptedKey
}
const res = await this.$get(this.api.encrypt)
const RE = A(R(res.encryptedKey, res.privateKey), res.encryptedData).split('/')
localStorage.setItem('osc', JSON.stringify(RE))
},
//
chooseUser (user) {
user.isEnable && this.$post(`${this.api.getToken}?id=${user.id}`).then(({ data }) => {
sessionStorage.setItem('token', data.token)
this.token = data.token
this.setLogin()
}).catch(res => { })
},
//
async setLogin () {
try {
const res = await this.$get(`${this.api.getUserRolesPermissionMenu}?platformId=${Setting.platformId}`)
const list = res.permissionMenu
addRoutes(res.permissionMenu[0].children)
this.$store.commit('setDataPer', res.dataPermissionList)
this.$message.success('登录成功!')
this.$router.push({
path: list[0].children[0].path
});
localStorage.setItem('ms_username', this.param.username);
} catch (e) {
if (e.status === 500) {
sessionStorage.clear()
}
}
}, },
blur () { blur () {
this.param.random = Math.floor(Math.random() * 999999999) this.param.random = Math.floor(Math.random() * 999999999)
@ -437,6 +503,46 @@ img {
color: #666; color: #666;
} }
/deep/.user-dia {
.tips {
margin-bottom: 20px;
text-align: center;
color: #666;
}
.users {
li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 15px;
margin-bottom: 10px;
line-height: 40px;
font-size: 14px;
background-color: #ebeef5;
cursor: pointer;
&.isEnable {
color: #c0c4cc;
background-color: #f5f7fa;
cursor: not-allowed;
}
&:last-child {
margin-bottom: 0;
}
&:hover {
background-color: #d3e0ff;
}
i {
font-size: 16px;
}
}
}
}
@media (max-width: 1600px) { @media (max-width: 1600px) {
/deep/.ms-login { /deep/.ms-login {
width: 1000px; width: 1000px;

@ -106,13 +106,13 @@
@selection-change="handleSelectionPractice"> @selection-change="handleSelectionPractice">
<el-table-column type="selection" width="55" align="center"></el-table-column> <el-table-column type="selection" width="55" align="center"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column> <el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column> <el-table-column prop="projectName" label="项目名称" align="center">
<el-table-column prop="remark" label="备注名称" align="center"></el-table-column>
<el-table-column prop="applicationName" label="系统名称" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.applicationName || systemAll.find(e => e.systemId == scope.row.systemId).systemName }} {{ scope.row.projectName || scope.row.paperName }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="remark" label="备注名称" align="center"></el-table-column>
<el-table-column prop="systemName" label="系统名称" align="center"></el-table-column>
<el-table-column label="排序" align="center" width="100"> <el-table-column label="排序" align="center" width="100">
<template slot-scope="scope"> <template slot-scope="scope">
<el-input v-model.trim="scope.row.sort" <el-input v-model.trim="scope.row.sort"
@ -156,13 +156,13 @@
@selection-change="handleSelectionAssessment"> @selection-change="handleSelectionAssessment">
<el-table-column type="selection" width="55" align="center"></el-table-column> <el-table-column type="selection" width="55" align="center"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column> <el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column> <el-table-column prop="projectName" label="项目名称" align="center">
<el-table-column prop="remark" label="备注名称" align="center"></el-table-column>
<el-table-column prop="applicationName" label="系统名称" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.applicationName || systemAll.find(e => e.systemId == scope.row.systemId).systemName }} {{ scope.row.projectName || scope.row.paperName }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="remark" label="备注名称" align="center"></el-table-column>
<el-table-column prop="systemName" label="系统名称" align="center"></el-table-column>
<el-table-column label="排序" align="center" width="100"> <el-table-column label="排序" align="center" width="100">
<template slot-scope="scope"> <template slot-scope="scope">
<el-input v-model.trim="scope.row.sort" <el-input v-model.trim="scope.row.sort"
@ -205,12 +205,12 @@
@selection-change="handleSelectionMatch"> @selection-change="handleSelectionMatch">
<el-table-column type="selection" width="55" align="center"></el-table-column> <el-table-column type="selection" width="55" align="center"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column> <el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column> <el-table-column prop="projectName" label="项目名称" align="center">
<el-table-column prop="applicationName" label="系统名称" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.applicationName || systemAll.find(e => e.systemId == scope.row.systemId).systemName }} {{ scope.row.projectName || scope.row.paperName }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="systemName" label="系统名称" align="center"></el-table-column>
<el-table-column label="排序" align="center" width="100"> <el-table-column label="排序" align="center" width="100">
<template slot-scope="scope"> <template slot-scope="scope">
<el-input v-model.trim="scope.row.sort" <el-input v-model.trim="scope.row.sort"
@ -272,7 +272,7 @@
@change="val => checkAllChange(val, projects[0].systemId)"></el-checkbox> @change="val => checkAllChange(val, projects[0].systemId)"></el-checkbox>
<li v-for="(item, i) in projects" :key="i" :title="item.projectName"> <li v-for="(item, i) in projects" :key="i" :title="item.projectName">
<el-checkbox v-model="item.check" <el-checkbox v-model="item.check"
:label="item.remark ? item.remark + '(' + item.projectName + ')' : item.projectName" :label="item.remark ? item.remark + '(' + item.projectName + ')' : (item.projectName || item.paperName)"
@change="val => projectChange(val, item)"></el-checkbox> @change="val => projectChange(val, item)"></el-checkbox>
</li> </li>
</ul> </ul>
@ -287,18 +287,18 @@
v-model.trim="checkedKeyword" clearable></el-input> v-model.trim="checkedKeyword" clearable></el-input>
<el-table :data="checkeds" class="table" stripe header-align="center" max-height="470"> <el-table :data="checkeds" class="table" stripe header-align="center" max-height="470">
<el-table-column type="index" width="55" label="序号" align="center"></el-table-column> <el-table-column type="index" width="55" label="序号" align="center"></el-table-column>
<el-table-column prop="applicationName" label="系统名称" align="center"> <el-table-column prop="systemName" label="系统名称" align="center"></el-table-column>
<el-table-column prop="projectName" width="80" label="系统类型" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.applicationName || systemAll.find(e => e.systemId == scope.row.systemId).systemName }} {{ scope.row.type === 1 ? '流程类' : scope.row.type === 3 ? '理论' : '编程类' }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="projectName" width="80" label="系统类型" align="center"> <el-table-column prop="remark" label="备注名称" align="center"></el-table-column>
<el-table-column prop="projectName" label="项目名称" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.type ? '流程类' : '编程类' }} {{ scope.row.projectName || scope.row.paperName }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="remark" label="备注名称" align="center"></el-table-column>
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
<el-table-column label="操作" align="center" width="55"> <el-table-column label="操作" align="center" width="55">
<template slot-scope="scope"> <template slot-scope="scope">
<i :class="['el-icon-delete rm', { disabled: scope.row.disabled }]" <i :class="['el-icon-delete rm', { disabled: scope.row.disabled }]"
@ -415,7 +415,6 @@ export default {
systemChecked: [], systemChecked: [],
curSystem: '', curSystem: '',
projects: [], projects: [],
projectAll: [],
projectKeyword: '', projectKeyword: '',
checkedKeyword: '', checkedKeyword: '',
checkeds: [], checkeds: [],
@ -442,7 +441,7 @@ export default {
projectKeyword: function (val) { projectKeyword: function (val) {
clearTimeout(this.searchTimer); clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => { this.searchTimer = setTimeout(() => {
this.filterProject(); this.getProject();
}, 500); }, 500);
}, },
checkedKeyword: function (val) { checkedKeyword: function (val) {
@ -577,6 +576,7 @@ export default {
this.pageNo = 1; this.pageNo = 1;
this.getConfig(); this.getConfig();
this.checkeds = JSON.parse(JSON.stringify(type == 1 ? this.assessmentData : type == 2 ? this.matches : this.practiceData)) this.checkeds = JSON.parse(JSON.stringify(type == 1 ? this.assessmentData : type == 2 ? this.matches : this.practiceData))
this.checkedAll = JSON.parse(JSON.stringify(this.checkeds))
}, },
// //
getConfig () { getConfig () {
@ -609,26 +609,23 @@ export default {
}).catch(err => { }) }).catch(err => { })
}, },
// //
getProject (item) { async getProject (item, fromSystemChange) {
const checked = this.checkeds const checked = this.checkeds
this.curSystem = item.systemId if (item) this.curSystem = item.systemId
this.$get(`${this.api.getInternalProjectBySystemId}?permissions=${this.permissions}&systemId=${item.systemId}`).then(res => { let res
this.projectAll = JSON.parse(JSON.stringify(res)) // if (!fromSystemChange) {
const result = [] res = await this.$get(`${this.api.getInternalProjectBySystemId}?permissions=${this.permissions}&systemId=${this.curSystem}&keyword=${this.projectKeyword}`)
res.map(e => { }
// const result = []
const include = checked.some(n => n.projectId == e.projectId && n.systemId == e.systemId) const projects = fromSystemChange ? this.projects : res
e.check = include projects.map(e => {
result.push(e) //
}) const include = checked.some(n => (e.projectId && n.projectId == e.projectId && n.systemId == e.systemId) || (e.paperId && n.paperId == e.paperId))
this.checkAll = !result.filter(e => !e.check).length e.check = include
this.projects = result result.push(e)
}).catch(err => { }) })
}, this.checkAll = !result.filter(e => !e.check).length
// this.projects = result
filterProject () {
const val = this.projectKeyword
this.projects = this.projectAll.filter(e => e.projectName.includes(val))
}, },
// //
systemChange (val, item) { systemChange (val, item) {
@ -640,7 +637,7 @@ export default {
}) })
} }
this.projectKeyword = '' this.projectKeyword = ''
this.$get(`${this.api.getInternalProjectBySystemId}?permissions=${this.permissions}&systemId=${item.systemId}`).then(res => { this.$get(`${this.api.getInternalProjectBySystemId}?permissions=${this.permissions}&systemId=${item.systemId}&keyword=${this.projectKeyword}`).then(res => {
if (val) { if (val) {
// //
if (!this.mulSystem) { if (!this.mulSystem) {
@ -648,18 +645,18 @@ export default {
item.check = true item.check = true
} }
res.map(e => { res.map(e => {
if (!checkeds.find(n => n.projectId == e.projectId && n.systemId == e.systemId)) { if (!checkeds.find(n => (e.projectId && n.projectId == e.projectId && n.systemId == e.systemId) || (e.paperId && e.paperId == n.paperId))) {
checkeds.push(e) checkeds.push(e)
} }
}) })
} else { } else {
res.map(e => { res.map(e => {
const i = checkeds.findIndex(n => n.projectId == e.projectId && n.systemId == e.systemId) const i = checkeds.findIndex(n => (e.projectId && n.projectId == e.projectId && n.systemId == e.systemId) || (e.paperId && e.paperId == n.paperId))
i === -1 || checkeds.splice(i, 1) i === -1 || checkeds.splice(i, 1)
}) })
} }
this.checkedAll = JSON.parse(JSON.stringify(checkeds)) // this.checkedAll = JSON.parse(JSON.stringify(checkeds)) //
this.getProject(item) this.getProject(item, 1)
}).catch(err => { }) }).catch(err => { })
}, },
// //
@ -671,8 +668,8 @@ export default {
}, },
// //
projectChange (val, item) { projectChange (val, item) {
const { systemId } = item const { systemId, paperId } = item
const i = this.checkeds.findIndex(e => e.projectId == item.projectId && e.systemId == systemId) const i = this.checkeds.findIndex(e => (item.projectId && e.projectId == item.projectId && e.systemId == systemId) || (paperId && paperId == e.paperId))
// push // push
if (val) { if (val) {
this.checkeds.push(item) this.checkeds.push(item)
@ -685,12 +682,11 @@ export default {
}) })
this.checkAll = !this.projects.find(e => !e.check) // this.checkAll = !this.projects.find(e => !e.check) //
this.checkedAll = JSON.parse(JSON.stringify(this.checkeds)) // this.checkedAll = JSON.parse(JSON.stringify(this.checkeds)) //
console.log("🚀 ~ file: AddCurriculum.vue ~ line 728 ~ projectChange ~ checkedAll", this.checkeds, item)
}, },
// //
filterChecked () { filterChecked () {
const val = this.checkedKeyword const val = this.checkedKeyword
this.checkeds = this.checkedAll.filter(e => e.projectName.includes(val)) this.checkeds = this.checkedAll.filter(e => (e.projectName && e.projectName.includes(val)) || (e.paperName && e.paperName.includes(val)))
}, },
// //
delProject (i, e) { delProject (i, e) {
@ -701,9 +697,9 @@ export default {
this.checkeds.splice(i, 1) this.checkeds.splice(i, 1)
// checkdisabled // checkdisabled
if (e.systemId == this.curSystem) { if (e.systemId == this.curSystem) {
const { projectId } = e const { projectId, paperId } = e
this.projects.map(n => { this.projects.map(n => {
if (n.projectId == projectId) { if ((projectId && n.projectId == projectId) || (paperId && n.paperId == paperId)) {
n.check = false n.check = false
} }
}) })
@ -822,7 +818,8 @@ export default {
form.systemIdByPractice = this.practiceData.map(i => { form.systemIdByPractice = this.practiceData.map(i => {
let obj = { let obj = {
isShow: i.isShow, isShow: i.isShow,
projectId: i.projectId, projectId: i.projectId || '',
paperId: i.paperId || '',
sort: Number(i.sort), sort: Number(i.sort),
systemId: i.systemId systemId: i.systemId
}; };
@ -838,6 +835,7 @@ export default {
let obj = { let obj = {
isShow: i.isShow, isShow: i.isShow,
projectId: i.projectId, projectId: i.projectId,
paperId: i.paperId || '',
sort: Number(i.sort), sort: Number(i.sort),
systemId: i.systemId systemId: i.systemId
}; };
@ -850,6 +848,7 @@ export default {
let obj = { let obj = {
isShow: i.isShow, isShow: i.isShow,
projectId: i.projectId, projectId: i.projectId,
paperId: i.paperId || '',
sort: Number(i.sort), sort: Number(i.sort),
systemId: i.systemId systemId: i.systemId
}; };
@ -864,6 +863,7 @@ export default {
spinner: 'el-icon-loading', spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)' background: 'rgba(0, 0, 0, 0.7)'
}) })
debugger
if (form.cid) { if (form.cid) {
this.$post(this.api.modifyCourse, form).then((res) => { this.$post(this.api.modifyCourse, form).then((res) => {
this.$message.success("编辑成功"); this.$message.success("编辑成功");

@ -634,7 +634,7 @@ export default {
width: "100%", width: "100%",
autoplay: false, autoplay: false,
vid: fileId, vid: fileId,
playauth: res.data.playAuth, playauth: res.playAuth,
encryptType: 1 // encryptType: 1 //
}, player => { }, player => {
this.downloadFile(row.name, player._urls[0].Url) this.downloadFile(row.name, player._urls[0].Url)
@ -649,7 +649,7 @@ export default {
// //
if (row.fileId) { if (row.fileId) {
this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => { this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => {
this.playAuth = res.data.playAuth; this.playAuth = res.playAuth;
if (this.player) { if (this.player) {
this.player.replayByVidAndPlayAuth(row.fileId, this.playAuth); this.player.replayByVidAndPlayAuth(row.fileId, this.playAuth);
} else { } else {

@ -139,7 +139,7 @@
<el-table-column prop="productTypeName" label="产品分类" align="center"></el-table-column> <el-table-column prop="productTypeName" label="产品分类" align="center"></el-table-column>
<el-table-column label="起止日期" align="center"> <el-table-column label="起止日期" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.status === '已过期' ? '' : scope.row.startAndEndTime }} {{ scope.row.status === '已过期' ? '-' : scope.row.startAndEndTime }}
<el-tooltip v-if="scope.row.other" class="item" effect="dark" placement="top"> <el-tooltip v-if="scope.row.other" class="item" effect="dark" placement="top">
<div slot="content"> <div slot="content">
还有<span v-html="scope.row.other"></span><br>的订单还未生效 还有<span v-html="scope.row.other"></span><br>的订单还未生效
@ -173,14 +173,14 @@
<ul class="filter"> <ul class="filter">
<li> <li>
<label>订单类型</label> <label>订单类型</label>
<el-select v-model="form3.orderType" clearable placeholder="请选择订单类型" @change="getOrder"> <el-select v-model="form3.orderType" clearable placeholder="请选择订单类型" @change="initOrder">
<el-option v-for="(item, index) in orderTypeList" :key="index" :label="item.name" <el-option v-for="(item, index) in orderTypeList" :key="index" :label="item.name"
:value="item.value"></el-option> :value="item.value"></el-option>
</el-select> </el-select>
</li> </li>
<li> <li>
<label>订单状态</label> <label>订单状态</label>
<el-select v-model="form3.orderStatus" clearable placeholder="请选择订单状态" @change="getOrder"> <el-select v-model="form3.orderStatus" clearable placeholder="请选择订单状态" @change="initOrder">
<el-option v-for="(item, index) in orderStatusList" :key="index" :label="item.name" <el-option v-for="(item, index) in orderStatusList" :key="index" :label="item.name"
:value="item.id"></el-option> :value="item.id"></el-option>
</el-select> </el-select>
@ -200,7 +200,7 @@
<el-table-column prop="orderContent" label="订单内容" align="center"> <el-table-column prop="orderContent" label="订单内容" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-popover trigger="hover" placement="top" style='width: 500px' <el-popover trigger="hover" placement="top" style='width: 500px'
v-if='scope.row.orderContent.length > 14'> v-if='scope.row.orderContent && scope.row.orderContent.length > 14'>
<p> {{ scope.row.orderContent }}</p> <p> {{ scope.row.orderContent }}</p>
<div slot="reference" class="name-wrapper"> <div slot="reference" class="name-wrapper">
<el-tag size="medium" class='tags'>{{ scope.row.orderContent }}</el-tag> <el-tag size="medium" class='tags'>{{ scope.row.orderContent }}</el-tag>
@ -526,6 +526,7 @@ export default {
], ],
products: [], products: [],
productAll: [], productAll: [],
productAllOrigin: [],
pageProduct: this.$route.query.type === 'tab2' ? (+this.$route.query.page || 1) : 1, pageProduct: this.$route.query.type === 'tab2' ? (+this.$route.query.page || 1) : 1,
pageSizeProduct: 10, pageSizeProduct: 10,
totalProduct: 0, totalProduct: 0,
@ -565,7 +566,6 @@ export default {
pageSizeOrder: 10, pageSizeOrder: 10,
totalOrder: 0, totalOrder: 0,
orders: [], orders: [],
orderAll: [],
bmsKeyword: '', bmsKeyword: '',
bms: [], bms: [],
@ -625,7 +625,7 @@ export default {
this.pageOrder = 1 this.pageOrder = 1
clearTimeout(this.searchTimer) clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => { this.searchTimer = setTimeout(() => {
this.handlePageOrder() this.initOrder()
}, 500) }, 500)
}, },
bmsKeyword: function (val) { bmsKeyword: function (val) {
@ -703,7 +703,7 @@ export default {
}) })
// //
// if (list[0].startTime && list[0].endTime) { // if (list[0].startTime && list[0].endTime) {
if (list[0].startTime && now < new Date(list[0].startTime).getTime()) { if (list[0].startTime && now < new Date(list[0].startTime)) {
e.startTime = list[0].startTime e.startTime = list[0].startTime
e.endTime = connect ? list[list.length - 1].endTime : list[0].endTime e.endTime = connect ? list[list.length - 1].endTime : list[0].endTime
e.status = '未生效' e.status = '未生效'
@ -717,7 +717,7 @@ export default {
e.other += `<br>${j.startTime} ~ ${j.endTime}` e.other += `<br>${j.startTime} ~ ${j.endTime}`
}) })
} }
} else if (list[list.length - 1].endTime && now > new Date(list[list.length - 1].endTime).getTime()) { } else if (list[list.length - 1].endTime && now > new Date(list[list.length - 1].endTime)) {
e.status = '已过期' e.status = '已过期'
} else { } else {
// //
@ -730,7 +730,7 @@ export default {
for (const j in list) { for (const j in list) {
const i = +j const i = +j
const n = list[i] const n = list[i]
if (n.startTime && n.endTime && now >= new Date(n.startTime).getTime() && now <= new Date(n.endTime).getTime()) { if (n.startTime && n.endTime && now >= new Date(n.startTime) && now <= new Date(n.endTime)) {
// //
e.startTime = n.startTime e.startTime = n.startTime
e.endTime = n.endTime e.endTime = n.endTime
@ -745,7 +745,7 @@ export default {
}) })
} }
break break
} else if (i != 0 && list[i - 1].endTime && n.startTime && n.endTime && now > new Date(list[i - 1].endTime).getTime() && now < new Date(n.startTime).getTime()) { } else if (i != 0 && list[i - 1].endTime && n.startTime && n.endTime && now > new Date(list[i - 1].endTime) && now < new Date(n.startTime)) {
// //
e.startTime = n.startTime e.startTime = n.startTime
e.endTime = n.endTime e.endTime = n.endTime
@ -776,13 +776,14 @@ export default {
} }
}) })
this.productAll = data this.productAll = data
this.productAllOrigin = data
this.totalProduct = data.length this.totalProduct = data.length
this.handlePage() this.handlePage()
}).catch(res => { }) }).catch(res => { })
}, },
// //
getRemain (startTime, endTime) { getRemain (startTime, endTime) {
return parseInt(((new Date(endTime).getTime() - new Date(startTime).getTime()) / 86400000)) return parseInt(((new Date(endTime) - new Date(startTime)) / 86400000))
}, },
// //
handlePage () { handlePage () {
@ -793,6 +794,15 @@ export default {
this.handlePage() this.handlePage()
this.$router.push(`addcustomer?id=${this.customerId}&type=tab2&page=${val}`) this.$router.push(`addcustomer?id=${this.customerId}&type=tab2&page=${val}`)
}, },
//
filterForm2 () {
const list = this.productAllOrigin
const { productType, status, keyword } = this.form2
this.productAll = list.filter(e => (productType === '' || productType === e.productType) && (e.status === status || status === '全部') && (!e.goodsName || (e.goodsName && e.goodsName.includes(keyword))))
this.pageProduct = 1
this.totalProduct = this.productAll.length
this.handlePage()
},
// //
setCustomer () { setCustomer () {
this.initCustomer() this.initCustomer()
@ -903,12 +913,6 @@ export default {
this.productTypeList = res.classificationList this.productTypeList = res.classificationList
}).catch(err => { }) }).catch(err => { })
}, },
//
filterForm2 () {
const list = this.productAll
const { productType, status, keyword } = this.form2
this.products = list.filter(e => (productType === '' || productType === e.productType) && (e.status === status || status === '全部') && (!e.goodsName || (e.goodsName && e.goodsName.includes(keyword))))
},
// //
exportList () { exportList () {
let list = this.productAll let list = this.productAll
@ -936,36 +940,32 @@ export default {
// //
getOrder () { getOrder () {
const { orderStatus, orderType } = this.form3 const { orderStatus, orderType, keyword } = this.form3
this.$post(this.api.orderList, { this.$post(this.api.getCustomerOrderRecord, {
customerId: this.customerId,
cityId: '', cityId: '',
customerName: this.form.customerName, orderContent: keyword,
orderStatus, orderStatus,
orderType, orderType,
pageNo: 1, pageNo: this.pageOrder,
pageSize: 10000, pageSize: this.pageSizeOrder,
provinceId: '' provinceId: ''
}).then(({ orderPage }) => { }).then(({ orders }) => {
orderPage.orders.forEach(e => { orders.records.forEach(e => {
e.orderType = this.orderTypeFn(e.orderType) e.orderType = this.orderTypeFn(e.orderType)
e.orderStatus = this.orderStatusFn(e.orderStatus) e.orderStatus = this.orderStatusFn(e.orderStatus)
e.orderNature = this.orderNatureFn(e.orderNature)
}); });
this.orderAll = orderPage.orders this.orders = orders.records
this.totalOrder = orderPage.total this.totalOrder = orders.total
this.handlePageOrder()
}).catch(res => { }) }).catch(res => { })
}, },
// initOrder () {
handlePageOrder () { this.pageOrder = 1
const { keyword } = this.form3 this.getOrder()
const list = keyword ? this.orderAll.filter(e => e.orderNumber.includes(keyword) || e.orderContent.includes(keyword)) : this.orderAll
this.totalOrder = list.length
this.orders = list.slice((this.pageOrder - 1) * this.pageSizeOrder, this.pageOrder * this.pageSizeOrder)
}, },
handleCurrentChangeOrder (val) { handleCurrentChangeOrder (val) {
this.pageOrder = val this.pageOrder = val
this.handlePageOrder() this.getOrder()
this.$router.push(`addcustomer?id=${this.customerId}&type=tab3&page=${val}`) this.$router.push(`addcustomer?id=${this.customerId}&type=tab3&page=${val}`)
}, },
// //
@ -1014,7 +1014,7 @@ export default {
this.pageProduct = 1 this.pageProduct = 1
this.pageOrder = 1 this.pageOrder = 1
this.pageBm = 1 this.pageBm = 1
index === 'tab3' && this.handlePageOrder() index === 'tab3' && this.initOrder()
this.updateTime = this.form.customerId ? 1 : 0 this.updateTime = this.form.customerId ? 1 : 0
} }
}, },

@ -5,80 +5,81 @@
<div class="box"> <div class="box">
<h1>欢迎使用开发者平台</h1> <h1>欢迎使用开发者平台</h1>
<div class="form"> <div class="form">
<ul class="tab"> <ul class="tab">
<li v-for="(item, i) in tabList" :key="i" :class="{active: activeIndex == item.id}" @click="handleSelect(item.id)">{{item.label}}</li> <li v-for="(item, i) in tabList" :key="i" :class="{ active: activeIndex == item.id }"
</ul> @click="handleSelect(item.id)">{{ item.label }}</li>
<el-form v-show="activeIndex==='1'" :model="param" :rules="rules" ref="login" label-width="0px"> </ul>
<el-form-item prop="account"> <el-form v-show="activeIndex === '1'" :model="param" :rules="rules" ref="login" label-width="0px">
<el-input @blur="blur" v-model="param.account" placeholder="请输入账号"></el-input> <el-form-item prop="account">
</el-form-item> <el-input @blur="blur" v-model="param.account" placeholder="请输入账号"></el-input>
<el-form-item prop="password"> </el-form-item>
<el-input <el-form-item prop="password">
type="password" <el-input type="password" placeholder="请输入密码" v-model="param.password">
placeholder="请输入密码" </el-input>
v-model="param.password" </el-form-item>
> <el-form-item prop="code" v-if="showVerify">
</el-input> <el-input placeholder="请输入验证码" v-model="param.code" @keyup.enter.native="submitForm()">
</el-form-item> </el-input>
<el-form-item prop="code" v-if="showVerify"> <img @click="blur" :src="verificationIMG" class="verification" alt="">
<el-input </el-form-item>
placeholder="请输入验证码" <div class="login-btn">
v-model="param.code" <el-button type="primary" @click="submitForm()">马上登录</el-button>
@keyup.enter.native="submitForm()" </div>
> </el-form>
</el-input>
<img @click="blur" :src="verificationIMG" class="verification" alt=""> <el-form v-show="activeIndex === '2'" :model="phoneOrEmail" :rules="phoneOrEmailrules" ref="phoneOrEmail"
</el-form-item> label-width="0px">
<div class="login-btn"> <el-form-item prop="account">
<el-button type="primary" @click="submitForm()">马上登录</el-button> <el-input @blur="phoneBlur" v-model="phoneOrEmail.account" placeholder="请输入电话/邮箱"></el-input>
</div> </el-form-item>
</el-form> <el-form-item prop="password">
<el-input type="password" placeholder="请输入密码" v-model="phoneOrEmail.password">
<el-form v-show="activeIndex==='2'" :model="phoneOrEmail" :rules="phoneOrEmailrules" ref="phoneOrEmail" label-width="0px"> </el-input>
<el-form-item prop="account"> </el-form-item>
<el-input @blur="phoneBlur" v-model="phoneOrEmail.account" placeholder="请输入电话/邮箱"></el-input> <el-form-item prop="code" v-if="showPhoneVerify">
</el-form-item> <el-input placeholder="请输入验证码" v-model="phoneOrEmail.code" @keyup.enter.native="submitForm('phone')">
<el-form-item prop="password"> </el-input>
<el-input <img @click="phoneBlur" :src="PhoneVerificationIMG" class="verification" alt="">
type="password" </el-form-item>
placeholder="请输入密码" <div class="login-btn">
v-model="phoneOrEmail.password" <el-button type="primary" @click="submitForm('phone')">马上登录</el-button>
> </div>
</el-input> </el-form>
</el-form-item>
<el-form-item prop="code" v-if="showPhoneVerify">
<el-input
placeholder="请输入验证码"
v-model="phoneOrEmail.code"
@keyup.enter.native="submitForm('phone')"
>
</el-input>
<img @click="phoneBlur" :src="PhoneVerificationIMG" class="verification" alt="">
</el-form-item>
<div class="login-btn">
<el-button type="primary" @click="submitForm('phone')">马上登录</el-button>
</div>
</el-form>
</div> </div>
</div> </div>
</div> </div>
<el-dialog title="绑定手机号" :visible.sync="phoneVisible" :close-on-click-modal="false" width="576px"> <el-dialog title="绑定手机号" :visible.sync="phoneVisible" :close-on-click-modal="false" width="576px">
<p class="tips">依据国家政策法规需绑定手机号进行网络实名才可登录使用本平台</p> <p class="tips">依据国家政策法规需绑定手机号进行网络实名才可登录使用本平台</p>
<el-form ref="form" label-width="60px"> <el-form ref="form" label-width="60px">
<el-form-item label="手机号"> <el-form-item label="手机号">
<el-input placeholder="请输入手机号" v-model="phone" maxlength="11"></el-input> <el-input placeholder="请输入手机号" v-model="phone" maxlength="11"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="验证码"> <el-form-item label="验证码">
<div style="display:flex;"> <div style="display:flex;">
<el-input v-model="phoneCode" placeholder="请输入验证码" maxlength="6"></el-input> <el-input v-model="phoneCode" placeholder="请输入验证码" maxlength="6"></el-input>
<el-button style="margin-left:10px" @click="sendPhoneCode" :disabled="phoneDisabled">{{phoneBtnText}}</el-button> <el-button style="margin-left:10px" @click="sendPhoneCode" :disabled="phoneDisabled">{{ phoneBtnText
</div> }}</el-button>
</el-form-item> </div>
</el-form> </el-form-item>
<span slot="footer" class="dialog-footer"> </el-form>
<el-button @click="phoneVisible = false"> </el-button> <span slot="footer" class="dialog-footer">
<el-button type="primary" @click="phoneSubmit"> </el-button> <el-button @click="phoneVisible = false"> </el-button>
</span> <el-button type="primary" @click="phoneSubmit"> </el-button>
</span>
</el-dialog>
<el-dialog title="请选择您要登录的用户" :visible.sync="userVisible" :close-on-click-modal="false" custom-class="user-dia"
width="500px">
<p class="tips">该手机号已绑定以下用户信息</p>
<ul class="users">
<li :class="{ isEnable: !user.isEnable }" v-for="(user, i) in users" :key="i" @click="chooseUser(user)">
<span>{{ user.schoolName }}{{ user.userName }}{{ user.workNumber }}{{
user.isEnable
? ''
: '(已禁用)' }}</span>
<i class="el-icon-right"></i>
</li>
</ul>
</el-dialog> </el-dialog>
<v-footer class="footer" ref="footer"></v-footer> <v-footer class="footer" ref="footer"></v-footer>
</div> </div>
@ -87,217 +88,272 @@
<script> <script>
import vFooter from '../components/Footer' import vFooter from '../components/Footer'
import Setting from '@/setting' import Setting from '@/setting'
import addRoutes from '@/libs/route/addRoutes'
import CryptoJS from 'crypto-js'
import JSEncrypt from 'jsencrypt'
export default { export default {
data: function() { data: function () {
var regPhoneOrEmail = (rule, value, callback) => {// var regPhoneOrEmail = (rule, value, callback) => {//
let emailReg = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ let emailReg = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
let phoneReg = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/ let phoneReg = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/
if (value === '') { if (value === '') {
callback(new Error('请输入手机或邮箱!')); callback(new Error('请输入手机或邮箱!'));
} else if (!emailReg.test(value)&&!phoneReg.test(value)) { } else if (!emailReg.test(value) && !phoneReg.test(value)) {
callback(new Error('输入的手机/邮箱格式不正确!')); callback(new Error('输入的手机/邮箱格式不正确!'));
} else { } else {
callback(); callback();
} }
}; };
return { return {
tabList: [ tabList: [
{ {
id: '1', id: '1',
label: '账号登录' label: '账号登录'
}, { }, {
id: '2', id: '2',
label: '手机号/邮箱登录' label: '手机号/邮箱登录'
} }
], ],
activeIndex:"1", activeIndex: "1",
showVerify: true,// - showVerify: true,// -
verificationIMG:'',// verificationIMG: '',//
// //
param: { param: {
account: '', account: '',
password: '', password: '',
code:'', code: '',
platform:3, platform: 3,
random:'', random: '',
distinguish:1, distinguish: 1,
type: 2 type: 2
}, },
rules: { rules: {
account: [{ required: true, message: '请输入账号', trigger: 'blur' }], account: [{ required: true, message: '请输入账号', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }], password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
code: [{ required: true, message: '请输入验证码', trigger: 'blur' }], code: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
}, },
// + // +
showPhoneVerify:true,// - showPhoneVerify: true,// -
PhoneVerificationIMG:'',// PhoneVerificationIMG: '',//
phoneOrEmail: { phoneOrEmail: {
account: '', account: '',
password: '', password: '',
code:'', code: '',
platform:3, platform: 3,
random:'', random: '',
distinguish:2, distinguish: 2,
type: 2 type: 2
}, },
phoneOrEmailrules:{ phoneOrEmailrules: {
account: [{ validator: regPhoneOrEmail, trigger: 'blur' }], account: [{ validator: regPhoneOrEmail, trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }], password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
code: [{ required: true, message: '请输入验证码', trigger: 'blur' }], code: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
}, },
phoneVisible:false, phoneVisible: false,
phone:'', phone: '',
phoneCode:'', phoneCode: '',
phoneDisabled:false, phoneDisabled: false,
phoneBtnText: '发送验证码', phoneBtnText: '发送验证码',
phoneTimer:'', phoneTimer: '',
phoneOpener:'' phoneOpener: '',
}; userVisible: false,
users: [],
};
},
components: {
vFooter
},
watch: {
verificationIMG: function (val) {// --
if (val) {
this.showVerify = true
} else {
this.showVerify = false
}
}, },
components: { PhoneVerificationIMG: function (val) {// --
vFooter if (val) {
this.showPhoneVerify = true
} else {
this.showPhoneVerify = false
}
}, },
watch:{ },
verificationIMG:function(val){// -- created () {
if(val){ if (this.param.account) {
this.showVerify = true this.showVerify = true
}else{ }
this.showVerify = false this.blur()
},
methods: {
submitForm (val) {
let ref = val === 'phone' ? 'phoneOrEmail' : 'login'
let param = val === 'phone' ? this.phoneOrEmail : this.param
this.$refs[ref].validate(valid => {
if (valid) {
this.$post(this.api.logins, param).then(({ status, data, message }) => {
localStorage.removeItem('examPath')
localStorage.removeItem('reviewPath')
this.getOss()
if (status == 200) {
const accounts = data.userAccounts
//
if (accounts instanceof Array) {
this.users = accounts
this.userVisible = true
} else {
sessionStorage.setItem('token', data.token)
this.setLogin()
}
} else {
param.code = ''
this.$message.error(message)
} }
}, }).catch(err => {
PhoneVerificationIMG:function(val){// -- if (err.status === 30001) {
if(val){ this.phoneVisible = true
this.showPhoneVerify = true } else if (err.status == 10004 || err.status == 10005) {
}else{ param.code = ''
this.showPhoneVerify = false this.blur()
} }
}, });
} else {
this.$message.error('请输入账号/密码/验证码');
return false;
}
});
},
// oss
async getOss () {
const A = (key, encryptedData) => {
const keyHex = CryptoJS.enc.Base64.parse(key)
const decrypted = CryptoJS.AES.decrypt(encryptedData, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
})
return decrypted.toString(CryptoJS.enc.Utf8)
}
const R = (encryptedKey, privateKey) => {
const decrypt = new JSEncrypt()
decrypt.setPrivateKey(privateKey)
const decryptedKey = decrypt.decrypt(encryptedKey)
return decryptedKey
}
const res = await this.$get(this.api.encrypt)
const RE = A(R(res.encryptedKey, res.privateKey), res.encryptedData).split('/')
localStorage.setItem('osc', JSON.stringify(RE))
}, },
created(){ //
if(this.param.account){ chooseUser (user) {
this.showVerify = true user.isEnable && this.$post(`${this.api.getToken}?id=${user.id}`).then(({ data }) => {
sessionStorage.setItem('token', data.token)
this.token = data.token
this.setLogin()
}).catch(res => { })
},
//
async setLogin () {
try {
const res = await this.$get(`${this.api.getUserRolesPermissionMenu}?platformId=${Setting.platformId}`)
const list = res.permissionMenu
addRoutes(res.permissionMenu[0].children)
this.$store.commit('setDataPer', res.dataPermissionList)
this.$message.success('登录成功!')
this.$router.push({
path: list[0].children[0].path
});
localStorage.setItem('ms_username', this.param.username);
} catch (e) {
if (e.status === 500) {
sessionStorage.clear()
} }
this.blur() }
}, },
methods: { blur () {
submitForm(val) { this.param.random = Math.floor(Math.random() * 999999999)
let ref = val==='phone'?'phoneOrEmail':'login' this.verificationIMG = this.api.verification + '?random=' + `${this.param.random}`
let param = val==='phone'?this.phoneOrEmail:this.param },
this.$refs[ref].validate(valid => { phoneBlur () {
if (valid) { this.phoneOrEmail.random = Math.floor(Math.random() * 999999999)
this.$post(this.api.logins,param).then(res => { this.PhoneVerificationIMG = this.api.verification + '?random=' + `${this.phoneOrEmail.random}`
const { message } = res
sessionStorage.setItem('token',res.data.token)
this.$get(`${this.api.getUserRolesPermissionMenu}?platformId=${Setting.platformId}`).then(res => {
const list = res.permissionMenu
this.$store.commit('setDataPer', res.dataPermissionList)
this.$message.success(message);
this.$router.push({
path: list[0].children[0].path
});
localStorage.setItem('ms_username', this.param.username);
}).catch(err => {
if (err.status === 500) {
sessionStorage.clear()
}
})
}).catch(err => {
if(err.status===30001){
this.phoneVisible = true
}else if(err.status == 10004){
this.blur()
}
});
} else {
this.$message.error('请输入账号/密码/验证码');
return false;
}
});
},
blur(){
this.param.random = Math.floor(Math.random()*999999999)
this.verificationIMG = this.api.verification+'?random='+`${this.param.random}`
},
phoneBlur(){
this.phoneOrEmail.random = Math.floor(Math.random()*999999999)
this.PhoneVerificationIMG = this.api.verification+'?random='+`${this.phoneOrEmail.random}`
},
handleSelect(val){
this.activeIndex = val
this.param.account = "";
this.param.password = "";
this.param.code = "";
this.phoneOrEmail.account = "";
this.phoneOrEmail.password = "";
this.phoneOrEmail.code = "";
this.$refs.phoneOrEmail.clearValidate()
// this.blur()
this.phoneBlur()
},
sendPhoneCode(){
if(!this.phone) return this.$message.warning('请输入手机号')
if(!/^1[3456789]\d{9}$/.test(this.phone)) return this.$message.warning('请输入正确的手机号')
let data = {
phone: this.phone,
types: 2
}
this.$post(this.api.sendPhoneOrEmailCode,data).then(res => {
this.phoneCountdown()//
if(res.message.opener){
this.phoneOpener = res.message.opener
}else{
this.$message(res.message)
}
}).catch(res => {})
},
phoneSubmit(){
if(!this.phone) return this.$message.warning('请输入手机号')
if(!/^1[3456789]\d{9}$/.test(this.phone)) return this.$message.warning('请输入正确的手机号')
if(!this.phoneCode) return this.$message.warning('请输入验证码')
let data = {
phone: this.phone,
types: 2,
code: this.phoneCode,
opener: this.phoneOpener,
platform: 3,
account: this.param.account
}
this.$post(this.api.bindPhoneOrEmail,data).then(res => {
sessionStorage.setItem('token',res.token)
this.$router.push({
path:'/customer'
});
localStorage.setItem('ms_username', this.param.username);
this.$message.success('绑定成功')
// this.form.phone = this.phone
// this.phoneVisible = false
}).catch(res => {})
},
phoneCountdown(){
let count = 60
if(!this.phoneTimer){
this.phoneDisabled = true
this.phoneTimer = setInterval(() => {
if(count > 0){
count--
this.phoneBtnText = `${count}秒后重试`
}else{
this.phoneDisabled = false
clearInterval(this.phoneTimer)
this.phoneTimer = null
this.phoneBtnText = `发送验证码`
}
},1000)
}
},
}, },
handleSelect (val) {
this.activeIndex = val
this.param.account = "";
this.param.password = "";
this.param.code = "";
this.phoneOrEmail.account = "";
this.phoneOrEmail.password = "";
this.phoneOrEmail.code = "";
this.$refs.phoneOrEmail.clearValidate()
// this.blur()
this.phoneBlur()
},
sendPhoneCode () {
if (!this.phone) return this.$message.warning('请输入手机号')
if (!/^1[3456789]\d{9}$/.test(this.phone)) return this.$message.warning('请输入正确的手机号')
let data = {
phone: this.phone,
types: 2
}
this.$post(this.api.sendPhoneOrEmailCode, data).then(res => {
this.phoneCountdown()//
if (res.message.opener) {
this.phoneOpener = res.message.opener
} else {
this.$message(res.message)
}
}).catch(res => { })
},
phoneSubmit () {
if (!this.phone) return this.$message.warning('请输入手机号')
if (!/^1[3456789]\d{9}$/.test(this.phone)) return this.$message.warning('请输入正确的手机号')
if (!this.phoneCode) return this.$message.warning('请输入验证码')
let data = {
phone: this.phone,
types: 2,
code: this.phoneCode,
opener: this.phoneOpener,
platform: 3,
account: this.param.account
}
this.$post(this.api.bindPhoneOrEmail, data).then(res => {
sessionStorage.setItem('token', res.token)
this.$router.push({
path: '/customer'
});
localStorage.setItem('ms_username', this.param.username);
this.$message.success('绑定成功')
// this.form.phone = this.phone
// this.phoneVisible = false
}).catch(res => { })
},
phoneCountdown () {
let count = 60
if (!this.phoneTimer) {
this.phoneDisabled = true
this.phoneTimer = setInterval(() => {
if (count > 0) {
count--
this.phoneBtnText = `${count}秒后重试`
} else {
this.phoneDisabled = false
clearInterval(this.phoneTimer)
this.phoneTimer = null
this.phoneBtnText = `发送验证码`
}
}, 1000)
}
},
},
}; };
</script> </script>
@ -305,24 +361,28 @@ export default {
.wrap { .wrap {
min-height: 100%; min-height: 100%;
} }
.logo { .logo {
z-index: 2; z-index: 2;
position: absolute; position: absolute;
top: 50px; top: 50px;
left: 50px; left: 50px;
} }
.login { .login {
position: relative; position: relative;
height: 100%; height: 100%;
background-image: url(../assets/img/devLogin.jpg); background-image: url(../assets/img/devLogin.jpg);
background-size: 100%; background-size: 100%;
} }
.box { .box {
width: 448px; width: 448px;
position: absolute; position: absolute;
right: 20%; right: 20%;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
h1 { h1 {
margin-bottom: 20px; margin-bottom: 20px;
font-size: 34px; font-size: 34px;
@ -330,76 +390,129 @@ export default {
text-align: center; text-align: center;
} }
} }
/deep/ .form { /deep/ .form {
padding: 20px 60px 0; padding: 20px 60px 0;
background-color: rgba(255, 255, 255, .3); background-color: rgba(255, 255, 255, .3);
border-radius: 4px; border-radius: 4px;
box-sizing: border-box; box-sizing: border-box;
border: 4px solid rgba(255, 255, 255, .2); border: 4px solid rgba(255, 255, 255, .2);
.el-input__inner {
height: 50px; .el-input__inner {
line-height: 50px; height: 50px;
border: 1px solid rgba(220, 220, 220, 1); line-height: 50px;
border-radius: 2px; border: 1px solid rgba(220, 220, 220, 1);
} border-radius: 2px;
.el-form-item { }
margin-bottom: 25px;
} .el-form-item {
.verification{ margin-bottom: 25px;
position: absolute; }
top: 1px;
right: 1px; .verification {
width: 160px; position: absolute;
height: 47px; top: 1px;
cursor: pointer; right: 1px;
} width: 160px;
height: 47px;
cursor: pointer;
}
} }
.tab{
display: flex; .tab {
justify-content: center; display: flex;
align-items: center; justify-content: center;
margin-bottom: 24px; align-items: center;
li{ margin-bottom: 24px;
padding: 18px 5px;
margin: 0 20px; li {
font-size: 16px; padding: 18px 5px;
font-weight: 600; margin: 0 20px;
color: #fff; font-size: 16px;
cursor: pointer; font-weight: 600;
border-bottom: 2px solid transparent; color: #fff;
&:last-child{ cursor: pointer;
margin-right: 0; border-bottom: 2px solid transparent;
}
&.active{ &:last-child {
color: #fff; margin-right: 0;
border-bottom-color: #ccc;
}
} }
&.active {
color: #fff;
border-bottom-color: #ccc;
}
}
} }
.title{
font-size: 16px; .title {
text-align: center; font-size: 16px;
font-weight: bold; text-align: center;
font-weight: bold;
} }
.login-btn { .login-btn {
text-align: center; text-align: center;
} }
.login-btn button { .login-btn button {
width: 100%; width: 100%;
height: 48px; height: 48px;
margin-bottom: 50px; margin-bottom: 50px;
font-weight: bold; font-weight: bold;
background: #1dabff; background: #1dabff;
border-radius: 4px; border-radius: 4px;
border: 0; border: 0;
} }
.forget{
margin-bottom: 28px; .forget {
text-align: right; margin-bottom: 28px;
color: #999; text-align: right;
font-weight:bold; color: #999;
&:hover{ font-weight: bold;
color: #0092FF;
&:hover {
color: #0092FF;
}
}
/deep/.user-dia {
.tips {
margin-bottom: 20px;
text-align: center;
color: #666;
}
.users {
li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 15px;
margin-bottom: 10px;
line-height: 40px;
font-size: 14px;
background-color: #ebeef5;
cursor: pointer;
&.isEnable {
color: #c0c4cc;
background-color: #f5f7fa;
cursor: not-allowed;
}
&:last-child {
margin-bottom: 0;
}
&:hover {
background-color: #d3e0ff;
}
i {
font-size: 16px;
}
} }
}
} }
</style> </style>

@ -9,8 +9,8 @@
<div class="p-title">大赛发布类型</div> <div class="p-title">大赛发布类型</div>
<el-form label-width="100px" label-suffix=":" size="small" :disabled="!editing && id != ''"> <el-form label-width="100px" label-suffix=":" size="small" :disabled="!editing && id != ''">
<el-form-item label="请选择类型"> <el-form-item label="请选择类型">
<el-radio v-model="releaseType" :label="0">仅发布信息</el-radio> <el-radio v-for="(item, i) in releaseTypes" :key="i" v-model="releaseType" :label="item.id">{{ item.name
<el-radio v-model="releaseType" :label="1">设置完整比赛</el-radio> }}</el-radio>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-button v-if="!editing && id" class="edit" type="primary" @click="editing = 1" <el-button v-if="!editing && id" class="edit" type="primary" @click="editing = 1"
@ -83,6 +83,20 @@ export default {
updateTime: 0, updateTime: 0,
setupId: '', setupId: '',
releaseType: 0, releaseType: 0,
releaseTypes: [
{
id: 0,
name: '仅发布信息'
},
{
id: 1,
name: '设置完整比赛'
},
// {
// id: 2,
// name: ''
// },
],
editing: this.$route.query.id ? 0 : 1, editing: this.$route.query.id ? 0 : 1,
showBtns: true, showBtns: true,
loadIns: null loadIns: null
@ -140,9 +154,10 @@ export default {
next (next, setupId, competitionId) { next (next, setupId, competitionId) {
if (!next) { if (!next) {
if (this.step === 3 && this.$refs['step' + this.step].form[0].contentId) { if (this.step === 3 && this.$refs['step' + this.step].form[0].contentId) {
// && // &&
this.editing = 0 this.editing = 0
this.step = 1 this.step = 1
this.$parent.initTabs && this.$parent.initTabs()
} else { } else {
// //
this.$router.push(`/match`) this.$router.push(`/match`)

@ -1,146 +1,192 @@
<template> <template>
<div> <div>
<el-card shadow="hover" <el-card shadow="hover" class="m-b-20">
class="m-b-20">
<div> <div>
<p class="m-b-20">比赛名称</p> <p class="m-b-20">比赛名称</p>
{{ form.stageName }} {{ form.stageName }}
</div> </div>
</el-card> </el-card>
<el-card shadow="hover" <el-card shadow="hover" class="m-b-20">
class="m-b-20">
<div> <div>
<p class="m-b-20">比赛时间</p> <p class="m-b-20">比赛时间</p>
<div class="date-inputs"> <div class="date-inputs">
起止时间 起止时间
<div style="display: inline-flex;align-items: center;"> <div style="display: inline-flex;align-items: center;">
<el-date-picker v-model="form.time" <el-date-picker v-model="form.time" type="datetimerange" range-separator="~" start-placeholder="开始日期"
type="datetimerange" end-placeholder="结束日期" format="yyyy-MM-dd HH:mm:ss" value-format="yyyy-MM-dd HH:mm:ss"
range-separator="~" @change="timeChange">
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-dd HH:mm:ss"
@change="timeChange">
</el-date-picker> </el-date-picker>
<el-alert style="width: auto;padding: 4px 16px;margin-left: 10px;" <el-alert style="width: auto;padding: 4px 16px;margin-left: 10px;"
:title="'(请设置在 ' + step1.playStartTime + ' ~ ' + step1.playEndTime + '间)'" :title="'(请设置在 ' + step1.playStartTime + ' ~ ' + step1.playEndTime + '间)'" type="error" :closable="false"
type="error" effect="dark">
:closable="false"
effect="dark">
</el-alert> </el-alert>
</div> </div>
</div> </div>
</div> </div>
</el-card> </el-card>
<el-card shadow="hover"
class="mgr20 m-b-20"> <!-- 理论系统 -->
<div> <template v-if="isTheory">
<p class="m-b-20">课程</p> <!-- 理论系统选择试卷库非理论则选择系统 -->
<div class="inline-input"> <el-card shadow="hover" class="mgr20 m-b-20">
<el-cascader ref="cur" <div>
v-model="mallIds" <p class="m-b-20">试卷库</p>
:options="curs" <div class="inline-input">
:props="{ checkStrictly: true, value: 'id' }" <el-select v-model="libraryId" placeholder="请选择试卷库" @change="getProject">
popper-class="course-cas" <el-option v-for="(item, i) in paperLibraries" :key="i" :label="item.libraryName" :value="item.libraryId">
@expand-change="curChange" </el-option>
@change="curChange"></el-cascader> </el-select>
</div>
</div> </div>
</div> </el-card>
</el-card>
<el-card shadow="hover" <el-card shadow="hover" class="m-b-20">
class="m-b-20"> <div class="flex-between m-b-20">
<div class="flex-between m-b-20"> <span>理论试卷</span>
<span>实训项目</span> <div style="display: inline-flex;">
<div style="display: inline-flex;"> <div>
<div> <el-input placeholder="请输入试卷名称" prefix-icon="el-icon-search" v-model.trim="keyword" clearable></el-input>
<el-input placeholder="请输入项目名称" </div>
prefix-icon="el-icon-search"
v-model.trim="keyword"
clearable></el-input>
</div> </div>
<el-button style="margin-left: 5px"
type="primary"
round
@click="toProject">自定义实验项目</el-button>
</div> </div>
</div> <p v-if="form.paperName" style="margin-bottom: 20px">
<!-- 实训项目表格 --> 已选试卷{{ form.paperName }}
<el-table :data="projects" <el-button type="primary" size="mini" @click="previewPaper(form)">预览</el-button>
class="table" </p>
stripe <el-table :data="projects" class="table" stripe header-align="center">
header-align="center"> <el-table-column width="60" label="选择" align="center">
<el-table-column width="60" <template slot-scope="scope">
label="选择" <el-radio v-model="form.paperId" :label="scope.row.paperId" @change="paperChange">&nbsp;</el-radio>
align="center"> </template>
<template slot-scope="scope"> </el-table-column>
<el-radio v-model="form.projectId" <el-table-column type="index" width="60" label="序号" align="center"></el-table-column>
:label="scope.row.projectId">&nbsp;</el-radio> <el-table-column prop="name" label="试卷名称" min-width="140" align="center"></el-table-column>
</template> <el-table-column prop="questionCount" label="试题总数" align="center" min-width="70"></el-table-column>
</el-table-column> <el-table-column prop="score" label="总分" align="center" min-width="70"></el-table-column>
<el-table-column prop="projectName" <el-table-column prop="difficult" label="试卷难度" align="center" min-width="70" sortable="custom">
label="项目名称" <template slot-scope="scope">{{ difficults.find(e => e.id === scope.row.difficult) ? difficults.find(e =>
align="center"></el-table-column> e.id === scope.row.difficult).name : '' }}</template>
<el-table-column prop="auth" </el-table-column>
label="项目权限" <el-table-column prop="suggestTime" label="建议用时" align="center" min-width="70">
align="center"> <template slot-scope="scope">{{ scope.row.suggestTime }}min</template>
<template slot-scope="scope"> </el-table-column>
{{ permissionsKeys[scope.row.permissions] }} <el-table-column prop="classificationPath" label="试卷分类" align="center" min-width="70"
</template> show-overflow-tooltip></el-table-column>
</el-table-column> <el-table-column label="建议用途" align="center" min-width="70">
<el-table-column prop="founder" <template slot-scope="scope">{{ paperTypes.find(e => e.id === scope.row.paperType) ? paperTypes.find(e =>
label="创建人" e.id === scope.row.paperType).name : '' }}</template>
align="center"> </el-table-column>
<template slot-scope="scope"> <el-table-column prop="updateTime" label="最近编辑时间" align="center" width="170"></el-table-column>
{{ scope.row.founder ? '老师创建' : '系统内置' }} <el-table-column prop="createUser" label="最近编辑人" align="center" width="110"></el-table-column>
</template> <el-table-column label="操作" align="center" width="80">
</el-table-column> <template slot-scope="scope">
<el-table-column prop="createTime" <el-button type="text" @click="previewPaper(scope.row)">预览</el-button>
label="创建时间" </template>
align="center"></el-table-column> </el-table-column>
<!-- <el-table-column label="操作" align="center"> </el-table>
<div class="pagination">
<el-pagination background :page-size="pageSize" @current-change="handleCurrentChange"
layout="total,prev, pager, next" :total="total"></el-pagination>
</div>
</el-card>
</template>
<template v-else>
<el-card shadow="hover" class="mgr20 m-b-20">
<div>
<p class="m-b-20">课程</p>
<div class="inline-input">
<el-cascader ref="cur" v-model="mallIds" :options="curs" :props="{ checkStrictly: true, value: 'id' }"
popper-class="course-cas" @expand-change="curChange" @change="curChange"></el-cascader>
</div>
</div>
</el-card>
<el-card shadow="hover" class="m-b-20">
<div class="flex-between m-b-20">
<span>实训项目</span>
<div style="display: inline-flex;">
<div>
<el-input placeholder="请输入项目名称" prefix-icon="el-icon-search" v-model.trim="keyword" clearable></el-input>
</div>
<el-button style="margin-left: 5px" type="primary" round @click="toProject">自定义实验项目</el-button>
</div>
</div>
<!-- 实训项目表格 -->
<el-table :data="projects" class="table" stripe header-align="center">
<el-table-column width="60" label="选择" align="center">
<template slot-scope="scope">
<el-radio v-model="form.projectId" :label="scope.row.projectId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
<el-table-column prop="auth" label="项目权限" align="center">
<template slot-scope="scope">
{{ permissionsKeys[scope.row.permissions] }}
</template>
</el-table-column>
<el-table-column prop="founder" label="创建人" align="center">
<template slot-scope="scope">
{{ scope.row.founder ? '老师创建' : '系统内置' }}
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" align="center"></el-table-column>
<!-- <el-table-column label="操作" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" @click="showProject(scope.row)">查看</el-button> <el-button type="text" @click="showProject(scope.row)">查看</el-button>
</template> </template>
</el-table-column> --> </el-table-column> -->
</el-table> </el-table>
<div class="pagination"> <div class="pagination">
<el-pagination background <el-pagination background :page-size="pageSize" @current-change="handleCurrentChange"
:page-size="pageSize" layout="total,prev, pager, next" :total="total"></el-pagination>
@current-change="handleCurrentChange" </div>
layout="total,prev, pager, next" </el-card>
:total="total"></el-pagination> </template>
</div>
</el-card>
<div style="text-align: center"> <div style="text-align: center">
<el-button @click="back">返回</el-button> <el-button @click="back">返回</el-button>
<el-button type="primary" <el-button type="primary" @click="save">保存</el-button>
@click="save">保存</el-button>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import Setting from '@/setting'
import util from "@/libs/util"; import util from "@/libs/util";
import { Loading } from 'element-ui' import { Loading } from 'element-ui'
import TestPaperConst from '@/const/testPaper'
export default { export default {
props: ['form', 'step1'], props: ['form', 'step1'],
data () { data () {
return { return {
difficults: TestPaperConst.difficults,
paperTypes: TestPaperConst.paperTypes,
loadIns: null, loadIns: null,
mallIds: [], mallIds: [],
curs: [], curs: [],
paperLibraries: [],
testPapers: [],
keyword: '', keyword: '',
projects: [], projects: [],
page: 1, page: 1,
pageSize: 5, pageSize: 5,
total: 0, total: 0,
libraryId: '',
sysId: '', sysId: '',
paperId: '',
paperName: '',
permissionsKeys: ['练习', '考核', '竞赛'], permissionsKeys: ['练习', '考核', '竞赛'],
timeInvalid: false timeInvalid: false,
}; };
}, },
computed: {
//
isTheory () {
return this.form.method === 1
},
},
watch: { watch: {
// , // ,
form: { form: {
@ -157,7 +203,7 @@ export default {
} }
}, },
mounted () { mounted () {
this.getCourse() this.isTheory ? this.getLibrary() : this.getCourse()
}, },
methods: { methods: {
// //
@ -186,7 +232,7 @@ export default {
records.map(e => { records.map(e => {
e.id = +e.mallId e.id = +e.mallId
e.label = e.productName e.label = e.productName
e.children = serviceList.records.filter(n => e.systemId.split(',').includes(n.systemId)) // e.children = serviceList.records.filter(n => e.systemId && e.systemId.split(',').includes(n.systemId)) //
}) })
this.curs = records this.curs = records
@ -216,31 +262,65 @@ export default {
this.loadIns = Loading.service() this.loadIns = Loading.service()
this.getProject() this.getProject()
}, },
//
async getLibrary () {
try {
const res = await this.$post(this.api.libraryList, {
pageNum: 1,
pageSize: 10000,
type: 1,
isDisable: 0,
})
const { records } = res.pageList
if (records.length) {
this.paperLibraries = records
this.libraryId = records[0].libraryId
this.loadIns = Loading.service()
this.getProject()
}
} finally { }
},
// // /
getProject () { async getProject () {
this.$post(this.api.getProjectAssessmentByCompetition, { try {
pageNum: this.page, //
pageSize: this.pageSize, if (this.isTheory) {
cid: this.form.cid, const res = await this.$post(this.api.examPaperList, {
projectName: this.keyword, pageNum: this.page,
systemId: this.sysId, pageSize: this.pageSize,
permissions: 2 type: 1,
}).then(({ data }) => { keyWord: this.keyword,
this.projects = data.records libraryId: this.libraryId,
this.total = data.total isDisable: 0,
this.loadIns.close() status: 1
}).catch(err => { })
this.projects = res.pageList.records
this.total = res.pageList.total
} else {
//
const { data } = await this.$post(this.api.getProjectAssessmentByCompetition, {
pageNum: this.page,
pageSize: this.pageSize,
cid: this.form.cid,
projectName: this.keyword,
systemId: this.sysId,
permissions: 2,
})
this.projects = data.records
this.total = data.total
}
} finally {
this.loadIns.close() this.loadIns.close()
}); }
}, },
initData () { initData () {
this.page = 1; this.page = 1
this.getProject(); this.getProject()
}, },
handleCurrentChange (val) { handleCurrentChange (val) {
this.page = val; this.page = val
this.getProject(); this.getProject()
}, },
// //
toProject () { toProject () {
@ -277,22 +357,58 @@ export default {
} }
} }
}, },
//
previewPaper (row) {
this.$parent.previewPaper(row)
},
//
paperChange (id) {
const item = this.projects.find(e => e.paperId === id)
if (item) this.form.paperName = item.name
},
// //
save () { save () {
const { form } = this const { form } = this
if (!form.time.length) return util.warningMsg('请选择比赛时间') if (!form.time.length) return util.warningMsg('请选择比赛时间')
const { playStartTime, playEndTime } = this.step1 const { playStartTime, playEndTime } = this.step1
if (new Date(form.time[0]) < new Date(playStartTime) || new Date(form.time[1]) > new Date(playEndTime)) return util.warningMsg('设置的阶段比赛时间必须要在第一步设置的竞赛时间范围内,请重新设置。') if (new Date(form.time[0]) < new Date(playStartTime) || new Date(form.time[1]) > new Date(playEndTime)) return util.warningMsg('设置的阶段比赛时间必须要在第一步设置的竞赛时间范围内,请重新设置。')
if (!form.cid) return util.warningMsg('请选择课程') //
if (!form.projectId) return util.warningMsg('请选择项目') if (this.isTheory) {
const { systemId, systemName, projectName } = this.projects.find(e => e.projectId == form.projectId) if (!this.libraryId) return util.warningMsg('请选择试卷库')
if (systemId) form.systemId = systemId if (!form.paperId) return util.warningMsg('请选择试卷')
if (projectName) form.projectName = projectName
if (systemName) form.systemName = systemName form.libraryId = this.libraryId
const curPaper = this.projects.find(e => e.paperId === form.paperId)
if (curPaper) form.paperName = curPaper.name
} else {
if (!form.cid) return util.warningMsg('请选择课程')
if (!form.projectId) return util.warningMsg('请选择项目')
const { systemId, systemName, projectName } = this.projects.find(e => e.projectId == form.projectId)
if (systemId) form.systemId = systemId
if (projectName) form.projectName = projectName
if (systemName) form.systemName = systemName
}
form.startTime = form.time[0] form.startTime = form.time[0]
form.endTime = form.time[1] form.endTime = form.time[1]
this.handlePaper()
this.$emit('hideSet', this.form) this.$emit('hideSet', this.form)
}, },
//
async handlePaper () {
const { form } = this
// id
if (form.paperName !== form.originPaperName) {
const res = await this.$post(this.api.copyExamPaper, {
associatedID: form.stageId,
paperId: form.paperId,
typeId: 1
})
if (res.examPaper) {
form.paperId = res.examPaper.paperId
}
}
},
// //
back () { back () {
this.$emit('update:form', this.$parent.curOriginForm) this.$emit('update:form', this.$parent.curOriginForm)
@ -302,5 +418,4 @@ export default {
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss"></style>
</style>

@ -37,41 +37,44 @@
<el-input placeholder="请输入竞赛名称" v-model="form.name" clearable></el-input> <el-input placeholder="请输入竞赛名称" v-model="form.name" clearable></el-input>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item class="req" label="主办方">
<div class="inline-input"> <template v-if="!isPractice">
<div class="input-wrap" v-for="(item, index) in sponsorList" :key="index"> <el-form-item class="req" label="主办方">
<el-input placeholder="主办方名称" v-model="sponsorList[index]"></el-input> <div class="inline-input">
<i v-if="sponsorList.length > 1" class="remove" @click="delSponsor(index)"></i> <div class="input-wrap" v-for="(item, index) in sponsorList" :key="index">
<button v-if="index == 0" class="add-btn" type="button" :disabled="!editing && form.id !== ''" <el-input placeholder="主办方名称" v-model="sponsorList[index]"></el-input>
@click="addSponsor"> <i v-if="sponsorList.length > 1" class="remove" @click="delSponsor(index)"></i>
<i class="el-icon-plus"></i> <button v-if="index == 0" class="add-btn" type="button" :disabled="!editing && form.id !== ''"
<span>添加</span> @click="addSponsor">
</button> <i class="el-icon-plus"></i>
<span>添加</span>
</button>
</div>
</div> </div>
</div> </el-form-item>
</el-form-item> <el-form-item label="承办方(选填)">
<el-form-item label="承办方(选填)"> <div class="inline-input">
<div class="inline-input"> <div class="input-wrap" v-for="(item, index) in undertakerList" :key="index">
<div class="input-wrap" v-for="(item, index) in undertakerList" :key="index"> <el-input placeholder="承办方名称" v-model="undertakerList[index]"></el-input>
<el-input placeholder="承办方名称" v-model="undertakerList[index]"></el-input> <i v-if="undertakerList.length > 1" class="remove" @click="delOrganizer(index)"></i>
<i v-if="undertakerList.length > 1" class="remove" @click="delOrganizer(index)"></i> <button v-if="index == 0" class="add-btn" type="button" :disabled="!editing && form.id !== ''"
<button v-if="index == 0" class="add-btn" type="button" :disabled="!editing && form.id !== ''" @click="addOrganizer">
@click="addOrganizer"> <i class="el-icon-plus"></i>
<i class="el-icon-plus"></i> <span>添加</span>
<span>添加</span> </button>
</button> </div>
</div> </div>
</div> <button v-if="!undertakerList.length" class="add-btn" type="button" @click="addOrganizer">
<button v-if="!undertakerList.length" class="add-btn" type="button" @click="addOrganizer"> <i class="el-icon-plus"></i>
<i class="el-icon-plus"></i> <span>添加</span>
<span>添加</span> </button>
</button> </el-form-item>
</el-form-item> <el-form-item class="req" label="报名时间">
<el-form-item class="req" label="报名时间"> <el-date-picker v-model="signupTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange"
<el-date-picker v-model="signupTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :picker-options="pickerOptions"></el-date-picker>
:picker-options="pickerOptions"></el-date-picker> </el-form-item>
</el-form-item> </template>
<el-form-item class="req" label="竞赛时间"> <el-form-item class="req" label="竞赛时间">
<el-date-picker v-model="playTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" <el-date-picker v-model="playTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange"
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
@ -92,42 +95,44 @@
</template> </template>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item class="req" label="竞赛类型"> <template v-if="!isPractice">
<el-radio v-model="form.completeCompetitionSetup.competitionType" :label="0">个人赛</el-radio> <el-form-item class="req" label="竞赛类型">
<el-radio v-model="form.completeCompetitionSetup.competitionType" :label="1">团队赛</el-radio> <el-radio v-model="form.completeCompetitionSetup.competitionType" :label="0">个人赛</el-radio>
</el-form-item> <el-radio v-model="form.completeCompetitionSetup.competitionType" :label="1">团队赛</el-radio>
<el-form-item class="req" v-if="!form.completeCompetitionSetup.competitionType" label="报名人数上限"> </el-form-item>
<div class="input-center"> <el-form-item class="req" v-if="!form.completeCompetitionSetup.competitionType" label="报名人数上限">
<el-input placeholder="请输入人数" v-model.number="form.completeCompetitionSetup.quantityLimit"
type="number"></el-input>
</div>
</el-form-item>
<template v-if="form.completeCompetitionSetup.competitionType">
<el-form-item class="req" label="报名团队数上限">
<div class="input-center"> <div class="input-center">
<el-input placeholder="请输入团队数" v-model.number="form.completeCompetitionSetup.quantityLimit" <el-input placeholder="请输入人数" v-model.number="form.completeCompetitionSetup.quantityLimit"
type="number"></el-input> type="number"></el-input>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item class="req" label="团队人数"> <template v-if="form.completeCompetitionSetup.competitionType">
<div class="input-center" style="width: 250px;"> <el-form-item class="req" label="报名团队数上限">
<el-input v-model.number="form.completeCompetitionSetup.minTeamSize" type="number"></el-input> <div class="input-center">
<el-input style="margin-left: 5px;" v-model.number="form.completeCompetitionSetup.maxTeamSize" <el-input placeholder="请输入团队数" v-model.number="form.completeCompetitionSetup.quantityLimit"
type="number"></el-input> / type="number"></el-input>
</div>
</el-form-item>
<el-form-item class="req" label="团队人数">
<div class="input-center" style="width: 250px;">
<el-input v-model.number="form.completeCompetitionSetup.minTeamSize" type="number"></el-input>
<el-input style="margin-left: 5px;" v-model.number="form.completeCompetitionSetup.maxTeamSize"
type="number"></el-input> /
</div>
</el-form-item>
</template>
<el-form-item class="req" label="报名邀请码">
<div class="input-center" style="width: 550px;">
<el-radio v-model="form.completeCompetitionSetup.isNeedCode" :label="0">不需要</el-radio>
<el-radio v-model="form.completeCompetitionSetup.isNeedCode" :label="1">需要</el-radio>
<el-input style="width: 250px" placeholder="请输入4位邀请码或点击随机生成"
v-model="form.completeCompetitionSetup.invitationCode"
:disabled="form.completeCompetitionSetup.isNeedCode === 0"></el-input>
<el-button v-if="form.completeCompetitionSetup.isNeedCode === 1" @click="randomInv">随机</el-button>
</div> </div>
</el-form-item> </el-form-item>
</template> </template>
<el-form-item class="req" label="报名邀请码">
<div class="input-center" style="width: 550px;">
<el-radio v-model="form.completeCompetitionSetup.isNeedCode" :label="0">不需要</el-radio>
<el-radio v-model="form.completeCompetitionSetup.isNeedCode" :label="1">需要</el-radio>
<el-input style="width: 250px" placeholder="请输入4位邀请码或点击随机生成"
v-model="form.completeCompetitionSetup.invitationCode"
:disabled="form.completeCompetitionSetup.isNeedCode === 0"></el-input>
<el-button v-if="form.completeCompetitionSetup.isNeedCode === 1" @click="randomInv">随机</el-button>
</div>
</el-form-item>
<el-form-item class="req" label="竞赛详情"> <el-form-item class="req" label="竞赛详情">
<quill v-if="quillShow" :border="true" v-model="form.description" :height="400" <quill v-if="quillShow" :border="true" v-model="form.description" :height="400"
:readonly="!editing && form.id !== ''" /> :readonly="!editing && form.id !== ''" />
@ -136,6 +141,56 @@
<Upload :limit="5" :file-list.sync="fileList" :on-remove="handleAnnexRemove" <Upload :limit="5" :file-list.sync="fileList" :on-remove="handleAnnexRemove"
@onSuccess="uploadAnnexSuccess" /> @onSuccess="uploadAnnexSuccess" />
</el-form-item> </el-form-item>
<template v-if="isPractice">
<el-form-item label="比赛方式">
<el-radio-group v-model="form.type">
<el-radio :label="0">实训</el-radio>
<el-radio :label="1">理论</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="比赛内容">
<el-button style="margin-bottom: 10px;" size="small" type="primary">选择理论试卷</el-button>
<el-table :data="list" class="table" ref="table" stripe header-align="center" row-key="id">
<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"></el-table-column>
<el-table-column prop="name" label="试卷名称" align="center" min-width="100"></el-table-column>
<el-table-column prop="questionCount" label="试题总数" align="center" width="70"></el-table-column>
<el-table-column prop="score" label="总分" align="center" width="60"></el-table-column>
<el-table-column prop="questionType" label="题型" align="center" min-width="90"
show-overflow-tooltip></el-table-column>
<el-table-column prop="difficult" label="试卷难度" align="center" width="100" sortable="custom">
<!-- <template slot-scope="scope">{{ difficults.find(e => e.id === scope.row.difficult) ? difficults.find(e
=>
e.id === scope.row.difficult).name : '' }}</template> -->
</el-table-column>
<el-table-column prop="suggestTime" label="建议用时" align="center" width="70">
<template slot-scope="scope">{{ scope.row.suggestTime }}min</template>
</el-table-column>
<el-table-column prop="classificationPath" label="试卷分类" align="center" width="90"
show-overflow-tooltip></el-table-column>
<el-table-column label="建议用途" align="center" width="70">
<!-- <template slot-scope="scope">{{ paperTypes.find(e => e.id === scope.row.paperType) ? paperTypes.find(e
=>
e.id === scope.row.paperType).name : '' }}</template> -->
</el-table-column>
<el-table-column prop="updateTime" label="最近编辑时间" align="center" width="160"
sortable="custom"></el-table-column>
<el-table-column prop="createUser" label="最近编辑人" align="center" width="90"></el-table-column>
<el-table-column label="操作" align="center" width="240">
<template slot-scope="scope">
<el-button type="text" @click="toDetail(scope.row, 1)">复制</el-button>
<!-- <el-button type="text" @click="edit(scope.row)">预览</el-button> -->
<el-button type="text" @click="toDetail(scope.row)">编辑</el-button>
<el-button type="text" @click="del(scope.row)">删除</el-button>
<el-switch v-if="!scope.row.status" v-model="scope.row.isDisable" :active-value="false"
:inactive-value="true" style="margin: 0 10px 0 5px" :active-text="scope.row.isDisable ? '关' : '开'"
@change="switchOff($event, scope.row, scope.$index)"></el-switch>
</template>
</el-table-column>
</el-table>
</el-form-item>
</template>
</el-form> </el-form>
</div> </div>
</div> </div>
@ -293,6 +348,11 @@ export default {
quill, quill,
Upload Upload
}, },
computed: {
isPractice () {
return this.$parent.releaseType === 2
},
},
watch: { watch: {
editing: function (val) { editing: function (val) {
this.quillShow = false this.quillShow = false

@ -104,7 +104,7 @@
阶段比赛结束后 阶段比赛结束后
<el-input v-model.number="item.resultAnnouncementTime" type="number" min="0" <el-input v-model.number="item.resultAnnouncementTime" type="number" min="0"
style="width: 120px"></el-input> style="width: 120px"></el-input>
小时公布阶段比赛成绩 小时公布阶段比赛成绩为空则不公布成绩为0则阶段比赛结束后立马公布成绩
</div> </div>
<div <div
v-if="item.resultAnnouncementTime !== '' && item.resultAnnouncementTime !== null && item.resultAnnouncementTime !== undefined" v-if="item.resultAnnouncementTime !== '' && item.resultAnnouncementTime !== null && item.resultAnnouncementTime !== undefined"
@ -136,13 +136,15 @@
</div> </div>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item prop="rule" label="成绩公布时间"> <el-form-item label="成绩公布时间">
阶段比赛结束后 阶段比赛结束后
<el-input v-model.number="form.competitionStageList[0].resultAnnouncementTime" type="number" min="0" <el-input v-model.number="form.competitionStageList[0].resultAnnouncementTime" type="number" min="0"
style="width: 120px"></el-input> style="width: 120px"></el-input>
小时公布阶段比赛成绩 小时公布阶段比赛成绩为空则不公布成绩为0则阶段比赛结束后立马公布成绩
</el-form-item> </el-form-item>
<el-form-item prop="resultsDetails" label="是否公布成绩详情"> <el-form-item
v-if="form.competitionStageList[0].resultAnnouncementTime !== '' && form.competitionStageList[0].resultAnnouncementTime !== null && form.competitionStageList[0].resultAnnouncementTime !== undefined"
prop="resultsDetails" label="是否公布成绩详情">
<el-radio v-model="form.competitionStageList[0].resultsDetails" :label="0"></el-radio> <el-radio v-model="form.competitionStageList[0].resultsDetails" :label="0"></el-radio>
<el-radio v-model="form.competitionStageList[0].resultsDetails" :label="1"></el-radio> <el-radio v-model="form.competitionStageList[0].resultsDetails" :label="1"></el-radio>
<p class="tips">若选择则公布成绩详情竞赛结束后参赛者可查看自己的比赛成绩得分详情</p> <p class="tips">若选择则公布成绩详情竞赛结束后参赛者可查看自己的比赛成绩得分详情</p>
@ -320,12 +322,12 @@ export default {
// //
if (this.step1.completeCompetitionSetup.competitionType) { if (this.step1.completeCompetitionSetup.competitionType) {
const { form, originForm } = this const { form, originForm } = this
// 34 // 34
let changeLimit = 0 let changeLimit = 0
for (const i in form.competitionStageList) { for (const i in form.competitionStageList) {
const e = form.competitionStageList[i] const e = form.competitionStageList[i]
if (e.teamNumLimit !== originForm.competitionStageList[i].teamNumLimit || e.customNumber !== originForm.competitionStageList[i].customNumber) { const originStage = originForm.competitionStageList[i]
if (!originStage || e.teamNumLimit !== originStage.teamNumLimit || e.customNumber !== originStage.customNumber) {
changeLimit = 1 changeLimit = 1
break break
} }

@ -22,6 +22,7 @@
</el-alert> </el-alert>
</div> </div>
</el-form-item> </el-form-item>
<!-- 其他赛事 -->
<template v-if="item.method === 2"> <template v-if="item.method === 2">
<el-form-item class="req" label="比赛地点"> <el-form-item class="req" label="比赛地点">
<el-input v-model="item.offlineAddress" style="width: 80%"></el-input> <el-input v-model="item.offlineAddress" style="width: 80%"></el-input>
@ -70,12 +71,25 @@
</el-form-item> </el-form-item>
</template> </template>
<template v-else> <template v-else>
<el-form-item class="req" prop="cid" label="课程系统"> <template v-if="item.method === 0">
{{ item.systemName }} <el-form-item class="req" prop="cid" label="课程系统">
</el-form-item> {{ item.systemName }}
<el-form-item class="req" prop="assessmentId" label="已选择考核"> </el-form-item>
{{ item.projectName }} <el-form-item class="req" prop="assessmentId" label="已选择考核">
</el-form-item> {{ item.projectName }}
</el-form-item>
</template>
<template v-else>
<el-form-item class="req" label="已选择试卷">
<div class="flex">
{{ item.paperName }}&emsp;
<el-form>
<el-button v-if="item.paperName" type="primary" size="mini" :disabled="false"
@click="previewPaper(item)">预览</el-button>
</el-form>
</div>
</el-form-item>
</template>
<el-form-item class="req" prop="resultAnnouncementTime" label="比赛地点"> <el-form-item class="req" prop="resultAnnouncementTime" label="比赛地点">
<div class="line"> <div class="line">
<el-checkbox v-model="item.onlineButton">线上</el-checkbox> <el-checkbox v-model="item.onlineButton">线上</el-checkbox>
@ -94,8 +108,7 @@
</div> </div>
</div> </div>
<set v-if="setVisible" :form.sync="form[curStep]" :step1.sync="step1" @hideSet="hideSet" /> <Set v-if="setVisible" :form.sync="form[curStep]" :step1.sync="step1" @hideSet="hideSet" />
<el-dialog title="提示" :visible.sync="tipsVisible" width="500px" :close-on-click-modal="false" <el-dialog title="提示" :visible.sync="tipsVisible" width="500px" :close-on-click-modal="false"
custom-class="tips-dia"> custom-class="tips-dia">
@ -113,11 +126,13 @@
</template> </template>
<script> <script>
import Set from './set'
import Oss from '@/components/upload/upload.js' import Oss from '@/components/upload/upload.js'
import Setting from '@/setting'
import Util from '@/libs/util' import Util from '@/libs/util'
import set from './set'
export default { export default {
props: ['setupId', 'competitionId', 'editing'], props: ['setupId', 'competitionId', 'editing'],
components: { Set },
data () { data () {
return { return {
headers: { headers: {
@ -151,6 +166,8 @@ export default {
stageId: '', stageId: '',
startTime: '', startTime: '',
systemId: '', systemId: '',
paperId: '',
paperName: '',
offlineAddress: '', offlineAddress: '',
offlineButton: 0, offlineButton: 0,
onlineAddress: '', onlineAddress: '',
@ -166,9 +183,6 @@ export default {
tipsVisible: false, tipsVisible: false,
}; };
}, },
components: {
set
},
watch: { watch: {
// , // ,
form: { form: {
@ -237,8 +251,10 @@ export default {
form.method = e.method form.method = e.method
form.stageId = e.stageId form.stageId = e.stageId
form.stageName = e.stageName form.stageName = e.stageName
if (form.paperName) form.originPaperName = form.paperName //
this.form.push(form) this.form.push(form)
}) })
this.resumeData() this.resumeData()
this.$nextTick(() => { this.$nextTick(() => {
this.updateTime = 0 this.updateTime = 0
@ -258,6 +274,19 @@ export default {
this.setVisible = false this.setVisible = false
this.$parent.showBtns = true this.$parent.showBtns = true
}, },
//
previewPaper (row) {
let url = `${location.origin}/examination`
if (Setting.isDev) {
url = `http://192.168.31.125:8098/`
} else if (Setting.isPro) {
const { host } = location
url = `https://${host === 'dev.huorantech.cn' ? host : 'www.huorantech.cn'}/examination/`
}
url += `#/testPaper/preview?id=${row.paperId}&token=${sessionStorage.getItem('token')}`
localStorage.setItem('exam_token', sessionStorage.getItem('token'))
window.open(url)
},
// //
timeChange (val) { timeChange (val) {
if (val.length) { if (val.length) {
@ -363,6 +392,7 @@ export default {
this.$confirm('团队赛发布成功,由于您设置的报名时间已结束,如需自动分配阶段参赛人员,请前往报名人员列表进行设置', '提示', { this.$confirm('团队赛发布成功,由于您设置的报名时间已结束,如需自动分配阶段参赛人员,请前往报名人员列表进行设置', '提示', {
confirmButtonText: '关闭', confirmButtonText: '关闭',
type: 'success', type: 'success',
showCancelButton: false,
closeOnClickModal: false, closeOnClickModal: false,
dangerouslyUseHTMLString: true, dangerouslyUseHTMLString: true,
showClose: false, showClose: false,
@ -377,6 +407,10 @@ export default {
this.$emit('next', next) this.$emit('next', next)
} }
}, },
// websocket
async sendSocket () {
await this.$post(`${this.api.refreshPageNotification}?content=1`)
},
// //
save (status, next = 0) { save (status, next = 0) {
const { form } = this const { form } = this
@ -401,11 +435,16 @@ export default {
Util.errorMsg('设置的阶段比赛时间必须要在第一步设置的竞赛时间范围内,请重新设置。') Util.errorMsg('设置的阶段比赛时间必须要在第一步设置的竞赛时间范围内,请重新设置。')
break break
} }
if (e.method !== 2 && !e.cid) { if (e.method === 0 && !e.cid) {
invalid = 1 invalid = 1
Util.errorMsg('请选择课程') Util.errorMsg('请选择课程')
break break
} }
if (e.method === 1 && !e.paperId) {
invalid = 1
Util.errorMsg('请选择试卷')
break
}
if (e.method === 2) { // 线 if (e.method === 2) { // 线
if (!e.offlineAddress) { if (!e.offlineAddress) {
invalid = 1 invalid = 1
@ -470,7 +509,10 @@ export default {
}).then(res => { }).then(res => {
this.$parent.hideLoad() this.$parent.hideLoad()
// //
status && this.publish(status) if (status) {
this.publish(status)
this.sendSocket()
}
Util.successMsg((status ? '发布' : '保存') + '成功') Util.successMsg((status ? '发布' : '保存') + '成功')
this.updateTime = 0 this.updateTime = 0
if (status && this.$parent.$refs.step1.form.completeCompetitionSetup.competitionType) { if (status && this.$parent.$refs.step1.form.completeCompetitionSetup.competitionType) {

@ -0,0 +1,211 @@
<template>
<!-- 理论考试选择试卷 -->
<div>
<el-dialog title="请选择试卷" :visible.sync="listVisible" width="1200px" :close-on-click-modal="false"
@closed="closeDia">
<div class="tool">
<ul class="filter">
<li>
<label>试卷库</label>
<el-select v-model="filter.libraryId" placeholder="请选择试卷库" @change="initData">
<el-option v-for="(item, i) in paperLibraries" :key="i" :label="item.libraryName" :value="item.libraryId">
</el-option>
</el-select>
</li>
<li>
<label>建议用途</label>
<el-select v-model="filter.paperType" clearable placeholder="请选择状态" @change="initData">
<el-option v-for="(item, i) in paperTypes" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</li>
<li>
<label>试卷难度</label>
<el-select v-model="filter.difficult" clearable multiple placeholder="请选择试卷难度" @change="initData">
<el-option v-for="(item, i) in difficults" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</li>
<li>
<label>题目类型</label>
<el-select v-model="questionType" clearable multiple placeholder="请选择题目类型" @change="initData">
<el-option v-for="(item, i) in questionTypes" :key="i" :label="item.name" :value="item.name"></el-option>
</el-select>
</li>
<li>
<label>搜索</label>
<el-input style="width: 250px;" placeholder="请输入试卷名称" prefix-icon="el-icon-search" v-model="filter.keyWord"
clearable />
</li>
</ul>
<div>
<!-- <el-button type="primary" @click="add">自定义理论试卷</el-button> -->
</div>
</div>
<el-table :data="papers" class="table" stripe header-align="center" @sort-change="sortChange">
<el-table-column width="60" label="选择" align="center">
<template slot-scope="scope">
<el-radio v-model="form.paperId" :label="scope.row.paperId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column type="index" width="60" label="序号" align="center"></el-table-column>
<el-table-column prop="name" label="试卷名称" min-width="140" align="center"></el-table-column>
<el-table-column prop="questionCount" label="试题总数" align="center" min-width="70"></el-table-column>
<el-table-column prop="score" label="总分" align="center" min-width="70"></el-table-column>
<el-table-column prop="questionType" label="题型" align="center" min-width="90"
show-overflow-tooltip></el-table-column>
<el-table-column prop="difficult" label="试卷难度" align="center" min-width="70" sortable="custom">
<template slot-scope="scope">{{ difficults.find(e => e.id === scope.row.difficult) ? difficults.find(e =>
e.id === scope.row.difficult).name : '' }}</template>
</el-table-column>
<el-table-column prop="suggestTime" label="建议用时" align="center" min-width="70">
<template slot-scope="scope">{{ scope.row.suggestTime }}min</template>
</el-table-column>
<el-table-column prop="classificationPath" label="试卷分类" align="center" min-width="70"
show-overflow-tooltip></el-table-column>
<el-table-column label="建议用途" align="center" min-width="70">
<template slot-scope="scope">{{ paperTypes.find(e => e.id === scope.row.paperType) ? paperTypes.find(e =>
e.id === scope.row.paperType).name : '' }}</template>
</el-table-column>
<el-table-column prop="updateTime" label="最近编辑时间" align="center" width="170"
sortable="custom"></el-table-column>
<el-table-column prop="createUser" label="最近编辑人" align="center" width="110"></el-table-column>
<el-table-column label="操作" align="center" width="80">
<template slot-scope="scope">
<el-button type="text" @click="previewPaper(scope.row)">预览</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background :page-size="pageSize" @current-change="handleCurrentChange"
layout="total,prev, pager, next" :total="total"></el-pagination>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="listVisible = false">取消</el-button>
<el-button type="primary" :loading="submiting" @click="submit">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Setting from '@/setting'
import Util from '@/libs/util'
import _ from 'lodash'
import QuesConst from '@/const/ques'
import TestPaperConst from '@/const/testPaper'
export default {
props: ['visible', 'form'],
data () {
return {
arabicToChinese: Util.arabicToChinese,
questionTypes: QuesConst.questionTypes,
difficults: TestPaperConst.difficults,
paperTypes: TestPaperConst.paperTypes,
listVisible: false,
searchTimer: null,
questionType: [],
paperLibraries: [],
filter: {
libraryId: '',
paperType: '',
difficult: [],
keyWord: '',
},
list: [],
page: 1,
pageSize: 10,
total: 0,
paperId: '',
submiting: false,
};
},
watch: {
'filter.keyWord': function (val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(this.initData, 500)
},
visible () {
this.listVisible = this.visible
this.visible && this.getList()
}
},
mounted () {
this.originForm = _.cloneDeep(this.form)
},
methods: {
//
async getList () {
try {
const res = await this.$post(this.api.examPaperList, {
...this.filter,
pageNum: this.page,
pageSize: this.pageSize,
type: 1,
keyWord: this.keyword,
libraryId: this.systemId
})
this.papers = res.pageList.records
this.total = res.pageList.total
} catch (e) { }
},
//
currentChange (val) {
this.page = val
this.getList()
},
handleCurrentChange (val) {
this.page = val
this.getList()
},
initData () {
this.page = 1
this.getList()
},
//
sortChange (column) {
if (column.prop === 'updateTime') this.filter.updateTimeOrder = column.order ? column.order === 'ascending' ? 1 : 2 : ''
this.getList()
},
//
add () {
this.form = _.cloneDeep(this.originForm)
this.detailVisible = true
},
//
previewPaper (row) {
this.$parent.previewPaper(row)
},
//
async submit () {
const { paperId } = this.form
if (!paperId) return Util.warningMsg('请选择试卷')
const curPaper = this.papers.find(e => e.paperId === paperId)
if (curPaper) this.form.paperName = curPaper.name
this.handlePaper()
},
//
async handlePaper () {
const { form } = this
// id
if (form.paperName !== form.originPaperName) {
const res = await this.$post(this.api.copyExamPaper, {
associatedID: form.stageId,
paperId: form.paperId,
typeId: 1
})
if (res.examPaper) {
form.paperId = res.examPaper.paperId
}
}
},
//
closeDia () {
this.$emit('update:visible', false)
}
}
};
</script>
<style lang="scss" scoped></style>

@ -29,17 +29,35 @@
<div class="tool mul"> <div class="tool mul">
<ul class="filter"> <ul class="filter">
<li> <li>
<label>赛来源</label> <label>赛来源</label>
<el-select v-model="form.platformSource" clearable @change="sourceChange"> <el-select v-model="form.platformSource" clearable @change="initData">
<el-option v-for="(item, i) in sourceList" :key="i" :label="item.name" :value="item.id"></el-option> <el-option v-for="(item, i) in sourceList" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select> </el-select>
</li> </li>
<li> <li>
<label>大赛范围</label> <label>发布类型</label>
<el-select v-model="form.competitionScope" clearable @change="initData"> <el-select v-model="form.releaseType" clearable @change="initData">
<el-option v-for="(item, i) in releaseTypes" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</li>
<li>
<label>竞赛范围</label>
<el-select v-model="form.competitionScope" @change="initData">
<el-option v-for="(item, i) in rangeList" :key="i" :label="item.name" :value="item.id"></el-option> <el-option v-for="(item, i) in rangeList" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select> </el-select>
</li> </li>
<li>
<label>竞赛类型</label>
<el-select v-model="form.competitionType" clearable @change="initData">
<el-option v-for="(item, i) in competitionTypes" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</li>
<li>
<label>状态</label>
<el-select v-model="form.publishStatus" clearable @change="initData">
<el-option v-for="(item, i) in publishStatus" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</li>
</ul> </ul>
<div> <div>
<el-button type="primary" round @click="add" v-auth>创建竞赛</el-button> <el-button type="primary" round @click="add" v-auth>创建竞赛</el-button>
@ -56,34 +74,39 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="competitionName" label="竞赛名称" align="center"></el-table-column> <el-table-column prop="competitionName" label="竞赛名称" align="center"></el-table-column>
<el-table-column prop="name" label="竞赛类型" width="90" align="center"> <el-table-column prop="name" label="竞赛来源" width="90" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.competitionType ? '团队赛' : '个人赛' }} {{ sourceList.find(e => e.id === scope.row.platformSource).name }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="founderName" label="创建人" align="center"></el-table-column> <el-table-column prop="name" label="发布类型" width="110" align="center">
<el-table-column prop="name" label="大赛来源" width="110" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ sourceList.find(e => e.id === scope.row.platformSource).name }} {{ scope.row.releaseType ? '设置完整比赛' : '练习赛' }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="name" label="大赛范围" align="center"> <el-table-column prop="name" label="竞赛范围" width="100" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ rangeList.find(e => e.id === scope.row.competitionScope).name }} {{ rangeList.find(e => e.id === scope.row.competitionScope).name }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="name" label="竞赛类型" width="90" align="center">
<template slot-scope="scope">
{{ scope.row.competitionType ? '团队赛' : '个人赛' }}
</template>
</el-table-column>
<el-table-column prop="applicantNum" label="报名人数" align="center" width="100"></el-table-column> <el-table-column prop="applicantNum" label="报名人数" align="center" width="100"></el-table-column>
<el-table-column prop="status" label="状态" align="center" width="80"> <el-table-column prop="status" label="状态" align="center" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.publishStatus ? '已发布' : '未发布' }} {{ scope.row.publishStatus ? '已发布' : '未发布' }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="time" label="赛时间" align="center" width="290"> <el-table-column prop="time" label="赛时间" align="center" width="290">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.playStartTime }} ~ {{ scope.row.playEndTime }} {{ scope.row.playStartTime }} ~ {{ scope.row.playEndTime }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="createTime" label="创建时间" align="center" width="160"></el-table-column> <el-table-column prop="createTime" label="创建时间" align="center" width="160"></el-table-column>
<el-table-column prop="founderName" label="创建人" width="130" align="center"></el-table-column>
<el-table-column label="操作" align="center" width="280"> <el-table-column label="操作" align="center" width="280">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" @click="copy(scope.row)">复制</el-button> <el-button type="text" @click="copy(scope.row)">复制</el-button>
@ -128,7 +151,7 @@
</template> </template>
<script> <script>
import util from "@/libs/util"; import Util from '@/libs/util'
import Bus from '@/libs/bus' import Bus from '@/libs/bus'
import qs from 'qs' import qs from 'qs'
export default { export default {
@ -150,11 +173,25 @@ export default {
name: "院校创建" name: "院校创建"
} }
], ],
rangeList: [ releaseTypes: [
{ {
id: '', id: '',
name: "不限" name: "不限"
}, },
{
id: 0,
name: '发布信息'
},
{
id: 1,
name: '完整比赛'
}
],
rangeList: [
{
id: null,
name: "不限"
},
{ {
id: 1, id: 1,
name: "全平台" name: "全平台"
@ -168,14 +205,45 @@ export default {
name: "校内" name: "校内"
} }
], ],
competitionTypes: [
{
id: '',
name: '不限'
},
{
id: 0,
name: '个人赛'
},
{
id: 1,
name: '团队赛'
}
],
publishStatus: [
{
id: '',
name: '不限'
},
{
id: 0,
name: '未发布'
},
{
id: 1,
name: '已发布'
}
],
matchData: [], matchData: [],
form: { form: {
keyWord: this.$route.query.keyWord || null, keyWord: null,
month: +this.$route.query.month || '', month: '',
startTime: this.$route.query.startTime || '', startTime: null,
endTime: this.$route.query.endTime || '', endTime: null,
platformSource: this.$route.query.platformSource === 'null' ? null : (+this.$route.query.platformSource || 0), // (01) releaseType: '',
competitionScope: this.$route.query.competitionScope ? +this.$route.query.competitionScope : '', // (0: 1: 2.) publishStatus: '',
competitionType: '',
platformSource: 0, // (01)
competitionScope: null, // (0: 1: 2.)
}, },
multipleSelection: [], multipleSelection: [],
dateList: [ dateList: [
@ -215,13 +283,14 @@ export default {
}] }]
}, },
loading: false, loading: false,
now: '',
}; };
}, },
watch: { watch: {
"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 = [];
} }
@ -246,6 +315,18 @@ export default {
mounted () { mounted () {
const { query } = this.$route const { query } = this.$route
if (query.page) { if (query.page) {
const { keyWord, month, startTime, endTime, platformSource, competitionScope, competitionType, publishStatus, releaseType } = query
this.form = {
keyWord: keyWord || null,
month: +month || '',
startTime: startTime || null,
endTime: endTime || null,
competitionType: competitionType || '',
publishStatus: publishStatus || '',
releaseType: releaseType || '',
platformSource: platformSource === 'null' ? null : (+platformSource || 0), // (01)
competitionScope: competitionScope ? +competitionScope : null, // (0: 1: 2.)
}
this.$router.push('/match').catch(() => { }) this.$router.push('/match').catch(() => { })
} }
@ -260,43 +341,25 @@ export default {
}) })
}, },
methods: { methods: {
getData () { async getData () {
this.loading = true this.loading = true
const { form } = this try {
this.$post(this.api.CompetitionPageConditionQueryByNakadai, { const { form } = this
pageNum: this.page, const { data } = await this.$post(this.api.CompetitionPageConditionQueryByNakadai, {
pageSize: this.pageSize, pageNum: this.page,
competitionScope: form.competitionScope === '' ? null : form.competitionScope, pageSize: this.pageSize,
endTime: form.endTime || null, ...form
keyWord: form.keyWord, })
platformSource: form.platformSource, this.matchData = data.records
startTime: form.startTime || null,
}).then(({ data }) => { this.now = await Util.getNow()
const list = data.records clearInterval(this.timer)
// this.handleBeganStage()
this.timer = setInterval(() => { this.timer = setInterval(() => {
const now = new Date() this.now = new Date(this.now.setSeconds(this.now.getSeconds() + 1))
list.map(e => { this.handleBeganStage()
if (!e.playingStages) {
this.$set(e, 'playingStages', [])
} else {
e.playingStages = []
}
//
if (now >= new Date(e.playStartTime) && now <= new Date(e.playEndTime)) {
//
if (e.competitionStageList) {
for (const n of e.competitionStageList) {
//
if (now >= new Date(n.startTime) && now <= new Date(n.endTime)) {
e.playingStages.push(n)
}
}
}
}
})
}, 1000) }, 1000)
this.matchData = list
this.total = data.total this.total = data.total
this.$refs.table.clearSelection() this.$refs.table.clearSelection()
this.loading = false this.loading = false
@ -304,8 +367,30 @@ export default {
this.page-- this.page--
this.getData() this.getData()
} }
}).catch(res => { } catch (e) {
this.loading = false this.loading = false
}
},
//
async handleBeganStage () {
this.matchData.map(e => {
if (!e.playingStages) {
this.$set(e, 'playingStages', [])
} else {
e.playingStages = []
}
//
if (this.now >= new Date(e.playStartTime) && this.now <= new Date(e.playEndTime)) {
//
if (e.competitionStageList) {
for (const n of e.competitionStageList) {
//
if (this.now >= new Date(n.startTime) && this.now <= new Date(n.endTime)) {
e.playingStages.push(n)
}
}
}
}
}) })
}, },
initData () { initData () {
@ -326,7 +411,7 @@ export default {
type: "warning" type: "warning"
}).then(async () => { }).then(async () => {
await this.$post(`${this.api.copyCompetition}?competitionId=${row.id}`) await this.$post(`${this.api.copyCompetition}?competitionId=${row.id}`)
util.successMsg('复制成功') Util.successMsg('复制成功')
this.initData() this.initData()
}).catch(() => { }) }).catch(() => { })
}, },
@ -349,7 +434,7 @@ export default {
competitionContents: data competitionContents: data
}).then(async res => { }).then(async res => {
await this.$post(`${this.api.refreshPageNotification}?content=1`) await this.$post(`${this.api.refreshPageNotification}?content=1`)
util.successMsg('修改成功') Util.successMsg('修改成功')
this.modifyVisible = false this.modifyVisible = false
this.getData() this.getData()
}).catch(err => { }) }).catch(err => { })
@ -374,7 +459,7 @@ export default {
}) })
.then(() => { .then(() => {
this.$post(`${this.api.batchDeleteCompetition}?competitionIds=${row.id}`).then(res => { this.$post(`${this.api.batchDeleteCompetition}?competitionIds=${row.id}`).then(res => {
util.successMsg("删除成功"); Util.successMsg("删除成功");
this.getData(); this.getData();
}).catch(res => { }).catch(res => {
}); });
@ -419,7 +504,7 @@ export default {
isOpen: val, isOpen: val,
type: 0 // (01) type: 0 // (01)
}).then(res => { }).then(res => {
util.successMsg(val == 1 ? '禁用成功' : '启用成功') Util.successMsg(val == 1 ? '禁用成功' : '启用成功')
}).catch(err => { }) }).catch(err => { })
await this.$post(`${this.api.refreshPageNotification}?content=1`) await this.$post(`${this.api.refreshPageNotification}?content=1`)

@ -42,7 +42,6 @@ export default {
tab3: "竞赛进展", tab3: "竞赛进展",
tab4: "公告通知", tab4: "公告通知",
tab5: "报名人员", tab5: "报名人员",
tab6: '查看异常团队'
} }
}; };
}, },
@ -55,7 +54,11 @@ export default {
AbnormalTeam AbnormalTeam
}, },
mounted () { mounted () {
Setting.dynamicRoute && this.initTabs() // if (Setting.dynamicRoute) {
this.initTabs()
// } else {
// this.active = this.$route.query.tab || 'tab1'
// }
}, },
methods: { methods: {
async initTabs () { async initTabs () {
@ -73,7 +76,12 @@ export default {
tab3 || this.$delete(this.tabs, 'tab3') tab3 || this.$delete(this.tabs, 'tab3')
tab4 || this.$delete(this.tabs, 'tab4') tab4 || this.$delete(this.tabs, 'tab4')
tab5 || this.$delete(this.tabs, 'tab5') tab5 || this.$delete(this.tabs, 'tab5')
res.competition.completeCompetitionSetup.competitionType || this.$delete(this.tabs, 'tab6')
if (res.competition.completeCompetitionSetup.competitionType) {
this.tabs.tab6 || this.$set(this.tabs, 'tab6', '查看异常团队')
} else {
this.tabs.tab6 && this.$delete(this.tabs, 'tab6')
}
const type = this.$route.query.tab const type = this.$route.query.tab
const keys = Object.keys(this.tabs) const keys = Object.keys(this.tabs)
@ -117,7 +125,7 @@ export default {
// tab // tab
tabSwitch (i) { tabSwitch (i) {
this.active = i this.active = i
this.$router.push(`/matchManage?id=${this.$route.query.id}&tab=${i}&name=${this.name}`) this.$router.push(`/matchManage?id=${this.$route.query.id}&tab=${i}&name=${this.name}`).catch(e => { })
}, },
// tab // tab
backOrTab (i) { backOrTab (i) {

@ -1,61 +1,57 @@
<template> <template>
<!-- 报名人员 --> <!-- 报名人员 -->
<div class="page-content" <div class="page-content" style="padding: 24px">
style="padding: 24px"> <el-table ref="table" :data="list" class="table" stripe header-align="center" row-key="stageId">
<el-table ref="table" <el-table-column type="index" width="60" label="序号" align="center">
:data="list"
class="table"
stripe
header-align="center"
row-key="stageId">
<el-table-column type="index"
width="60"
label="序号"
align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.$index + 1 }} {{ scope.$index + 1 }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="stageName" <el-table-column prop="stageName" label="阶段名称" align="center"></el-table-column>
label="阶段名称" <el-table-column prop="competitionContent" label="比赛内容" align="center"></el-table-column>
align="center"></el-table-column> <el-table-column prop="methodName" label="比赛方式" align="center"></el-table-column>
<el-table-column prop="methodName" <el-table-column label="竞赛类型" align="center">
label="比赛方式"
align="center"></el-table-column>
<el-table-column prop="founderName"
label="比赛形式"
align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.competitionType ? '团队赛' : '个人赛' }} {{ scope.row.competitionType ? '团队赛' : '个人赛' }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="ruleName" <el-table-column prop="ruleName" label="赛制" align="center"></el-table-column>
label="赛制" <el-table-column prop="status" label="大赛状态" align="center"></el-table-column>
align="center"></el-table-column> <el-table-column prop="reviewStatus" label="评阅情况" align="center"></el-table-column>
<el-table-column prop="status" <el-table-column label="竞赛时间" width="290" align="center">
label="状态"
align="center"></el-table-column>
<el-table-column label="竞赛起止时间"
width="290"
align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.startTime + ' ~ ' + scope.row.endTime }} {{ scope.row.startTime + ' ~ ' + scope.row.endTime }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" <el-table-column label="操作" align="center" width="280">
align="center"
width="260">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="primary" <el-button type="text" @click="toRank(scope.row, scope.$index)">排名</el-button>
@click="toRank(scope.row, scope.$index)">排名</el-button> <el-button type="text" @click="toArch(scope.row, scope.$index)">成绩统计</el-button>
<el-button @click="toArch(scope.row, scope.$index)">成绩管理</el-button> <!-- <el-button @click="toArch(scope.row, scope.$index)">编辑试卷</el-button> -->
<template v-if="scope.row.method === 1">
<el-button v-if="scope.row.showMyReviewTask" type="text"
@click="showReview(scope.row, '/myReview/records')">我的评阅任务</el-button>
<el-button v-auth="'/review:分配评阅任务'" type="text"
@click="showReview(scope.row, '/allocationReview')">分配评阅任务</el-button>
</template>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<el-drawer title="" :visible.sync="reviewVisible" size="100%" :close-on-click-modal="false" :withHeader="false"
custom-class="review-dia">
<div>
<button type="button" class="el-drawer__close-btn" @click="reviewVisible = false">
<i class="el-dialog__close el-icon el-icon-close"></i>
</button>
</div>
<iframe :src="reviewUrl" frameborder="0" width="100%"></iframe>
</el-drawer>
</div> </div>
</template> </template>
<script> <script>
import Setting from '@/setting'
import Const from '@/const/match' import Const from '@/const/match'
export default { export default {
name: "matchArch", name: "matchArch",
@ -66,6 +62,8 @@ export default {
form: {}, form: {},
timer: null, timer: null,
curStep: [], curStep: [],
reviewVisible: false,
reviewUrl: '',
}; };
}, },
mounted () { mounted () {
@ -125,7 +123,16 @@ export default {
this.$store.commit('setInnerReferrer', this.$route.fullPath) this.$store.commit('setInnerReferrer', this.$route.fullPath)
const cur = this.form.competitionStage[i] const cur = this.form.competitionStage[i]
const showFile = !!(cur.method === 2 && cur.competitionStageContentSetting && cur.competitionStageContentSetting.whetherToUploadFiles) const showFile = !!(cur.method === 2 && cur.competitionStageContentSetting && cur.competitionStageContentSetting.whetherToUploadFiles)
this.$router.push(`/matchArchList?id=${this.id}&stageId=${row.stageId}&method=${row.method}&competitionType=${row.competitionType}&showFile=${showFile}`) this.$router.push(`/${cur.method === 2 ? 'otherArchList' : 'matchArchList'}?id=${this.id}&stageId=${row.stageId}&method=${row.method}&competitionType=${row.competitionType}&showFile=${showFile}&showMyReviewTask=${row.showMyReviewTask}`)
},
//
showReview (row, path) {
let url = `${location.origin}/reviewCenter/`
if (Setting.isDev) url = `http://192.168.31.125:8099/`
url += `#${path}?token=${sessionStorage.getItem('token')}&v=${Date.now()}&competitionId=${this.id}&stageId=${row.stageId}`
localStorage.setItem('review_token', sessionStorage.getItem('token'))
this.reviewUrl = url
this.reviewVisible = true
} }
} }
}; };
@ -133,15 +140,29 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
/deep/.el-collapse-item__header { /deep/.el-collapse-item__header {
font-size: 16px; font-size: 16px;
color: #333; color: #333;
} }
.line { .line {
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
align-items: center; align-items: center;
span {
margin-right: 30px; span {
} margin-right: 30px;
}
}
/deep/.review-dia {
.el-drawer__close-btn {
position: absolute;
top: 20px;
right: 20px;
}
iframe {
height: 100%;
}
} }
</style> </style>

File diff suppressed because it is too large Load Diff

@ -36,15 +36,15 @@
</tr> </tr>
<tr> <tr>
<th>学校</th> <th>学校</th>
<td>{{ info.person.schoolName }}</td> <td>{{ info.person.realSchool }}</td>
</tr> </tr>
</template> </template>
<template v-if="form.completeCompetitionSetup.competitionType"> <template v-if="form.completeCompetitionSetup.competitionType">
<template> <template>
<tr> <tr>
<th>队长</th> <th>队长</th>
<td>{{ info.caption.userName }}{{ info.caption.schoolName && ',' + info.caption.schoolName }}{{ <td>{{ info.captain.userName }}{{ info.captain.realSchool && ',' + info.captain.realSchool }}{{
info.caption.workNumber && ',' + info.caption.workNumber }}</td> info.captain.workNumber && ',' + info.captain.workNumber }}</td>
</tr> </tr>
<tr> <tr>
<th>团队成员</th> <th>团队成员</th>
@ -129,7 +129,7 @@
<td colspan="6">暂无数据</td> <td colspan="6">暂无数据</td>
</tr> </tr>
</table> </table>
<el-alert v-if="form.completeCompetitionSetup.competitionType" style="margin-top: 10px;" <el-alert v-if="form.completeCompetitionSetup.competitionType && form.rule !== 2" style="margin-top: 10px;"
:title="'注:请团长(团队创建人)设置各阶段参赛成员,只有被选择的允许参赛成员可进入对应阶段比赛' + (info.teamLimit ? ',每个团队成员只能参加一个赛项阶段' : '') + '!'" :title="'注:请团长(团队创建人)设置各阶段参赛成员,只有被选择的允许参赛成员可进入对应阶段比赛' + (info.teamLimit ? ',每个团队成员只能参加一个赛项阶段' : '') + '!'"
type="warning" show-icon> type="warning" show-icon>
</el-alert> </el-alert>
@ -144,12 +144,13 @@
}}</el-tag> }}</el-tag>
</div> </div>
<div class="flex-center"> <div class="flex-center">
<p>队长{{ info.caption.userName }}</p> <p>队长{{ info.captain.userName }}</p>
<el-button type="primary" @click="transfer">转让队长</el-button> <el-button type="primary" @click="transfer">转让队长</el-button>
</div> </div>
<el-table :data="info.teamDetail" stripe header-align="center"> <el-table :data="info.teamDetail" stripe header-align="center">
<el-table-column prop="userName" 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="schoolName" label="学校" min-width="100" align="center"></el-table-column> <el-table-column prop="realSchool" label="学校" min-width="100" align="center"></el-table-column>
<el-table-column prop="phone" 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="workNumber" label="学号" min-width="100" align="center"></el-table-column>
<el-table-column prop="createTime" label="加入时间" width="180" align="center"></el-table-column> <el-table-column prop="createTime" label="加入时间" width="180" align="center"></el-table-column>
<el-table-column label="操作" align="center" width="160"> <el-table-column label="操作" align="center" width="160">
@ -198,7 +199,7 @@
<tr v-for="(item, i) in members" :key="i"> <tr v-for="(item, i) in members" :key="i">
<td>{{ i + 1 }}</td> <td>{{ i + 1 }}</td>
<td>{{ item.userName }}</td> <td>{{ item.userName }}</td>
<td>{{ item.schoolName }}</td> <td>{{ item.realSchool }}</td>
<td>{{ item.timeSum }}min</td> <td>{{ item.timeSum }}min</td>
<td>{{ item.score }}</td> <td>{{ item.score }}</td>
<td> <td>
@ -239,7 +240,7 @@ export default {
info: { info: {
isCaption: 0, isCaption: 0,
person: {}, person: {},
caption: {}, captain: {},
team: { team: {
captain: 1, captain: 1,
invitationCode: '' invitationCode: ''
@ -314,10 +315,10 @@ export default {
info.team = {} info.team = {}
info.teamDetail = [] info.teamDetail = []
} else { } else {
info.isCaption = info.team.caption info.isCaption = info.team.captain
} }
const caption = info.teamDetail.find(e => !e.caption) const captain = info.teamDetail.find(e => !e.captain)
info.caption = caption ? caption : {} info.captain = captain ? captain : {}
info.person = info.personalDetail || info.teamDetail.find(e => e.accountId == info.team.accountId) info.person = info.personalDetail || info.teamDetail.find(e => e.accountId == info.team.accountId)
this.originInfo = JSON.parse(JSON.stringify(info)) this.originInfo = JSON.parse(JSON.stringify(info))
// accountId // accountId
@ -347,9 +348,10 @@ export default {
teamId: this.info.teamId teamId: this.info.teamId
}) })
this.teamErrors = res.teamTip.split(';').filter(e => e) this.teamErrors = res.teamTip.split(';').filter(e => e)
if (Object.keys(res.stageTip).length) { if (Object.keys(res.stageTip).length) {
this.stageTip = res.stageTip this.stageTip = res.stageTip
} else {
this.stageTip = null
} }
}, },
// //
@ -451,7 +453,7 @@ export default {
transferSubmit () { transferSubmit () {
if (!this.checkedPlayer) return Util.errorMsg('请选择成员') if (!this.checkedPlayer) return Util.errorMsg('请选择成员')
this.$post(this.api.captainOfTransfer, { this.$post(this.api.captainOfTransfer, {
captainId: this.info.caption.teamId, captainId: this.info.captain.teamId,
playerId: this.checkedPlayer playerId: this.checkedPlayer
}).then(res => { }).then(res => {
this.checkedPlayer = '' this.checkedPlayer = ''
@ -570,9 +572,9 @@ export default {
}, },
// //
show (row) { show (row) {
this.curRow = row
// //
if (this.form.completeCompetitionSetup.competitionType) { // if (this.form.completeCompetitionSetup.competitionType) { //
this.curRow = row
this.memberVisible = true this.memberVisible = true
if (this.info.teamId) { if (this.info.teamId) {
this.getMembers() this.getMembers()
@ -589,7 +591,7 @@ export default {
}, },
// //
toReport (row) { toReport (row) {
this.$router.push(`/matchReport?reportId=${row.reportId}`) this.$router.push(`/${this.curRow.method === 1 ? 'theoryReport' : 'trialReport'}?reportId=${row.reportId}`)
}, },
back () { back () {
this.$router.push(this.$store.state.innerReferrer) this.$router.push(this.$store.state.innerReferrer)

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<el-card shadow="hover" class="m-b-20 head-card"> <el-card shadow="hover" class="m-b-20 head-card">
<div class="flex-between m-b-20"> <div class="flex-between">
<el-page-header v-if="grades.length" @back="back" :content="grades[index].stageName + '/排名'"></el-page-header> <el-page-header v-if="grades.length" @back="back" :content="grades[index].stageName + '/排名'"></el-page-header>
</div> </div>
@ -14,15 +14,41 @@
@click="tabChange(item.stageId)">{{ item.stageName }}排名</a> @click="tabChange(item.stageId)">{{ item.stageName }}排名</a>
</template> </template>
</div> </div>
<div class="flex-between" style="margin: 20px 0">
<div class="tool flex-between" style="margin-top: 20px">
<div style="display: inline-flex;align-items: center"> <div style="display: inline-flex;align-items: center">
<el-radio v-model="type" :label="0" @change="typeChange">默认系统排序</el-radio> <el-radio v-model="type" :label="0" @change="typeChange">默认系统排序</el-radio>
<el-radio v-model="type" :label="1" @change="typeChange">手动上传</el-radio> <el-radio v-model="type" :label="1" @change="typeChange">手动上传</el-radio>
<el-button type="primary" :disabled="type === 0" class="ml20" @click="batchImport">上传文件</el-button> <el-button type="primary" :disabled="type === 0" class="ml20" @click="batchImport">上传文件</el-button>
</div> </div>
<div style="display: inline-flex;align-items: center"> <ul class="filter" style="flex: none;">
<el-input style="margin-right: 15px" :placeholder="'请输入' + (competitionType ? '团队名称/队长' : '学生姓名') + '/学校'" <li>
prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> <label>省份</label>
<el-select v-model="filter.provinceId" clearable filterable placeholder="请选择省份" @change="provinceChange"
@clear="clearProvince">
<el-option v-for="(item, i) in provinces" :key="i" :label="item.provinceName"
:value="item.provinceId"></el-option>
</el-select>
</li>
<li>
<label>城市</label>
<el-select v-model="filter.cityId" clearable filterable placeholder="请选择城市" :disabled="!filter.provinceId"
@change="initData">
<el-option v-for="(item, i) in cities" :key="i" :label="item.cityName" :value="item.cityId"></el-option>
</el-select>
</li>
<li>
<label>学校</label>
<el-select v-model="filter.realSchoolId" clearable filterable placeholder="请选择学校" @change="initData">
<el-option v-for="(item, i) in schools" :key="i" :label="item.schoolName"
:value="item.schoolId"></el-option>
</el-select>
</li>
<li>
<el-input style="margin-right: 15px" :placeholder="'请输入' + (competitionType ? '团队名称/队长' : '学生姓名') + '/学校'"
prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
</li>
<el-button v-if="!published" type="primary" @click="cancelPublish(1)">发布排名</el-button> <el-button v-if="!published" type="primary" @click="cancelPublish(1)">发布排名</el-button>
<template v-else> <template v-else>
<span style="margin-right: 10px;white-space: nowrap;">{{ publishTime }}发布排名</span> <span style="margin-right: 10px;white-space: nowrap;">{{ publishTime }}发布排名</span>
@ -31,8 +57,9 @@
<el-button v-if="list.length" type="primary" :loading="exporting" @click="exportData">{{ exporting ? '正在导出' : <el-button v-if="list.length" type="primary" :loading="exporting" @click="exportData">{{ exporting ? '正在导出' :
'批量导出' '批量导出'
}}</el-button> }}</el-button>
</div> </ul>
</div> </div>
<el-table :data="list" class="table" ref="table" stripe row-key="scoreId" <el-table :data="list" class="table" ref="table" stripe row-key="scoreId"
@selection-change="handleSelectionChange" header-align="center"> @selection-change="handleSelectionChange" header-align="center">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column> <el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
@ -46,6 +73,8 @@
<el-table-column prop="leaderName" label="队长" min-width="150" align="center"></el-table-column> <el-table-column prop="leaderName" label="队长" min-width="150" align="center"></el-table-column>
</template> </template>
<el-table-column v-else prop="userName" label="学生姓名" min-width="100" align="center"></el-table-column> <el-table-column v-else prop="userName" label="学生姓名" min-width="100" align="center"></el-table-column>
<el-table-column prop="provinceName" label="省份" min-width="100" align="center"></el-table-column>
<el-table-column prop="cityName" label="城市" min-width="100" align="center"></el-table-column>
<el-table-column prop="schoolName" label="学生账号归属" min-width="100" align="center"></el-table-column> <el-table-column prop="schoolName" label="学生账号归属" min-width="100" align="center"></el-table-column>
<el-table-column prop="realSchool" label="学生所在院校" min-width="100" align="center"></el-table-column> <el-table-column prop="realSchool" label="学生所在院校" min-width="100" align="center"></el-table-column>
<el-table-column prop="timeSum" label="用时" width="90" align="center"> <el-table-column prop="timeSum" label="用时" width="90" align="center">
@ -100,7 +129,7 @@
<template v-if="item.accountId"> <template v-if="item.accountId">
<td>{{ i + 1 }}</td> <td>{{ i + 1 }}</td>
<td>{{ item.userName }}</td> <td>{{ item.userName }}</td>
<td>{{ item.schoolName }}</td> <td>{{ item.realSchool }}</td>
<td>{{ item.timeSum }}min</td> <td>{{ item.timeSum }}min</td>
<td>{{ item.score }}</td> <td>{{ item.score }}</td>
<td> <td>
@ -178,10 +207,18 @@ export default {
id: +this.$route.query.id, id: +this.$route.query.id,
stageId: +this.$route.query.stageId, stageId: +this.$route.query.stageId,
index: +this.$route.query.index, index: +this.$route.query.index,
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, searchTimer: null,
filter: {
provinceId: '',
cityId: '',
realSchoolId: '',
},
provinces: [],
cities: [],
schools: [],
keyword: this.$route.query.keyword || '', keyword: this.$route.query.keyword || '',
teamCalculationMethods: [ teamCalculationMethods: [
{ {
@ -262,6 +299,8 @@ export default {
} }
}, },
mounted () { mounted () {
this.getProvince()
this.getSchool()
this.getStage() this.getStage()
}, },
methods: { methods: {
@ -275,6 +314,7 @@ export default {
}, },
// //
getRank () { getRank () {
const { filter } = this
this.loading = true this.loading = true
// //
if (this.type) { if (this.type) {
@ -284,7 +324,8 @@ export default {
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 keyword: this.keyword,
...filter
}).then(({ message, publishStatus }) => { }).then(({ message, publishStatus }) => {
// isRelease 01 // isRelease 01
this.published = publishStatus this.published = publishStatus
@ -307,7 +348,8 @@ export default {
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 keyword: this.keyword,
...filter
}).then(({ page, publishStatus, total }) => { }).then(({ page, publishStatus, total }) => {
this.published = publishStatus this.published = publishStatus
this.list = page || [] this.list = page || []
@ -319,7 +361,7 @@ export default {
}) })
} else { } else {
// //
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.$post(`${this.api.stageRaceRanking}?competitionId=${this.id}&stageId=${this.active}&pageNum=${this.page}&pageSize=${this.pageSize}&publicationType=${this.type}&keyword=${this.keyword}&provinceId=${filter.provinceId}&cityId=${filter.cityId}&realSchoolId=${filter.realSchoolId}`).then(({ page, total, publishStatus }) => {
this.published = publishStatus this.published = publishStatus
this.list = page this.list = page
this.total = total this.total = total
@ -367,6 +409,39 @@ export default {
this.active = i this.active = i
this.initData() this.initData()
}, },
//
async getProvince () {
const { list } = await this.$get(this.api.queryProvince)
this.provinces = list
},
//
clearProvince () {
this.filter.cityId = ''
},
//
provinceChange () {
this.clearProvince()
this.getCity()
this.initData()
},
//
async getCity () {
const id = this.filter.provinceId
if (id) {
const { list } = await this.$get(this.api.queryCity, {
provinceId: id
})
this.cities = list
}
},
//
async getSchool () {
const { list } = await this.$get(this.api.querySchoolData)
this.schools = list
},
// //
show (row, i) { show (row, i) {
this.teams = [] this.teams = []
@ -449,7 +524,7 @@ export default {
}, },
// //
toReport (row) { toReport (row) {
this.$router.push(`/matchReport?reportId=${row.reportId}`) this.$router.push(`/${this.method !== 1 ? 'trialReport' : 'theoryReport'}?reportId=${row.reportId}`)
}, },
handleSelectionChange (val) { // handleSelectionChange (val) { //
this.multipleSelection = val; this.multipleSelection = val;

@ -1,449 +0,0 @@
<template>
<div class="wrap">
<el-card shadow="hover"
class="m-b-20">
<el-page-header @back="$router.back()"
content="查看报告"></el-page-header>
</el-card>
<div class="content"
v-loading="loading">
<div class="text-right">
<el-button type="primary"
@click="exportPage">导出报告</el-button>
</div>
<h6 class="r-title">标准实验报告</h6>
<div class="info">
<h6 class="l-title">
<img src="@/assets/img/info1.png"
alt="">
基本信息
</h6>
<ul :class="['info-list', {edit: editing}]">
<li>
<label>学生姓名</label>
<el-input v-if="editing"
v-model="infoData.userName"
disabled></el-input>
<span v-else>{{ infoData.userName }}</span>
</li>
<li>
<label>学生学号</label>
<el-input v-if="editing"
v-model="infoData.workNumber"
disabled></el-input>
<span v-else>{{ infoData.workNumber }}</span>
</li>
<li>
<label>实验时间</label>
<el-input v-if="editing"
v-model="infoData.submitTime"
disabled></el-input>
<span v-else>{{ infoData.submitTime }}</span>
</li>
<li>
<label>实验成绩</label>
<el-input v-if="editing"
v-model="infoData.score"
disabled></el-input>
<div v-else
class="score-wrap">
<em>{{ infoData.score }}</em>
<img src="@/assets/img/point.png"
alt="">
</div>
</li>
<li>
<label>学生班级</label>
<el-input v-if="editing"
v-model="infoData.className"></el-input>
<span v-else>{{ infoData.className }}</span>
</li>
<li>
<label>指导老师</label>
<el-input v-if="editing"
v-model="infoData.instructor"></el-input>
<span v-else>{{ infoData.instructor }}</span>
</li>
<li>
<label>实验学时</label>
<el-input v-if="editing"
v-model="infoData.period"></el-input>
<span v-else>{{ infoData.period }}</span>
</li>
</ul>
<div class="m-b-20">
<h6 class="l-title">
<img src="@/assets/img/report2.png"
alt="">
实验项目名称
</h6>
<el-input v-if="editing"
v-model="form.projectName"
type="textarea"></el-input>
<div v-else
class="pre-wrap"
v-html="form.projectName"></div>
</div>
<div class="m-b-20">
<h6 class="l-title">
<img src="@/assets/img/report3.png"
alt="">
实验目的
</h6>
<div :class="['pre-wrap', {edit: editing}]"
v-html="form.purpose"></div>
</div>
<div class="m-b-20">
<h6 class="l-title">
<img src="@/assets/img/report4.png"
alt="">
实验数据
</h6>
<el-table :data="expData"
class="table"
border
stripe
header-align="center">
<el-table-column type="index"
label="序号"
align="center"
width="60">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="judgmentName"
label="判分点"
width="270"
align="center"></el-table-column>
<el-table-column v-if='project'
prop="judgmentName"
label="考核点"
align="center"
width="150">
<template slot-scope="scope">
<div v-for="(item, index) in scope.row.lcRuleRecords"
:key="index">
<span>
<span>{{index+1}}. </span>{{item.name}}
</span>
</div>
</template>
</el-table-column>
<el-table-column prop="ruleAnswer"
label="参考答案"
style='word-wrap: break-word'>
<template slot-scope="scope">
<div v-if='scope.row.lcRuleRecords'>
<div v-for="(item, index) in scope.row.lcRuleRecords"
:key="index">
<span>
<span>{{index+1}}. </span>{{item.ruleAnswer}}
</span>
</div>
</div>
<div v-else
v-html="scope.row.referenceAnswer"></div>
</template>
</el-table-column>
<el-table-column prop="userAnswer"
label="学生答案">
<template slot-scope="scope">
<div v-if='scope.row.lcRuleRecords'>
<div v-for="(item, index) in scope.row.lcRuleRecords"
:key="index">
<span v-if='item.userAnswer'>
<span>{{index+1}}. </span>{{item.userAnswer}}
</span>
<span v-else>
<span>{{index+1}}. </span>未填写
</span>
</div>
</div>
<div v-else
v-html='scope.row.answer'
style='white-space: pre-wrap'></div>
<template v-if="scope.row.runThePictureList">
<img v-for="(img, i) in scope.row.runThePictureList"
:key="i"
width="200"
class="result-pic"
:src="img"
alt="">
</template>
</template>
</el-table-column>
<el-table-column prop="quesScore"
label="分值"
:key="6"
width="80"
align="center"></el-table-column>
<el-table-column prop="score"
label="得分"
width="80"
align="center"></el-table-column>
</el-table>
</div>
<div class="m-b-20">
<h6 class="l-title">
<img src="@/assets/img/report5.png"
alt="">
实验总结与体会
</h6>
<quill v-if="editing"
:border="true"
v-model="form.summarize"
:minHeight="150"
:height="150" />
<div v-else
class="pre-wrap"
v-html="form.summarize"></div>
</div>
</div>
</div>
</div>
</template>
<script>
import util from "@/libs/util";
export default {
data () {
return {
reportId: this.$route.query.reportId,
title: "实验报告",
form: {
className: "",
instructor: "",
period: "",
projectName: "",
summarize: "",
},
infoData: {},
expData: [],
editing: false,
loadIns: null,
loading: false,
project: false,
userScores: []
};
},
mounted () {
this.getData()
},
methods: {
getData () { //
this.loading = true
this.$get(`${this.api.reportDetail}?reportId=${this.reportId}`).then(({ report, userScores }) => {
this.form = report
this.expData = userScores
this.project = this.expData.find(e => e.lcRuleRecords) // lcRuleRecords
let form = this.form;
this.infoData = {
workNumber: form.workNumber,
experimentalClassName: form.experimentalClassName,
instructor: form.instructor,
period: form.period,
laboratory: form.laboratory,
submitTime: form.submitTime,
score: form.score,
className: form.className,
userName: form.userName
}
const data = report.data
this.userScores = userScores
// data使
if (!data) {
this.handleList(userScores)
this.$post(this.api.editExperimentalData, {
reportId,
data: JSON.stringify(userScores)
}).then(res => { }).catch(err => { })
} else {
this.handleList(userScores.find(e => e.lcRuleRecords) ? userScores : JSON.parse(data))
}
}).catch(res => {
this.loading = false
})
},
//
handleList (list) {
this.project = list.find(e => e.lcRuleRecords) // lcRuleRecords
if (this.project) {
list.map(e => {
e.assessmentPoint = ''
e.referenceAnswer = ''
e.answer = ''
e.lcRuleRecords.map((n, i) => {
e.assessmentPoint += `${i + 1}.${n.name}`
e.referenceAnswer += `${i + 1}.${n.ruleAnswer}`
e.answer += `${i + 1}.${n.userAnswer}`
})
})
} else { // pythonuserScores
list.forEach(e => {
const item = this.userScores.find(n => n.judgmentId == e.judgmentId)
if (item && item.runThePictureList) e.runThePictureList = item.runThePictureList
})
}
this.expData = list
this.loading = false
},
exportPage () {
const form = Object.assign(this.form, this.infoData)
const list = JSON.parse(JSON.stringify(this.expData))
list.map((e, i) => {
const item = this.userScores.find(n => n.judgmentId == e.judgmentId)
if (item && item.runThePicture) e.runThePicture = item.runThePicture
if (item && item.runThePictureList) e.runThePictureList = item.runThePictureList
e.id = i + 1
// if (e.referenceAnswer && typeof e.referenceAnswer === 'string') e.referenceAnswer = e.referenceAnswer.replace(/<[^>]+>/g, '').replace(/(&nbsp;|&amp;|%s)/g, '').replace(/>/g, '&gt;').replace(/</g, '&lt;')
if (e.answer && typeof e.answer === 'string') e.answer = e.answer.replace(/<[^>]+>/g, '').replace(/(&nbsp;|&amp;|%s)/g, '').replace(/>/g, '&gt;').replace(/</g, '&lt;')
})
for (const i in form) {
if (form[i] && typeof form[i] === 'string') form[i] = form[i].replace(/<[^>]+>/g, '')
}
form.purpose = form.purpose.replace(/<[^>]+>/g, '')
this.$post(this.project ? this.api.exportBankExperimentReport : this.api.exportLabReport, {
...form,
experimentalData: list
}).then(res => {
console.log(res)
util.downloadFileDirect(`实验报告.docx`, new Blob([res]))
}).catch(res => { })
},
}
};
</script>
<style lang="scss" scoped>
.wrap {
padding: 12px 300px 20px;
}
.text-right {
text-align: right;
}
code,
kbd,
samp {
font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', arial, STHeiTi, sans-serif;
word-wrap: break-word;
white-space: pre-wrap;
}
/deep/ pre {
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
word-break: break-all;
overflow: hidden;
font-size: 12px;
font-weight: 400;
font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', arial, STHeiTi, sans-serif;
}
.content {
padding: 16px 40px;
background: #fff;
.r-title {
margin-bottom: 40px;
font-size: 24px;
text-align: center;
color: #333;
}
.info {
padding: 20px 16px;
border: 1px solid #e1e6f2;
}
.l-title {
display: flex;
align-items: center;
padding: 5px 8px;
margin-bottom: 12px;
font-size: 14px;
color: #333;
background-color: #f7f5ff;
}
.info-list {
display: flex;
flex-wrap: wrap;
padding: 10px 0 0 20px;
li {
display: inline-flex;
width: 23%;
padding: 0 10px;
margin-bottom: 34px;
}
&.edit {
li {
align-items: center;
}
}
label {
font-size: 14px;
color: #333;
white-space: nowrap;
}
span {
min-width: 150px;
padding: 0 10px 3px;
border-bottom: 1px solid #e1e6f2;
}
/deep/.el-input {
width: 174px;
}
}
.score-wrap {
position: relative;
min-width: 150px;
border-bottom: 1px solid #e1e6f2;
em {
position: absolute;
top: -12px;
left: 30px;
font-family: din;
font-size: 30px;
font-weight: 600;
color: #0b1d30;
}
img {
position: absolute;
bottom: -15px;
left: 0;
}
}
/deep/.el-textarea .el-textarea__inner,
.pre-wrap {
min-height: 72px;
padding: 10px 16px;
font-size: 14px;
color: #333;
&.edit {
color: #abb3c6;
border: 1px solid #cacfdb;
border-radius: 4px;
background-color: #f6f7f9;
}
}
/deep/ .table th {
background-color: #e5dfff !important;
.cell {
line-height: 35px;
color: #fff;
}
}
}
.result-pic {
margin: 10px 0;
}
@media (max-width: 1650px) {
.wrap {
padding: 12px 200px 20px;
}
}
@media (max-width: 1430px) {
.wrap {
padding: 12px 100px 20px;
}
}
</style>

@ -17,9 +17,22 @@
</li> </li>
</ul> </ul>
<div> <div>
<el-button v-show="loaded && info.completeCompetitionSetup.competitionType" type="primary" round <template v-if="loaded && info.completeCompetitionSetup.competitionType">
:disabled="hasReport" :loading="allocating" @click="autoAllocationConfirm">{{ !notBeginSign && allocated ? <el-button type="primary" round :disabled="hasReport" :loading="allocating" @click="autoAllocationConfirm">{{
'取消' : '' }}自动分配阶段成员</el-button> !notBeginSign && allocated ?
'取消' : '' }}自动分配阶段成员</el-button>
<el-tooltip placement="top">
<div slot="content">
<p>报名结束前设置的自动分配将在报名结束时触发一次系统自动分配取消则不触发</p>
<p style="margin: 5px 0;">报名结束后也可以手动点击自动分配按钮来立即触发系统自动分配并且点击一次就触发一次</p>
<p></p>
<p style="margin: 5px 0;">&emsp;&emsp;1. 自动分配仅对触发时已报名的人员进行对于分配后才报名的人员如需自动分配则需手动再次触发自动分配</p>
<p>&emsp;&emsp;2. 若已有学生提交了成绩报告则无法启用自动分配功能</p>
</div>
<i class="el-icon-question"
style="margin: 0 10px 0 5px;font-size: 16px;color: #8f8f8f;cursor: pointer;"></i>
</el-tooltip>
</template>
<el-button type="primary" round @click="batchImport">导入</el-button> <el-button type="primary" round @click="batchImport">导入</el-button>
<el-button type="primary" round @click="add" v-auth="'/match:管理:报名人员:新增'">新增</el-button> <el-button type="primary" round @click="add" v-auth="'/match:管理:报名人员:新增'">新增</el-button>
<el-button type="primary" round :loading="exporting" @click="exportAll" <el-button type="primary" round :loading="exporting" @click="exportAll"
@ -69,11 +82,13 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" width="270"> <el-table-column label="操作" align="center" width="270">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-auth="'/match:管理:报名人员:编辑'" type="text" @click="edit(scope.row)">编辑</el-button> <template v-if="!scope.row.isDel">
<el-button type="text" @click="del(scope.row)">删除</el-button> <el-button v-auth="'/match:管理:报名人员:编辑'" type="text" @click="edit(scope.row)">编辑</el-button>
<el-button type="text" @click="del(scope.row)">删除</el-button>
</template>
<template v-if="info.releaseType"> <template v-if="info.releaseType">
<el-button v-auth="'/match:管理:报名人员:参赛信息与成绩'" type="text" @click="toInfo(scope.row)">参赛信息与成绩</el-button> <el-button v-auth="'/match:管理:报名人员:参赛信息与成绩'" type="text" @click="toInfo(scope.row)">参赛信息与成绩</el-button>
<el-switch v-auth="'/match:管理:报名人员:禁用'" v-model="scope.row.isDisable" <el-switch v-if="!scope.row.isDel" v-auth="'/match:管理:报名人员:禁用'" v-model="scope.row.isDisable"
:active-text="scope.row.isDisable ? '禁用' : '启用'" :active-value="0" :inactive-value="1" :active-text="scope.row.isDisable ? '禁用' : '启用'" :active-value="0" :inactive-value="1"
style="margin: 0 10px 0 5px" @change="switchOff($event, scope.row, scope.$index)"></el-switch> style="margin: 0 10px 0 5px" @change="switchOff($event, scope.row, scope.$index)"></el-switch>
</template> </template>

@ -0,0 +1,675 @@
<template>
<div>
<el-card shadow="hover" class="m-b-20 head-card">
<div class="flex-between m-b-20">
<el-page-header @back="back" content="成绩管理"></el-page-header>
</div>
</el-card>
<div v-loading="loading">
<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="tool flex-between">
<ul class="filter">
<li>
<label>省份</label>
<el-select v-model="filter.provinceId" filterable clearable placeholder="请选择省份" @change="provinceChange"
@clear="clearProvince">
<el-option v-for="(item, i) in provinces" :key="i" :label="item.provinceName"
:value="item.provinceId"></el-option>
</el-select>
</li>
<li>
<label>城市</label>
<el-select v-model="filter.cityId" filterable clearable placeholder="请选择城市" :disabled="!filter.provinceId"
@change="initData">
<el-option v-for="(item, i) in cities" :key="i" :label="item.cityName" :value="item.cityId"></el-option>
</el-select>
</li>
<li>
<label>学校</label>
<el-select v-model="filter.realSchoolId" clearable filterable placeholder="请选择学校" @change="initData">
<el-option v-for="(item, i) in schools" :key="i" :label="item.schoolName"
:value="item.schoolId"></el-option>
</el-select>
</li>
<li>
<el-input size="small" placeholder="请输入学生姓名" prefix-icon="el-icon-search" v-model="keyword" clearable
style="width: 300px"></el-input>
</li>
</ul>
<div v-if="!active">
<el-button v-if="method == 2" type="primary" @click="batchImport">上传成绩</el-button>
<el-button type="primary" :disabled="!!multipleSelection.find(e => method != 2 && !e.reportId)"
@click="delAllData">批量删除</el-button>
<el-button type="primary" :loading="exporting" @click="exportData">{{ exporting ? '正在导出' : '批量导出'
}}</el-button>
</div>
<div v-else>
<el-button type="primary" :loading="exporting1" @click="exportData1">{{ exporting1 ? '正在导出' : '批量导出'
}}</el-button>
</div>
</div>
<template v-if="!active">
<el-table :data="list" class="table" :key="1" ref="table" stripe header-align="center"
@selection-change="handleSelectionChange" row-key="id">
<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="provinceName" label="省份" min-width="100" align="center"></el-table-column>
<el-table-column prop="cityName" label="城市" min-width="100" align="center"></el-table-column>
<el-table-column prop="schoolName" label="学生账号归属" min-width="100" align="center"></el-table-column>
<el-table-column prop="realSchool" label="学生所在院校" min-width="100" 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">
<template slot-scope="scope">
{{ scope.row.submitTime ? scope.row.score : '--' }}
</template>
</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="状态" width="100" align="center">
<template slot-scope="scope">
{{ scope.row.reportId || method == 2 ? '已参加' : '未参加' }}
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="160">
<template slot-scope="scope">
<el-button v-if="method != 2 && scope.row.reportId" type="text"
@click="show(scope.row)">查看成绩报告</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="id">
<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="provinceName" label="省份" align="center"></el-table-column>
<el-table-column prop="cityName" label="城市" align="center"></el-table-column>
<el-table-column prop="schoolName" label="学生账号归属" align="center"></el-table-column>
<el-table-column prop="realSchool" 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="操作" 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>
</div>
<el-dialog title="批量导入" :visible.sync="importVisible" width="24%" :close-on-click-modal="false"
@close="cancelUpload">
<div style="text-align: center">
<template v-if="!uploadFaild">
<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="upload" name="file" accept=".xls,.xlsx" class="import-file" :before-upload="beforeUpload"
: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" :disabled="uploading" :data="{
competitionId: this.id,
stageId: this.stageId,
systemId: 0
}">
<el-button type="primary" :loading="uploading" class="ml20">上传文件<i
class="el-icon-upload2 el-icon--right"></i></el-button>
</el-upload>
</template>
<template v-else>
<p style="margin: -10px 0 13px;font-size: 14px;color: #e90000;">{{ faildData.tip }}</p>
<p type="primary"
style="margin-bottom: 10px;font-size: 14px;color: #9076FF;text-decoration: underline;cursor: pointer;"
@click="showFaild">部分数据导入失败查看失败原因</p>
</template>
</div>
<span v-if="uploading" slot="footer" class="dialog-footer">
<el-button @click="cancelUpload">停止导入</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
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,
filter: {
provinceId: '',
cityId: '',
realSchoolId: '',
reviewStatus: '',
scoreSortOrder: '',
submitTimeSortOrder: '',
},
provinces: [],
cities: [],
schools: [],
keyword: this.$route.query.keyword || '',
searchTimer: null,
list: [],
multipleSelection: [],
page: +this.$route.query.page || 1,
pageSize: 10,
total: 0,
list1: [],
multipleSelection1: [],
page1: 1,
total1: 0,
avgScore: 0, //
importVisible: false,
uploadList: [],
uploadFaild: false,
uploading: false,
faildData: null,
headers: {
token: sessionStorage.getItem("token")
},
statData: {},
tabs: ['成绩列表', '文件列表'],
active: 0,
loading: false,
exporting: false,
exporting1: false,
};
},
watch: {
keyword: function (val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.$router.push({
path: '/otherArchList',
query: {
...this.$route.query,
keyword: val
}
})
this.initData();
}, 500);
}
},
mounted () {
this.getData()
this.getProvince()
this.getSchool()
},
methods: {
async getData () {
this.loading = true
//
if (this.active) {
const { data } = await this.$post(this.api.cCompetitionStageFileList, {
pageNum: this.page1,
pageSize: this.pageSize,
competitionId: this.id,
stageId: this.stageId,
keyWord: this.keyword,
...this.filter
})
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
this.loading = false
} else { //
const { data, page } = await this.$post(this.api.stageGradeManagementList, {
pageNum: this.page,
pageSize: this.pageSize,
competitionId: this.id,
keyWord: this.keyword,
stageId: this.stageId,
isNakadai: 1,
...this.filter
})
this.loading = false
this.total = page.total
this.list = page.records
this.statData = data
this.avgScore = (+data.avgScore).toFixed(2)
this.method != 2 && this.getChart()
}
},
initData () {
this.page = 1
this.getData()
},
//
async getProvince () {
const { list } = await this.$get(this.api.queryProvince)
this.provinces = list
},
//
clearProvince () {
this.filter.cityId = ''
},
//
provinceChange () {
this.clearProvince()
this.getCity()
this.initData()
},
//
async getCity () {
const id = this.filter.provinceId
if (id) {
const { list } = await this.$get(this.api.queryCity, {
provinceId: id
})
this.cities = list
}
},
//
async getSchool () {
const { list } = await this.$get(this.api.querySchoolData)
this.schools = list
},
//
show (row) {
this.$router.push(`/trialReport?reportId=${row.reportId}`)
},
// ()
async exportData () {
if (this.list.length) {
this.exporting = true
//
if (this.multipleSelection.length) {
const res = await axios.post(this.api.exportExperimentalResultsInBatch, this.multipleSelection, {
headers: this.headers,
responseType: 'blob'
})
util.downloadFileDirect(`赛事成绩.xls`, new Blob([res.data]))
this.exporting = false
} else if (this.list.length) {
const res = await axios.post(this.api.allExperimentalResultsAreDerived, {
pageNum: 1,
pageSize: 10000,
competitionId: this.id,
isNakadai: 1,
stageId: this.stageId,
}, {
headers: this.headers,
responseType: 'blob'
})
util.downloadFileDirect(`赛事成绩.xls`, new Blob([res.data]))
this.exporting = false
}
}
},
// ()
exportData1 () {
this.exporting1 = true
let list = this.list1
if (this.multipleSelection1.length) {
list = this.multipleSelection1
}
Zip('批量导出', list, () => {
this.exporting1 = 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: this.stageId
}).then(res => {
util.successMsg("删除成功");
this.getData();
}).catch(res => {
});
}).catch(() => { });
},
delAllData () { //
const list = this.multipleSelection
this.$confirm(list.length ? '该项目下的所有成绩报告将会删除,是否继续?' : '是否确定删除列表所有成绩数据?', "提示", {
type: "warning"
}).then(async () => {
let ids = []
if (list.length) {
ids = list.map(item => {
return this.method == 2 ? item.scoreId : item.reportId
});
ids = ids.filter(e => e)
}
const data = {
competitionId: this.id,
stageId: this.stageId
}
if (list.length) data.ids = ids
await this.$post(this.api.batchDeleteContestGrade, data)
this.multipleSelection = [];
this.$refs.table.clearSelection();
util.successMsg("删除成功");
this.getData();
}).catch(() => { });
},
handleSelectionChange (val) { //
this.multipleSelection = val;
},
handleCurrentChange (val) { //
this.$router.push({
path: '/otherArchList',
query: {
...this.$route.query,
page: 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", "10-20", "20-30", "30-40", "40-50", "50-60", "60-70", "70-80", "80-90", "90-100"]
},
yAxis: {
name: "人数",
type: "value",
minInterval: 10
},
series: [{
data,
type: "line",
areaStyle: {},
label: {
show: true,
position: 'top'
},
color: ["#8191fd"]
}]
});
},
//
batchImport () {
this.importVisible = true
this.uploadList = []
this.uploadFaild = false
},
//
download () {
axios.get(`${this.api.gradeDownloadExcel}?competitionId=${this.id}&stageId=${this.stageId}`, {
headers: this.headers,
responseType: 'blob'
}).then((res) => {
util.downloadFileDirect('赛事成绩导入模板.xlsx', new Blob([res.data]))
}).catch(res => { })
},
//
handleExceed (files, fileList) {
util.warningMsg(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
)
},
//
showFaild () {
axios.get(`${this.api.performanceExportFailure}?exportCode=${this.faildData.exportCode}&competitionType=${this.faildData.competitionType}`, {
headers: this.headers,
responseType: 'blob'
}).then((res) => {
util.downloadFileDirect(`批量导入成绩管理失败数据导出.xls`, new Blob([res.data]))
}).catch(res => { })
},
uploadSuccess (res) {
this.uploading = false
this.uploadFaild = false
if (res.status === 200) {
this.initData()
const { data } = res
if (data.exportCode) {
this.faildData = data
this.uploadFaild = true
} else {
util.successMsg(data.tip, 3000)
this.importVisible = false
}
} else {
util.errorMsg(res.message || '上传失败,请检查数据')
}
},
uploadError (err, file, fileList) {
this.uploading = false
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
})
},
beforeUpload (file) {
this.uploading = true
},
beforeRemove (file, fileList) {
return this.$confirm(`确定移除 ${file.name}`)
},
handleRemove (file, fileList) {
this.uploadList = fileList
this.uploadFaild = false
},
cancelUpload () {
this.uploading = false
if (this.$refs.upload) this.$refs.upload.abort()
this.keyword = ''
this.initData()
this.importVisible = false
},
// 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()
},
back () {
this.$router.push(this.$store.state.innerReferrer)
}
}
};
</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;
}
}
/deep/.import-file {
.el-progress__text,
.el-progress,
.el-upload-list__item-status-label {
display: none !important;
}
}
</style>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,413 @@
<template>
<div class="wrap">
<el-card shadow="hover" class="m-b-20">
<el-page-header @back="$router.back()" content="查看报告"></el-page-header>
</el-card>
<div class="content" v-loading="loading">
<div class="text-right">
<el-button type="primary" @click="exportPage">导出报告</el-button>
</div>
<h6 class="r-title">标准实验报告</h6>
<div class="info">
<h6 class="l-title">
<img src="@/assets/img/info1.png" alt="">
基本信息
</h6>
<ul :class="['info-list', { edit: editing }]">
<li>
<label>学生姓名</label>
<el-input v-if="editing" v-model="infoData.userName" disabled></el-input>
<span v-else>{{ infoData.userName }}</span>
</li>
<li>
<label>学生学号</label>
<el-input v-if="editing" v-model="infoData.workNumber" disabled></el-input>
<span v-else>{{ infoData.workNumber }}</span>
</li>
<li>
<label>实验时间</label>
<el-input v-if="editing" v-model="infoData.submitTime" disabled></el-input>
<span v-else>{{ infoData.submitTime }}</span>
</li>
<li>
<label>实验成绩</label>
<el-input v-if="editing" v-model="infoData.score" disabled></el-input>
<div v-else class="score-wrap">
<em>{{ infoData.score }}</em>
<img src="@/assets/img/point.png" alt="">
</div>
</li>
<li>
<label>学生班级</label>
<el-input v-if="editing" v-model="infoData.className"></el-input>
<span v-else>{{ infoData.className }}</span>
</li>
<li>
<label>指导老师</label>
<el-input v-if="editing" v-model="infoData.instructor"></el-input>
<span v-else>{{ infoData.instructor }}</span>
</li>
<li>
<label>实验学时</label>
<el-input v-if="editing" v-model="infoData.period"></el-input>
<span v-else>{{ infoData.period }}</span>
</li>
</ul>
<div class="m-b-20">
<h6 class="l-title">
<img src="@/assets/img/report2.png" alt="">
实验项目名称
</h6>
<el-input v-if="editing" v-model="form.projectName" type="textarea"></el-input>
<div v-else class="pre-wrap" v-html="form.projectName"></div>
</div>
<div class="m-b-20">
<h6 class="l-title">
<img src="@/assets/img/report3.png" alt="">
实验目的
</h6>
<div :class="['pre-wrap', { edit: editing }]" v-html="form.purpose"></div>
</div>
<div class="m-b-20">
<h6 class="l-title">
<img src="@/assets/img/report4.png" alt="">
实验数据
</h6>
<el-table :data="expData" class="table" border stripe header-align="center">
<el-table-column type="index" label="序号" align="center" width="60">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="judgmentName" label="判分点" width="270" align="center"></el-table-column>
<el-table-column v-if='project' prop="judgmentName" label="考核点" align="center" width="150">
<template slot-scope="scope">
<div v-for="(item, index) in scope.row.lcRuleRecords" :key="index">
<span>
<span>{{ index + 1 }}. </span>{{ item.name }}
</span>
</div>
</template>
</el-table-column>
<el-table-column prop="ruleAnswer" label="参考答案" style='word-wrap: break-word'>
<template slot-scope="scope">
<div v-if='scope.row.lcRuleRecords'>
<div v-for="(item, index) in scope.row.lcRuleRecords" :key="index">
<span>
<span>{{ index + 1 }}. </span>{{ item.ruleAnswer }}
</span>
</div>
</div>
<div v-else v-html="scope.row.referenceAnswer"></div>
</template>
</el-table-column>
<el-table-column prop="userAnswer" label="学生答案">
<template slot-scope="scope">
<div v-if='scope.row.lcRuleRecords'>
<div v-for="(item, index) in scope.row.lcRuleRecords" :key="index">
<span v-if='item.userAnswer'>
<span>{{ index + 1 }}. </span>{{ item.userAnswer }}
</span>
<span v-else>
<span>{{ index + 1 }}. </span>未填写
</span>
</div>
</div>
<div v-else class="pre-code">{{ scope.row.answer }}</div>
<template v-if="scope.row.runThePictureList">
<img v-for="(img, i) in scope.row.runThePictureList" :key="i" width="200" class="result-pic"
:src="img" alt="">
</template>
</template>
</el-table-column>
<el-table-column prop="quesScore" label="分值" :key="6" width="80" align="center"></el-table-column>
<el-table-column prop="score" label="得分" width="80" align="center"></el-table-column>
</el-table>
</div>
<div class="m-b-20">
<h6 class="l-title">
<img src="@/assets/img/report5.png" alt="">
实验总结与体会
</h6>
<quill v-if="editing" :border="true" v-model="form.summarize" :minHeight="150" :height="150" />
<div v-else class="pre-wrap" v-html="form.summarize"></div>
</div>
</div>
</div>
</div>
</template>
<script>
import util from "@/libs/util";
export default {
data () {
return {
reportId: this.$route.query.reportId,
title: "实验报告",
form: {
className: "",
instructor: "",
period: "",
projectName: "",
summarize: "",
},
infoData: {},
expData: [],
editing: false,
loadIns: null,
loading: false,
project: false,
userScores: []
};
},
mounted () {
this.getData()
},
methods: {
getData () { //
this.loading = true
this.$get(`${this.api.reportDetail}?reportId=${this.reportId}`).then(({ report, userScores }) => {
this.form = report
this.project = this.expData.find(e => e.lcRuleRecords) // lcRuleRecords
let form = this.form;
this.infoData = {
workNumber: form.workNumber,
experimentalClassName: form.experimentalClassName,
instructor: form.instructor,
period: form.period,
laboratory: form.laboratory,
submitTime: form.submitTime,
score: form.score,
className: form.className,
userName: form.userName
}
const { data } = report
// data使
if (!data) {
this.userScores = userScores
this.handleList(userScores)
this.$post(this.api.editExperimentalData, {
reportId,
data: JSON.stringify(userScores)
}).then(res => { }).catch(err => { })
} else {
this.handleList(JSON.parse(data))
}
}).catch(res => {
this.loading = false
})
},
//
handleList (list) {
this.project = list.find(e => e.lcRuleRecords) // lcRuleRecords
if (this.project) {
list.map(e => {
e.assessmentPoint = ''
e.referenceAnswer = ''
e.answer = ''
e.lcRuleRecords && e.lcRuleRecords.map((n, i) => {
e.assessmentPoint += `${i + 1}.${n.name}`
e.referenceAnswer += `${i + 1}.${n.ruleAnswer}`
e.answer += `${i + 1}.${n.userAnswer}`
})
})
} else { // pythonuserScores
list.forEach(e => {
const item = this.userScores.find(n => n.judgmentId == e.judgmentId)
if (item && item.runThePictureList) e.runThePictureList = item.runThePictureList
})
}
this.expData = list
this.loading = false
},
exportPage () {
const form = Object.assign(this.form, this.infoData)
const list = JSON.parse(JSON.stringify(this.expData))
list.map((e, i) => {
const item = this.userScores.find(n => n.judgmentId == e.judgmentId)
if (item && item.runThePicture) e.runThePicture = item.runThePicture
if (item && item.runThePictureList) e.runThePictureList = item.runThePictureList
e.id = i + 1
// if (e.referenceAnswer && typeof e.referenceAnswer === 'string') e.referenceAnswer = e.referenceAnswer.replace(/<[^>]+>/g, '').replace(/(&nbsp;|&amp;|%s)/g, '').replace(/>/g, '&gt;').replace(/</g, '&lt;')
if (e.answer && typeof e.answer === 'string') e.answer = e.answer.replace(/<[^>]+>/g, '').replace(/(&nbsp;|&amp;|%s)/g, '').replace(/>/g, '&gt;').replace(/</g, '&lt;')
})
for (const i in form) {
if (form[i] && typeof form[i] === 'string') form[i] = form[i].replace(/<[^>]+>/g, '')
}
form.purpose = form.purpose.replace(/<[^>]+>/g, '')
this.$post(this.project ? this.api.exportBankExperimentReport : this.api.exportLabReport, {
...form,
experimentalData: list
}).then(res => {
console.log(res)
util.downloadFileDirect(`实验报告.docx`, new Blob([res]))
}).catch(res => { })
},
}
};
</script>
<style lang="scss" scoped>
.wrap {
padding: 12px 300px 20px;
}
.pre-code {
white-space: pre-wrap;
}
.text-right {
text-align: right;
}
code,
kbd,
samp {
font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', arial, STHeiTi, sans-serif;
word-wrap: break-word;
white-space: pre-wrap;
}
/deep/ pre {
white-space: pre-wrap;
/* css-3 */
white-space: -moz-pre-wrap;
/* Mozilla, since 1999 */
white-space: pre-wrap;
/* Opera 4-6 */
white-space: -o-pre-wrap;
/* Opera 7 */
word-wrap: break-word;
/* Internet Explorer 5.5+ */
word-break: break-all;
overflow: hidden;
font-size: 12px;
font-weight: 400;
font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', arial, STHeiTi, sans-serif;
}
.content {
padding: 16px 40px;
background: #fff;
.r-title {
margin-bottom: 40px;
font-size: 24px;
text-align: center;
color: #333;
}
.info {
padding: 20px 16px;
border: 1px solid #e1e6f2;
}
.l-title {
display: flex;
align-items: center;
padding: 5px 8px;
margin-bottom: 12px;
font-size: 14px;
color: #333;
background-color: #f7f5ff;
}
.info-list {
display: flex;
flex-wrap: wrap;
padding: 10px 0 0 20px;
li {
display: inline-flex;
width: 23%;
padding: 0 10px;
margin-bottom: 34px;
}
&.edit {
li {
align-items: center;
}
}
label {
font-size: 14px;
color: #333;
white-space: nowrap;
}
span {
min-width: 150px;
padding: 0 10px 3px;
border-bottom: 1px solid #e1e6f2;
}
/deep/.el-input {
width: 174px;
}
}
.score-wrap {
position: relative;
min-width: 150px;
border-bottom: 1px solid #e1e6f2;
em {
position: absolute;
top: -12px;
left: 30px;
font-family: din;
font-size: 30px;
font-weight: 600;
color: #0b1d30;
}
img {
position: absolute;
bottom: -15px;
left: 0;
}
}
/deep/.el-textarea .el-textarea__inner,
.pre-wrap {
min-height: 72px;
padding: 10px 16px;
font-size: 14px;
color: #333;
&.edit {
color: #abb3c6;
border: 1px solid #cacfdb;
border-radius: 4px;
background-color: #f6f7f9;
}
}
/deep/ .table th {
background-color: #e5dfff !important;
.cell {
line-height: 35px;
color: #fff;
}
}
}
.result-pic {
margin: 10px 0;
}
@media (max-width: 1650px) {
.wrap {
padding: 12px 200px 20px;
}
}
@media (max-width: 1430px) {
.wrap {
padding: 12px 100px 20px;
}
}
</style>

@ -602,15 +602,15 @@
<template slot="header" slot-scope="scope"> <template slot="header" slot-scope="scope">
<template v-if="viewDisabled || isEdit">使用期限</template> <template v-if="viewDisabled || isEdit">使用期限</template>
<template v-else> <template v-else>
<el-input class="batch-time" :disabled="viewDisabled || isEdit" maxlength="4" <el-input class="batch-time" :disabled="viewDisabled || isEdit" maxlength="4"
@change="batchDeadlineChange(2)" @change="batchDeadlineChange(2)"
@input="productProps[2].deadline = productProps[2].deadline.replace(/[^0-9.]/g, '')" @input="productProps[2].deadline = productProps[2].deadline.replace(/[^0-9.]/g, '')"
v-model="productProps[2].deadline" placeholder="批量输入时间" /> v-model="productProps[2].deadline" placeholder="批量输入时间" />
<el-select class="batch-unit" v-model="productProps[2].unit" :disabled="viewDisabled || isEdit" <el-select class="batch-unit" v-model="productProps[2].unit" :disabled="viewDisabled || isEdit"
placeholder="请选择" @change="batchUnitChange(2)"> placeholder="请选择" @change="batchUnitChange(2)">
<el-option v-for="(item, i) in units" :key="i" :label="item.name" :value="item.id"></el-option> <el-option v-for="(item, i) in units" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select> </el-select>
</template> </template>
</template> </template>
<template slot-scope="scope"> <template slot-scope="scope">
@ -741,15 +741,15 @@
<template slot="header" slot-scope="scope"> <template slot="header" slot-scope="scope">
<template v-if="viewDisabled || isEdit">使用期限</template> <template v-if="viewDisabled || isEdit">使用期限</template>
<template v-else> <template v-else>
<el-input class="batch-time" :disabled="viewDisabled || isEdit" maxlength="4" <el-input class="batch-time" :disabled="viewDisabled || isEdit" maxlength="4"
@change="batchDeadlineChange(3)" @change="batchDeadlineChange(3)"
@input="productProps[3].deadline = productProps[3].deadline.replace(/[^0-9.]/g, '')" @input="productProps[3].deadline = productProps[3].deadline.replace(/[^0-9.]/g, '')"
v-model="productProps[3].deadline" placeholder="批量输入时间" /> v-model="productProps[3].deadline" placeholder="批量输入时间" />
<el-select class="batch-unit" v-model="productProps[3].unit" :disabled="viewDisabled || isEdit" <el-select class="batch-unit" v-model="productProps[3].unit" :disabled="viewDisabled || isEdit"
placeholder="请选择" @change="batchUnitChange(3)"> placeholder="请选择" @change="batchUnitChange(3)">
<el-option v-for="(item, i) in units" :key="i" :label="item.name" :value="item.id"></el-option> <el-option v-for="(item, i) in units" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select> </el-select>
</template> </template>
</template> </template>
<template slot-scope="scope"> <template slot-scope="scope">
@ -888,15 +888,15 @@
<template slot="header" slot-scope="scope"> <template slot="header" slot-scope="scope">
<template v-if="viewDisabled || isEdit">使用期限</template> <template v-if="viewDisabled || isEdit">使用期限</template>
<template v-else> <template v-else>
<el-input class="batch-time" :disabled="viewDisabled || isEdit" maxlength="4" <el-input class="batch-time" :disabled="viewDisabled || isEdit" maxlength="4"
@change="batchDeadlineChange(5)" @change="batchDeadlineChange(5)"
@input="productProps[5].deadline = productProps[5].deadline.replace(/[^0-9.]/g, '')" @input="productProps[5].deadline = productProps[5].deadline.replace(/[^0-9.]/g, '')"
v-model="productProps[5].deadline" placeholder="批量输入时间" /> v-model="productProps[5].deadline" placeholder="批量输入时间" />
<el-select class="batch-unit" v-model="productProps[5].unit" :disabled="viewDisabled || isEdit" <el-select class="batch-unit" v-model="productProps[5].unit" :disabled="viewDisabled || isEdit"
placeholder="请选择" @change="batchUnitChange(5)"> placeholder="请选择" @change="batchUnitChange(5)">
<el-option v-for="(item, i) in units" :key="i" :label="item.name" :value="item.id"></el-option> <el-option v-for="(item, i) in units" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select> </el-select>
</template> </template>
</template> </template>
<template slot-scope="scope"> <template slot-scope="scope">
@ -1906,7 +1906,8 @@ export default {
}, },
// orderRepeatid // orderRepeatid
handleOrderRepeat (id) { handleOrderRepeat (id) {
this.orderRepeat.includes(id) && this.orderRepeat.splice(this.orderRepeat.findIndex(e => e == id), 1) const i = this.orderRepeat.findIndex(e => e == id)
i !== -1 && this.orderRepeat.splice(i, 1)
}, },
/* 处理0开头的期限 */ /* 处理0开头的期限 */
zero (e, row) { zero (e, row) {
@ -1935,6 +1936,12 @@ export default {
this.getSettlemennt() this.getSettlemennt()
}); });
this.$forceUpdate(); this.$forceUpdate();
//
this.productProps.map(e => {
this[e.name].map(n => {
this.deadLine(n.periodOfUse, n, n.options, 1)
})
})
} }
}, },
// //
@ -1965,7 +1972,7 @@ export default {
// if (this.renewDisabled && this.coursePermissions.length === 1) { // if (this.renewDisabled && this.coursePermissions.length === 1) {
// return this.$message.warning(""); // return this.$message.warning("");
// } else { // } else {
this.handleOrderRepeat(row.dataOrCourseId) this.handleOrderRepeat(row.mallId)
this.coursePermissions.splice(index, 1); this.coursePermissions.splice(index, 1);
// } // }
}); });
@ -1978,7 +1985,7 @@ export default {
// if (this.renewDisabled && this.theoryCourseList.length === 1) { // if (this.renewDisabled && this.theoryCourseList.length === 1) {
// return this.$message.warning(""); // return this.$message.warning("");
// } else { // } else {
this.handleOrderRepeat(row.dataOrCourseId) this.handleOrderRepeat(row.mallId)
this.theoryCourseList.splice(index, 1); this.theoryCourseList.splice(index, 1);
// } // }
}); });
@ -1992,7 +1999,7 @@ export default {
// if (this.renewDisabled && this.dataPlatformPermissions.length === 1) { // if (this.renewDisabled && this.dataPlatformPermissions.length === 1) {
// return this.$message.warning(""); // return this.$message.warning("");
// } else { // } else {
this.handleOrderRepeat(row.dataOrCourseId) this.handleOrderRepeat(row.mallId)
this.dataPlatformPermissions.splice(index, 1); this.dataPlatformPermissions.splice(index, 1);
// } // }
}); });
@ -2006,7 +2013,7 @@ export default {
// if (this.renewDisabled && this.valuePermissions.length === 1) { // if (this.renewDisabled && this.valuePermissions.length === 1) {
// return this.$message.warning(""); // return this.$message.warning("");
// } else { // } else {
this.handleOrderRepeat(row.dataOrCourseId) this.handleOrderRepeat(row.mallId)
this.valuePermissions.splice(index, 1); this.valuePermissions.splice(index, 1);
// } // }
}); });
@ -2165,7 +2172,7 @@ export default {
// if (this.renewDisabled && this.practicalCourses.length === 1) { // if (this.renewDisabled && this.practicalCourses.length === 1) {
// return this.$message.warning(""); // return this.$message.warning("");
// } else { // } else {
this.handleOrderRepeat(row.dataOrCourseId) this.handleOrderRepeat(row.mallId)
this.practicalCourses.splice(index, 1); this.practicalCourses.splice(index, 1);
// } // }
}); });
@ -2179,7 +2186,7 @@ export default {
if (this.renewDisabled && this.expTools.length === 1) { if (this.renewDisabled && this.expTools.length === 1) {
return this.$message.warning("续费至少保留一条产品信息"); return this.$message.warning("续费至少保留一条产品信息");
} else { } else {
this.handleOrderRepeat(row.dataOrCourseId) this.handleOrderRepeat(row.mallId)
this.expTools.splice(index, 1); this.expTools.splice(index, 1);
} }
}); });

File diff suppressed because it is too large Load Diff

@ -0,0 +1,50 @@
<template>
<div>
<iframe :src="url" frameborder="0" width="100%"></iframe>
</div>
</template>
<script>
import Setting from '@/setting'
export default {
data () {
return {
url: ''
};
},
mounted () {
const token = sessionStorage.getItem('token')
const cache = localStorage.getItem('reviewPath') // localStorage
let url = `${location.origin}/reviewCenter/`
if (Setting.isDev) url = `http://192.168.31.125:8099/`
if (cache) {
url += '#' + this.replaceParam(cache, Date.now())
} else {
url += `#/myReview?nakadai=1${Setting.isDev ? `&token=${token}` : ''}&v=${Date.now()}`
}
console.log("🚀 ~ mounted ~ url:", url)
localStorage.setItem('review_token', token)
this.url = url
},
methods: {
replaceParam (url, newVValue) {
const vParamRegex = /v=[^&]+/g
let newUrl = url.replace(vParamRegex, `v=${newVValue}`)
const [baseUrl, hash] = newUrl.split('#');
if (hash) {
newUrl = `${baseUrl}#${hash.replace(vParamRegex, `v=${newVValue}`)}`
}
return newUrl
}
}
};
</script>
<style lang="scss" scoped>
iframe {
height: calc(100vh - 167px);
}
</style>

@ -161,7 +161,7 @@ export default {
// //
toBackstage (row) { toBackstage (row) {
this.setReferrer() this.setReferrer()
if (row.systemId == 19) { if (row.systemId == 19 || row.systemId == 30) {
location.href = `${Setting.sandPath}/#/config?token=${sessionStorage.getItem('token')}&admin=1&referrer=${encodeURIComponent(location.href)}` location.href = `${Setting.sandPath}/#/config?token=${sessionStorage.getItem('token')}&admin=1&referrer=${encodeURIComponent(location.href)}`
} else { } else {
this.$router.push(`/backstage?systemId=${row.systemId}&show=1&name=${row.systemName}`) this.$router.push(`/backstage?systemId=${row.systemId}&show=1&name=${row.systemName}`)

@ -1,28 +1,20 @@
<template> <template>
<div ref="main" <div ref="main" class="main" v-loading="loading">
class="main"
v-loading="loading">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="24"> <el-col :span="24">
<el-card shadow="hover" <el-card shadow="hover" class="mgb20">
class="mgb20">
<div class="flex-between"> <div class="flex-between">
<el-page-header @back="back" <el-page-header @back="back" 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"
:loading="submiting === 0" @click="handleSubmit(0, projectManage.isOpen = 1, projectManage.ztOpen = 1)">保存为草稿
@click="handleSubmit(0,projectManage.isOpen=1,projectManage.ztOpen = 1)">保存为草稿
</el-button> </el-button>
<el-button type="primary" <el-button type="primary" :loading="submiting === 1" @click="handleSubmit(1)">确定并发布</el-button>
:loading="submiting === 1"
@click="handleSubmit(1)">确定并发布</el-button>
</div> </div>
</div> </div>
</el-card> </el-card>
<el-card shadow="hover" <el-card shadow="hover" class="mgb20">
class="mgb20">
<div class="flex-center mgb20"> <div class="flex-center mgb20">
<p class="addhr_tag"></p> <p class="addhr_tag"></p>
<span>课程信息</span> <span>课程信息</span>
@ -33,26 +25,18 @@
<el-form label-width="80px"> <el-form label-width="80px">
<div style="display: flex"> <div style="display: flex">
<el-form-item label="项目名称"> <el-form-item label="项目名称">
<el-input :disabled="isDetail" <el-input :disabled="isDetail" v-model.trim="projectManage.projectName" placeholder="20个字符以内"
v-model.trim="projectManage.projectName" @blur="projectNameExistis"></el-input>
placeholder="20个字符以内"
@blur="projectNameExistis"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="备注"> <el-form-item label="备注">
<el-input v-model.trim="projectManage.remark" <el-input v-model.trim="projectManage.remark" placeholder="20个字符以内"></el-input>
placeholder="20个字符以内"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="项目用途"> <el-form-item label="项目用途">
<el-select :disabled="isDetail" <el-select :disabled="isDetail" v-model="projectManage.permissions" placeholder="请选择"
v-model="projectManage.permissions" @change="permissionChange">
placeholder="请选择" <el-option label="练习" :value="0"></el-option>
@change="permissionChange"> <el-option label="考核" :value="1"></el-option>
<el-option label="练习" <el-option label="竞赛" :value="2"></el-option>
:value="0"></el-option>
<el-option label="考核"
:value="1"></el-option>
<el-option label="竞赛"
:value="2"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</div> </div>
@ -60,8 +44,7 @@
</div> </div>
</el-card> </el-card>
<el-card shadow="hover" <el-card shadow="hover" class="mgb20">
class="mgb20">
<div class="flex-center mgb20"> <div class="flex-center mgb20">
<p class="addhr_tag"></p> <p class="addhr_tag"></p>
<span>实验目标</span> <span>实验目标</span>
@ -70,20 +53,14 @@
<div> <div>
<el-form label-width="0"> <el-form label-width="0">
<el-form-item> <el-form-item>
<quill :border="true" <quill :border="true" :readonly="isDetail" v-model="projectManage.experimentTarget"
:readonly="isDetail" :type.sync="projectManage.experimentTargetType" radio :minHeight="150" :height="150" />
v-model="projectManage.experimentTarget"
:type.sync="projectManage.experimentTargetType"
radio
:minHeight="150"
:height="150" />
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
</el-card> </el-card>
<el-card shadow="hover" <el-card shadow="hover" class="mgb20">
class="mgb20">
<div class="flex-center mgb20"> <div class="flex-center mgb20">
<p class="addhr_tag"></p> <p class="addhr_tag"></p>
<span>项目背景</span> <span>项目背景</span>
@ -92,30 +69,22 @@
<div> <div>
<el-form label-width="0"> <el-form label-width="0">
<el-form-item> <el-form-item>
<quill :border="true" <quill :border="true" :readonly="isDetail" v-model="projectManage.experimentDescription"
:readonly="isDetail" :type.sync="projectManage.experimentDescriptionType" radio :minHeight="150" :height="150"
v-model="projectManage.experimentDescription" :index="1" />
:type.sync="projectManage.experimentDescriptionType"
radio
:minHeight="150"
:height="150"
:index="1" />
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
</el-card> </el-card>
<el-card shadow="hover" <el-card shadow="hover" class="mgb20">
class="mgb20">
<div class="flex-between mgb20"> <div class="flex-between mgb20">
<div class="flex-center"> <div class="flex-center">
<p class="addhr_tag"></p> <p class="addhr_tag"></p>
<span>实验任务</span> <span>实验任务</span>
</div> </div>
<div> <div>
<el-button :disabled="isDetail" <el-button :disabled="isDetail" type="primary" @click="toJudgePoint('home')">进入判分点
type="primary"
@click="toJudgePoint('home')">进入判分点
</el-button> </el-button>
</div> </div>
</div> </div>
@ -123,120 +92,67 @@
<div class="mgb20 flex-between"> <div class="mgb20 flex-between">
<div class="flex-center"> <div class="flex-center">
<div class="m-r-20" <div class="m-r-20" style="color: #f00">项目总分值100</div>
style="color: #f00">项目总分值100</div>
<!-- <div>权重&emsp;<div class="dib"><el-input></el-input></div></div> --> <!-- <div>权重&emsp;<div class="dib"><el-input></el-input></div></div> -->
</div> </div>
<div> <div>
<el-button :disabled="isDetail" <el-button :disabled="isDetail" class="m-r-20" type="text" @click="avgDistributionScore">
class="m-r-20"
type="text"
@click="avgDistributionScore">
平均分配分值 平均分配分值
</el-button> </el-button>
<el-button :disabled="isDetail" <el-button :disabled="isDetail" class="m-r-20" type="text" @click="manualDistributionScore">
class="m-r-20"
type="text"
@click="manualDistributionScore">
手动分配分值 手动分配分值
</el-button> </el-button>
<span>(待分配分值: {{ handDistributionScore }}/100)</span> <span>(待分配分值: {{ handDistributionScore }}/100)</span>
</div> </div>
</div> </div>
<el-button :disabled="isDetail" <el-button :disabled="isDetail" type="primary" icon="el-icon-plus" round @click="handleAddJudgment"
type="primary" style="margin-bottom: 10px">判分点
icon="el-icon-plus"
round
@click="handleAddJudgment"
style="margin-bottom: 10px">判分点
</el-button> </el-button>
<el-button :disabled="isDetail" <el-button :disabled="isDetail" type="primary" icon="el-icon-delete" round @click="batchDeleteProjectJudgment"
type="primary" style="margin-bottom: 10px">批量删除
icon="el-icon-delete"
round
@click="batchDeleteProjectJudgment"
style="margin-bottom: 10px">批量删除
</el-button> </el-button>
<div class="draggable"> <div class="draggable">
<u-table ref="projectJudgementTable" <el-table ref="projectJudgementTable" :data="projectJudgmentData" class="table" stripe header-align="center"
:data="projectJudgmentData" :use-virtual="isLc" :max-height="600" :row-height="60" :border="false"
class="table" @selection-change="handleSelectionProjectJudgment" row-key="judgmentId" v-loading="listLoading">
stripe <el-table-column type="selection" width="55" align="center"></el-table-column>
header-align="center" <el-table-column prop="sort" label="序号" width="80" align="center">
:use-virtual="isLc"
:max-height="600"
:row-height="60"
:border="false"
@selection-change="handleSelectionProjectJudgment"
row-key="judgmentId"
v-loading="listLoading">
<u-table-column type="selection"
width="55"
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>
</u-table-column> </el-table-column>
<u-table-column prop="name" <el-table-column prop="name" label="判分指标" align="center" show-overflow-tooltip
label="判分指标" min-width="140"></el-table-column>
align="center" <el-table-column prop="name" label="判分点名称" align="center" show-overflow-tooltip
show-overflow-tooltip min-width="140"></el-table-column>
min-width="140"></u-table-column> <el-table-column label="实验要求" align="center" width="600">
<u-table-column prop="name"
label="判分点名称"
align="center"
show-overflow-tooltip
min-width="140"></u-table-column>
<u-table-column label="实验要求"
align="center"
width="600">
<template slot-scope="scope"> <template slot-scope="scope">
<quill :readonly="true" <quill :readonly="true" elseRead="true" v-model="scope.row.experimentalRequirements" :index="2" />
elseRead="true"
v-model="scope.row.experimentalRequirements"
:index="2" />
</template> </template>
</u-table-column> </el-table-column>
<u-table-column prop="score" <el-table-column prop="score" label="分数" align="center" width="120">
label="分数"
align="center"
width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<el-input :disabled="isDetail" <el-input :disabled="isDetail" :key="scope.$index" type="number" step="0.1"
:key="scope.$index" v-model.trim="scope.row.score"></el-input>
type="number"
step="0.1"
v-model.trim="scope.row.score"></el-input>
<!-- <!--
@input="scoreChange(scope.row, scope.$index)" --> @input="scoreChange(scope.row, scope.$index)" -->
</template> </template>
</u-table-column> </el-table-column>
<u-table-column label="操作" <el-table-column label="操作" width="140" align="center">
width="140"
align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button :disabled="isDetail" <el-button :disabled="isDetail" type="text" style="margin-right: 10px"
type="text" @click="toJudgePoint('edit', scope.row)">自定义</el-button>
style="margin-right: 10px" <el-button :disabled="isDetail" type="text" @click="delJudgePoint(scope.$index)">
@click="toJudgePoint('edit', scope.row)">自定义</el-button>
<el-button :disabled="isDetail"
type="text"
@click="delJudgePoint(scope.$index)">
删除 删除
</el-button> </el-button>
</template> </template>
</u-table-column> </el-table-column>
</u-table> </el-table>
</div> </div>
</el-card> </el-card>
<el-card shadow="hover" <el-card shadow="hover" class="mgb20">
class="mgb20">
<div class="flex-between mgb20"> <div class="flex-between mgb20">
<div class="flex-center"> <div class="flex-center">
<p class="addhr_tag"></p> <p class="addhr_tag"></p>
@ -244,25 +160,16 @@
</div> </div>
<div> <div>
启用 启用
<el-switch :disabled="isDetail" <el-switch :disabled="isDetail" :active-value="0" :inactive-value="1"
:active-value="0" v-model="projectManage.hintOpen"></el-switch>
:inactive-value="1"
v-model="projectManage.hintOpen"></el-switch>
</div> </div>
</div> </div>
<div class="border-b-dashed"></div> <div class="border-b-dashed"></div>
<div> <div>
<el-form label-width="0"> <el-form label-width="0">
<el-form-item prop="tips" <el-form-item prop="tips" label="">
label=""> <quill :border="true" :readonly="isDetail" v-model="projectManage.experimentHint"
<quill :border="true" :type.sync="projectManage.experimentHintType" radio :minHeight="150" :height="400" :index="3" />
:readonly="isDetail"
v-model="projectManage.experimentHint"
:type.sync="projectManage.experimentHintType"
radio
:minHeight="150"
:height="400"
:index="3" />
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
@ -271,62 +178,34 @@
</el-row> </el-row>
<!--选择判分点对话框--> <!--选择判分点对话框-->
<el-dialog title="添加判分点" <el-dialog title="添加判分点" :visible.sync="dialogVisible" width="40%" :close-on-click-modal="false"
:visible.sync="dialogVisible" @close="closeJudgment">
width="40%"
:close-on-click-modal="false"
@close="closeJudgment">
<div class="text-right mgb10"> <div class="text-right mgb10">
<div> <div>
<el-input placeholder="请输入需要查找的判分点" <el-input placeholder="请输入需要查找的判分点" prefix-icon="el-icon-search" v-model.trim="judgementpointsquery"
prefix-icon="el-icon-search" clearable></el-input>
v-model.trim="judgementpointsquery"
clearable></el-input>
</div> </div>
</div> </div>
<u-table v-loading="visibleLoading" <el-table v-loading="visibleLoading" :data="judgementData" ref="judgementTable" class="table" stripe
:data="judgementData" header-align="center" use-virtual :row-height="45" :max-height="400" :border="false"
ref="judgementTable" @selection-change="handleSelectionJudgment" :row-key="rowKey">
class="table" <el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
stripe <el-table-column prop="id" label="序号" align="center" width="100">
header-align="center"
use-virtual
:row-height="45"
:max-height="400"
:border="false"
@selection-change="handleSelectionJudgment"
:row-key="rowKey">
<u-table-column type="selection"
width="55"
align="center"
:reserve-selection="true"></u-table-column>
<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>
</u-table-column> </el-table-column>
<u-table-column prop="name" <el-table-column prop="name" label="判分点名称" align="center"></el-table-column>
label="判分点名称" <el-table-column label="操作" align="center" width="100">
align="center"></u-table-column>
<u-table-column label="操作"
align="center"
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>
</u-table-column> </el-table-column>
</u-table> </el-table>
<div slot="footer" <div slot="footer" class="dialog-footer">
class="dialog-footer">
<el-button @click="closeJudgment"> </el-button> <el-button @click="closeJudgment"> </el-button>
<el-button type="primary" <el-button type="primary" :loading="savingJud" @click="saveJudgment"> </el-button>
:loading="savingJud"
@click="saveJudgment"> </el-button>
</div> </div>
</el-dialog> </el-dialog>
</div> </div>
@ -440,6 +319,8 @@ export default {
if (this.$route.query.projectId) { if (this.$route.query.projectId) {
this.projectId = this.$route.query.projectId; this.projectId = this.$route.query.projectId;
this.getInfoData(); this.getInfoData();
} else {
this.rowDrop()
} }
// //
if (JSON.stringify(this.projectFields) != "{}") { if (JSON.stringify(this.projectFields) != "{}") {
@ -447,7 +328,6 @@ export default {
this.projectManage = projectManage; this.projectManage = projectManage;
this.projectJudgmentData = projectJudgmentData; this.projectJudgmentData = projectJudgmentData;
} }
this.rowDrop();
this.$refs.main.scrollTop = 0; this.$refs.main.scrollTop = 0;
}, },
beforeDestroy () { beforeDestroy () {
@ -482,6 +362,7 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
this.updateTime = 0 this.updateTime = 0
this.$refs.main.scrollTop = 0; this.$refs.main.scrollTop = 0;
this.rowDrop();
}); });
}).catch(err => { }).catch(err => {
this.loading = false this.loading = false
@ -785,24 +666,16 @@ export default {
// //
rowDrop () { rowDrop () {
// //
const tbody = document.querySelector(".draggable .el-table__body-wrapper tbody"); const tbody = document.querySelector(".el-table__body tbody");
const _this = this; const that = this;
Sortable.create(tbody, { this.$refs.projectJudgementTable && Sortable.create(tbody, {
// //
draggable: ".draggable .el-table__row", // draggable: ".draggable .el-table__row",
onEnd ({ newIndex, oldIndex }) { onUpdate ({ newIndex, oldIndex }) {
// : vue$nextTick console.log("🚀 ~ onEnd ~ newIndex, oldIndex:", newIndex, oldIndex)
_this.projectJudgmentData.splice(newIndex, 0, _this.projectJudgmentData.splice(oldIndex, 1)[0]); if (newIndex == oldIndex) return false
let newArray = _this.projectJudgmentData.slice(0); const currentRow = that.projectJudgmentData.splice(oldIndex, 1)[0]
_this.projectJudgmentData = []; that.projectJudgmentData.splice(newIndex, 0, currentRow)
_this.$nextTick(function () {
newArray.forEach((e, i) => {
_this.$set(e, "sort", i + 1);//
_this.$set(e, "name", e.name + "?");
_this.$set(e, "name", e.name.slice(0, e.name.length - 1)); //
});
_this.projectJudgmentData = newArray;
});
} }
}); });
}, },
@ -911,13 +784,14 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
/deep/ .readonly .ql-toolbar { /deep/ .readonly .ql-toolbar {
height: 0; height: 0;
padding: 0; padding: 0;
border-bottom: 0; border-bottom: 0;
} }
.main { .main {
overflow: auto; overflow: auto;
overflow-x: hidden; overflow-x: hidden;
height: calc(100vh - 161px); height: calc(100vh - 161px);
} }
</style> </style>

File diff suppressed because it is too large Load Diff

@ -4,8 +4,7 @@
<div class="side"> <div class="side">
<div class="m-b-20"> <div class="m-b-20">
<h6 class="p-title">后台员工账号</h6> <h6 class="p-title">后台员工账号</h6>
<el-radio-group v-model="studentType" <el-radio-group v-model="studentType" @change="changeType">
@change="changeType">
<div class="m-b-20"> <div class="m-b-20">
<el-radio :label="1">所有员工</el-radio> <el-radio :label="1">所有员工</el-radio>
</div> </div>
@ -17,40 +16,25 @@
<el-divider></el-divider> <el-divider></el-divider>
<div> <div>
<div class="flex-between"> <div class="flex-between">
<h6 class="p-title" <h6 class="p-title" style="margin-bottom: 0">组织架构</h6>
style="margin-bottom: 0">组织架构</h6> <el-button type="text" @click="addOrg" v-auth="'/system:后台账号:新增部门'">添加</el-button>
<el-button type="text"
@click="addOrg"
v-auth="'/system:后台账号:新增部门'">添加</el-button>
</div> </div>
<div style="overflow: auto"> <div style="overflow: auto">
<el-tree :data="orgList" <el-tree :data="orgList" default-expand-all ref="orgTree" node-key="id" highlight-current
default-expand-all :expand-on-click-node="false" @node-click="handleNodeClick"
ref="orgTree" :props="{ children: 'children', label: 'organizationName', isLeaf: 'leaf' }">
node-key="id" <span class="custom-tree-node" slot-scope="{ node, data }">
highlight-current
:expand-on-click-node="false"
@node-click="handleNodeClick"
:props="{children: 'children', label: 'organizationName', isLeaf: 'leaf'}">
<span class="custom-tree-node"
slot-scope="{ node, data }">
<span class="org-name">{{ node.label }}</span> <span class="org-name">{{ node.label }}</span>
<span> <span>
<el-button v-auth="'/system:后台账号:新增部门'" <el-button v-auth="'/system:后台账号:新增部门'" type="text" icon="el-icon-circle-plus-outline"
type="text" @click="() => addOrg(node, data)">
icon="el-icon-circle-plus-outline"
@click="() => addOrg(node, data)">
</el-button> </el-button>
<el-button v-auth="'/system:后台账号:编辑部门'" <el-button v-auth="'/system:后台账号:编辑部门'" type="text" icon="el-icon-edit-outline"
type="text" @click="() => editOrg(node, data)">
icon="el-icon-edit-outline"
@click="() => editOrg(node, data)">
</el-button> </el-button>
<el-button v-auth="'/system:后台账号:删除部门'" <el-button v-auth="'/system:后台账号:删除部门'" type="text" icon="el-icon-delete"
type="text" @click="() => delOrg(node, data)">
icon="el-icon-delete"
@click="() => delOrg(node, data)">
</el-button> </el-button>
</span> </span>
</span> </span>
@ -58,36 +42,22 @@
</div> </div>
</div> </div>
<el-dialog :title="orgForm.id ? '编辑' : '新增' + '部门'" <el-dialog :title="orgForm.id ? '编辑' : '新增' + '部门'" :visible.sync="orgVisible" :close-on-click-modal="false"
:visible.sync="orgVisible" width="50%">
:close-on-click-modal="false" <el-form v-if="orgVisible" ref="orgForm" :model="orgForm" :rules="orgRules" label-width="100px">
width="50%"> <el-form-item label="部门名称" prop="organizationName">
<el-form v-if="orgVisible" <el-input v-model.trim="orgForm.organizationName" placeholder="请输入"></el-input>
ref="orgForm"
:model="orgForm"
:rules="orgRules"
label-width="100px">
<el-form-item label="部门名称"
prop="organizationName">
<el-input v-model.trim="orgForm.organizationName"
placeholder="请输入"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="上级部门"> <el-form-item label="上级部门">
<span v-if="orgForm.parentName">{{ orgForm.parentName }}</span> <span v-if="orgForm.parentName">{{ orgForm.parentName }}</span>
<el-cascader v-else <el-cascader v-else :options="orgListDia" v-model="cascaderValue" :props="cascaderProps" clearable
:options="orgListDia" style="width: 100%">
v-model="cascaderValue"
:props="cascaderProps"
clearable
style="width: 100%">
</el-cascader> </el-cascader>
</el-form-item> </el-form-item>
</el-form> </el-form>
<span slot="footer" <span slot="footer" class="dialog-footer">
class="dialog-footer">
<el-button @click="closeOrg"> </el-button> <el-button @click="closeOrg"> </el-button>
<el-button type="primary" <el-button type="primary" @click="orgSubmit"> </el-button>
@click="orgSubmit"> </el-button>
</span> </span>
</el-dialog> </el-dialog>
</div> </div>
@ -97,195 +67,96 @@
<div class="tool"> <div class="tool">
<ul class="filter"> <ul class="filter">
<li> <li>
<el-input style="width: 250px;" <el-input style="width: 250px;" placeholder="请输入员工姓名/手机号" prefix-icon="el-icon-search" v-model="keyWord"
placeholder="请输入员工姓名/手机号" clearable></el-input>
prefix-icon="el-icon-search"
v-model="keyWord"
clearable></el-input>
</li> </li>
</ul> </ul>
<div> <div>
<el-button type="primary" <el-button type="primary" @click="addStaff" v-auth="'/system:后台账号:新增员工'">新增员工</el-button>
@click="addStaff" <el-button type="primary" @click="batchImport" v-auth="'/system:后台账号:批量导入'">批量导入</el-button>
v-auth="'/system:后台账号:新增员工'">新增员工</el-button>
<el-button type="primary"
@click="batchImport"
v-auth="'/system:后台账号:批量导入'">批量导入</el-button>
</div> </div>
</div> </div>
<el-table :data="listData" <el-table :data="listData" class="table" ref="table" stripe header-align="center"
class="table" @selection-change="handleSelectionChange" row-key="accountId">
ref="table" <el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
stripe <el-table-column type="index" width="60" label="序号" align="center"></el-table-column>
header-align="center" <el-table-column prop="userName" label="员工姓名" align="center" min-width="100"></el-table-column>
@selection-change="handleSelectionChange" <el-table-column prop="account" label="账号" align="center" min-width="100"></el-table-column>
row-key="accountId"> <el-table-column prop="phone" label="手机号" align="center" width="120"></el-table-column>
<el-table-column type="selection" <el-table-column prop="staffArchitectureName" label="所在部门" align="center" min-width="200"
width="55" show-overflow-tooltip></el-table-column>
align="center" <el-table-column prop="roleName" label="授权角色" align="center" min-width="200"
:reserve-selection="true"></el-table-column> show-overflow-tooltip></el-table-column>
<el-table-column type="index" <el-table-column prop="lastLoginTime" label="最后登录时间" align="center" width="130"></el-table-column>
width="60" <el-table-column label="操作" align="center" width="300">
label="序号"
align="center"></el-table-column>
<el-table-column prop="userName"
label="员工姓名"
align="center"
min-width="100"></el-table-column>
<el-table-column prop="account"
label="账号"
align="center"
min-width="100"></el-table-column>
<el-table-column prop="phone"
label="手机号"
align="center"
width="120"></el-table-column>
<el-table-column prop="staffArchitectureName"
label="所在部门"
align="center"
min-width="200"
show-overflow-tooltip></el-table-column>
<el-table-column prop="roleName"
label="授权角色"
align="center"
min-width="200"
show-overflow-tooltip></el-table-column>
<el-table-column prop="lastLoginTime"
label="最后登录时间"
align="center"
width="130"></el-table-column>
<el-table-column label="操作"
align="center"
width="300">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" <el-button type="text" v-auth="'/system:后台账号:查看'" @click="queryStaff(scope.row, true)">查看</el-button>
v-auth="'/system:后台账号:查看'" <el-button type="text" v-auth="'/system:后台账号:编辑'" @click="queryStaff(scope.row, false)">编辑</el-button>
@click="queryStaff(scope.row,true)">查看</el-button> <el-button type="text" v-auth="'/system:后台账号:重置密码'" @click="resetPassword(scope.row)">重置密码</el-button>
<el-button type="text" <el-button type="text" v-auth="'/system:后台账号:删除'" @click="delStaff(scope.row)">删除</el-button>
v-auth="'/system:后台账号:编辑'"
@click="queryStaff(scope.row,false)">编辑</el-button>
<el-button type="text"
v-auth="'/system:后台账号:重置密码'"
@click="resetPassword(scope.row)">重置密码</el-button>
<el-button type="text"
v-auth="'/system:后台账号:删除'"
@click="delStaff(scope.row)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="pagination"> <div class="pagination">
<el-pagination background <el-pagination background @current-change="currentChange" :current-page="page" layout="total, prev, pager, next"
@current-change="currentChange" :total="total"></el-pagination>
:current-page="page"
layout="total, prev, pager, next"
:total="total"></el-pagination>
</div> </div>
<el-dialog :title="isDetail ? '查看' : (form.accountId ? '编辑' : '新增') + '员工'" <el-dialog :title="isDetail ? '查看' : (form.accountId ? '编辑' : '新增') + '员工'" :visible.sync="staffVisible"
:visible.sync="staffVisible" width="580px" class="dialog" :close-on-click-modal="false" @close="closeStaff">
width="580px" <el-form ref="form" :model="form" :rules="rules" label-width="150px" :disabled="isDetail"
class="dialog" style='margin-right: 80px;'>
:close-on-click-modal="false" <el-form-item prop="workNumber" label="工号">
@close="closeStaff"> <el-input v-model.trim="form.workNumber" placeholder="请输入工号"></el-input>
<el-form ref="form"
:model="form"
:rules="rules"
label-width="150px"
:disabled="isDetail"
style='margin-right: 80px;'>
<el-form-item prop="workNumber"
label="工号">
<el-input v-model.trim="form.workNumber"
placeholder="请输入工号"></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="userName" <el-form-item prop="userName" label="姓名">
label="姓名"> <el-input v-model.trim="form.userName" placeholder="请输入姓名"></el-input>
<el-input v-model.trim="form.userName"
placeholder="请输入姓名"></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="account" <el-form-item prop="account" label="账号">
label="账号"> <el-input v-model.trim="form.account" placeholder="请输入账号"></el-input>
<el-input v-model.trim="form.account"
placeholder="请输入账号"></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="roleList" <el-form-item prop="roleList" label="授权角色">
label="授权角色"> <el-select class="w-100" v-model="form.roleList" multiple>
<el-select class="w-100"
v-model="form.roleList"
multiple>
<template v-for="item in roleList"> <template v-for="item in roleList">
<!-- 不显示超管 --> <!-- 不显示超管 -->
<el-option v-if="item.roleName !== '超级管理员'" <el-option v-if="item.roleName !== '超级管理员'" :key="item.id" :label="item.roleName" :value="item.id">
:key="item.id"
:label="item.roleName"
:value="item.id">
</el-option> </el-option>
</template> </template>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="所在部门"> <el-form-item label="所在部门">
<el-cascader class="w-100" <el-cascader class="w-100" v-model="form.staffArchitectureId" :options="orgList"
v-model="form.staffArchitectureId" :props="casProps"></el-cascader>
:options="orgList"
:props="casProps"></el-cascader>
</el-form-item> </el-form-item>
<el-form-item prop="phone" <el-form-item prop="phone" label="手机号">
label="手机号"> <el-input v-model.trim="form.phone" placeholder="请输入手机号" maxlength="11"></el-input>
<el-input v-model.trim="form.phone"
placeholder="请输入手机号"
maxlength="11"></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="email" <el-form-item prop="email" label="邮箱">
label="邮箱"> <el-input v-model.trim="form.email" placeholder="请输入邮箱"></el-input>
<el-input v-model.trim="form.email"
placeholder="请输入邮箱"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<span slot="footer" <span slot="footer" class="dialog-footer" v-if="!isDetail">
class="dialog-footer"
v-if="!isDetail">
<el-button @click="staffVisible = false">取消</el-button> <el-button @click="staffVisible = false">取消</el-button>
<el-button type="primary" <el-button type="primary" @click="submitStaff">确定</el-button>
@click="submitStaff">确定</el-button>
</span> </span>
</el-dialog> </el-dialog>
<el-dialog title="批量导入" <el-dialog title="批量导入" :visible.sync="importVisible" width="24%" :close-on-click-modal="false">
:visible.sync="importVisible"
width="24%"
:close-on-click-modal="false">
<div style="text-align: center"> <div style="text-align: center">
<div style="margin-bottom: 10px;"> <div style="margin-bottom: 10px;">
<el-button type="primary" <el-button type="primary" @click="download">模板下载<i class="el-icon-download el-icon--right"></i></el-button>
@click="download">模板下载<i class="el-icon-download el-icon--right"></i></el-button>
</div> </div>
<el-upload ref="importStaff" <el-upload ref="importStaff" name="file" accept=".xls,.xlsx" :on-remove="handleRemove" :on-error="uploadError"
name="file" :on-success="uploadSuccess" :before-remove="beforeRemove" :limit="1" :on-exceed="handleExceed"
accept=".xls,.xlsx" :action="this.api.importStaff" :file-list="uploadList" :headers="headers">
:on-remove="handleRemove" <el-button type="primary" class="ml20">上传文件<i class="el-icon-upload2 el-icon--right"></i></el-button>
:on-error="uploadError"
:on-success="uploadSuccess"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="this.api.importStaff"
:file-list="uploadList"
:headers="headers">
<el-button type="primary"
class="ml20">上传文件<i class="el-icon-upload2 el-icon--right"></i></el-button>
</el-upload> </el-upload>
<el-link v-if="uploadFaild" <el-link v-if="uploadFaild" type="primary" @click="showFaild">部分数据导入失败查看失败原因</el-link>
type="primary"
@click="showFaild">部分数据导入失败查看失败原因</el-link>
</div> </div>
<span slot="footer" <span slot="footer" class="dialog-footer">
class="dialog-footer"> <el-button size="small" @click="importVisible = false"> </el-button>
<el-button size="small" <el-button size="small" type="primary" @click="uploadSure"> </el-button>
@click="importVisible = false"> </el-button>
<el-button size="small"
type="primary"
@click="uploadSure"> </el-button>
</span> </span>
</el-dialog> </el-dialog>
</div> </div>
@ -868,27 +739,32 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.m-b-20 { .m-b-20 {
margin-bottom: 20px; margin-bottom: 20px;
} }
.org-name { .org-name {
margin-right: 20px; margin-right: 20px;
} }
.w-100 { .w-100 {
width: 100%; width: 100%;
} }
.wrap { .wrap {
display: flex; display: flex;
min-height: 100%; min-height: 100%;
padding: 0 24px; padding: 0 24px;
.side {
width: 300px; .side {
padding: 24px 10px 24px 0; width: 300px;
margin-right: 24px; padding: 24px 10px 24px 0;
border-right: 1px solid rgba(0, 0, 0, 0.06); margin-right: 24px;
} border-right: 1px solid rgba(0, 0, 0, 0.06);
.right { }
width: calc(100% - 374px);
padding: 24px 0; .right {
} width: calc(100% - 374px);
padding: 24px 0;
}
} }
</style> </style>

@ -705,7 +705,7 @@ export default {
// //
if (row.fileId) { if (row.fileId) {
this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => { this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => {
this.playAuth = res.data.playAuth; this.playAuth = res.playAuth;
if (this.player) { if (this.player) {
this.player.replayByVidAndPlayAuth(row.fileId, this.playAuth); this.player.replayByVidAndPlayAuth(row.fileId, this.playAuth);
} else { } else {

@ -1,78 +1,46 @@
<template> <template>
<!-- 课程预览 --> <!-- 课程预览 -->
<div class="wrap"> <div class="wrap">
<el-card shadow="hover" <el-card shadow="hover" class="m-b-20">
class="m-b-20">
<div class="flex-between"> <div class="flex-between">
<el-page-header @back="back" <el-page-header @back="back" :content="'课程预览'"></el-page-header>
:content="'课程预览'"></el-page-header>
</div> </div>
</el-card> </el-card>
<div class="flex"> <div class="flex">
<div class="cover" <div class="cover" :class="{ 'is-word': showMask1 }">
:class="{'is-word': showMask1}"> <img v-if="coverUrl" :src="coverUrl" alt="" width="100%" height="100%">
<img v-if="coverUrl"
:src="coverUrl"
alt=""
width="100%"
height="100%">
<template v-else-if="iframeSrc"> <template v-else-if="iframeSrc">
<iframe class="inner fileIframe" <iframe class="inner fileIframe" id="fileIframe" :src="iframeSrc" frameborder="0"></iframe>
id="fileIframe"
:src="iframeSrc"
frameborder="0"></iframe>
<template v-if="showMask"> <template v-if="showMask">
<div class="mask" <div class="mask" style="width: 500px;height: 30px;top: 53px;right: 320px"></div>
style="width: 500px;height: 30px;top: 53px;right: 320px"></div> <div class="mask" style="width: 175px;height: 30px;top: 53px;right: 5px"></div>
<div class="mask"
style="width: 175px;height: 30px;top: 53px;right: 5px"></div>
</template> </template>
<template v-if="showMask1"> <template v-if="showMask1">
<div class="word-mask" <div class="word-mask" style="height: 40px;"></div>
style="height: 40px;"></div> <div class="word-mask2" style="top: 55px;left: 28%;width: 44%;height: calc(100% - 80px);"></div>
<div class="word-mask2"
style="top: 55px;left: 28%;width: 44%;height: calc(100% - 80px);"></div>
</template> </template>
<template v-if="showMask2"> <template v-if="showMask2">
<div class="excel-mask1" <div class="excel-mask1" style="height: 48px;"></div>
style="height: 48px;"></div>
</template> </template>
</template> </template>
<div class="pdf inner" <div class="pdf inner" v-else-if="pdfSrc">
v-else-if="pdfSrc">
<p class="arrow"> <p class="arrow">
<span @click="changePdfPage(0)" <span @click="changePdfPage(0)" class="turn el-icon-arrow-left" :class="{ grey: currentPage == 1 }"></span>
class="turn el-icon-arrow-left"
:class="{grey: currentPage==1}"></span>
{{ currentPage }} / {{ pageCount }} {{ currentPage }} / {{ pageCount }}
<span @click="changePdfPage(1)" <span @click="changePdfPage(1)" class="turn el-icon-arrow-right"
class="turn el-icon-arrow-right" :class="{ grey: currentPage == pageCount }"></span>
:class="{grey: currentPage==pageCount}"></span>
</p> </p>
<pdf class="pdf-wrap" <pdf class="pdf-wrap" :src="pdfSrc" :page="currentPage" @num-pages="pageCount = $event"
:src="pdfSrc" @page-loaded="currentPage = $event" @loaded="loadPdfHandler">
:page="currentPage"
@num-pages="pageCount=$event"
@page-loaded="currentPage=$event"
@loaded="loadPdfHandler">
</pdf> </pdf>
</div> </div>
<div class="inner" <div class="inner" v-else-if="playAuth">
v-else-if="playAuth"> <div class="video_wid" id="player"></div>
<div class="video_wid"
id="player"></div>
</div> </div>
<div class="inner" <div class="inner" v-else-if="videoSrc">
v-else-if="videoSrc"> <video class="video" :key="videoSrc" width="100%" height="100%" autoplay controls>
<video class="video" <source :src="videoSrc" type="video/mp4">
:key="videoSrc"
width="100%"
height="100%"
autoplay
controls>
<source :src="videoSrc"
type="video/mp4">
您的浏览器不支持 video 标签 您的浏览器不支持 video 标签
</video> </video>
</div> </div>
@ -81,49 +49,26 @@
<div class="list"> <div class="list">
<h4 class="title">{{ courseName }}</h4> <h4 class="title">{{ courseName }}</h4>
<div class="desc-wrap"> <div class="desc-wrap">
<div class="desc" <div class="desc" :class="{ active: desShrink }" v-html="description"></div>
:class="{active: desShrink}" <i class="arrow" :class="{ active: desShrink }" v-if="description.length > 40">
v-html="description"></div>
<i class="arrow"
:class="{active: desShrink}"
v-if="description.length > 40">
<span>...</span> <span>...</span>
<img src="@/assets/img/arrow-down.png" <img src="@/assets/img/arrow-down.png" alt="" @click="desShrink = !desShrink">
alt=""
@click="desShrink = !desShrink">
</i> </i>
</div> </div>
<div class="chapters"> <div class="chapters">
<template v-if="videoList.length"> <template v-if="videoList.length">
<div class="chapter" <div class="chapter" v-for="(item, index) in videoList" :key="index">
v-for="(item,index) in videoList"
:key="index">
<div class="chapterName">{{ item.name }}</div> <div class="chapterName">{{ item.name }}</div>
<div class="section" <div class="section" v-if="item.subsectionList.length">
v-if="item.subsectionList.length"> <div v-for="(section, i) in item.subsectionList" :key="i" @click="preview(section, item.name)">
<div v-for="(section,i) in item.subsectionList" <p class="sectionName ellipsis" :class="{ active: curLink === `${item.name}${section.name}` }">
:key="i" <img v-if="section.fileType === 'pptx'" src="@/assets/img/exts/ppt.png" alt="">
@click="preview(section, item.name)"> <img v-else-if="section.fileType === 'mp4'" src="@/assets/img/exts/video.png" alt="">
<p class="sectionName ellipsis"
:class="{active: curLink === `${item.name}${section.name}`}">
<img v-if="section.fileType === 'pptx'"
src="@/assets/img/exts/ppt.png"
alt="">
<img v-else-if="section.fileType === 'mp4'"
src="@/assets/img/exts/video.png"
alt="">
<img v-else-if="section.fileType === 'doc' || section.fileType === 'docx'" <img v-else-if="section.fileType === 'doc' || section.fileType === 'docx'"
src="@/assets/img/exts/word.png" src="@/assets/img/exts/word.png" alt="">
alt=""> <img v-else-if="section.fileType === 'txt'" src="@/assets/img/exts/txt.png" alt="">
<img v-else-if="section.fileType === 'txt'" <img v-else-if="section.fileType === 'pdf'" src="@/assets/img/exts/pdf.png" alt="">
src="@/assets/img/exts/txt.png" <img v-else src="@/assets/img/exts/pic.png" alt="">
alt="">
<img v-else-if="section.fileType === 'pdf'"
src="@/assets/img/exts/pdf.png"
alt="">
<img v-else
src="@/assets/img/exts/pic.png"
alt="">
{{ section.name }} {{ section.name }}
</p> </p>
</div> </div>
@ -222,7 +167,7 @@ export default {
// //
if (row.fileId) { if (row.fileId) {
this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => { this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => {
this.playAuth = res.data.playAuth; this.playAuth = res.playAuth;
this.$nextTick(() => { this.$nextTick(() => {
if (this.player) { if (this.player) {
this.player.replayByVidAndPlayAuth(row.fileId, this.playAuth); this.player.replayByVidAndPlayAuth(row.fileId, this.playAuth);
@ -320,265 +265,317 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.wrap { .wrap {
padding: 0 200px; padding: 0 200px;
} }
$height: 700px; $height: 700px;
.video_wid, .video_wid,
.cover { .cover {
position: relative; position: relative;
width: 76%; width: 76%;
height: $height !important; height: $height !important;
border: 0; border: 0;
} }
.page { .page {
/deep/.des { /deep/.des {
overflow: auto; overflow: auto;
div,
p, div,
span { p,
font-family: PingFangSC-Regular !important; span {
} font-family: PingFangSC-Regular !important;
} }
}
} }
.l-title { .l-title {
font-size: 17px; font-size: 17px;
} }
.cover { .cover {
background-color: #252528; background-color: #252528;
img {
border-radius: 8px; img {
} border-radius: 8px;
&.is-word { }
overflow: hidden;
} &.is-word {
overflow: hidden;
}
} }
.fileIframe { .fileIframe {
height: $height !important; height: $height !important;
} }
.video_wid, .video_wid,
.inner { .inner {
width: 100%; width: 100%;
height: 100% !important; height: 100% !important;
border: 0; border: 0;
overflow: auto; overflow: auto;
} }
.cover.is-word { .cover.is-word {
.inner { .inner {
height: calc(100% + 38px) !important; height: calc(100% + 38px) !important;
margin-top: -38px; margin-top: -38px;
} }
} }
.video_wid:focus { .video_wid:focus {
outline: none; outline: none;
} }
.catalog { .catalog {
width: 296px; width: 296px;
padding: 16px; padding: 16px;
margin-left: 12px; margin-left: 12px;
background-color: #252528; background-color: #252528;
} }
.list { .list {
height: calc(700px - 82px); height: calc(700px - 82px);
overflow-y: auto; overflow-y: auto;
.title {
margin-bottom: 11px; .title {
color: #fff; margin-bottom: 11px;
font-size: 16px; color: #fff;
} font-size: 16px;
.pro-title { }
margin-bottom: 5px;
color: #fff; .pro-title {
font-size: 12px; margin-bottom: 5px;
} color: #fff;
/deep/.el-progress-bar { font-size: 12px;
width: 92%; }
}
/deep/.el-progress__text { /deep/.el-progress-bar {
color: #fff; width: 92%;
}
/deep/.el-progress__text {
color: #fff;
}
.desc-wrap {
position: relative;
.desc {
font-size: 12px;
color: #fff;
line-height: 22px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
text-overflow: ellipsis;
overflow: hidden;
&.active {
display: block;
overflow: visible;
}
} }
.desc-wrap {
position: relative; .arrow {
.desc { position: absolute;
font-size: 12px; bottom: 2px;
color: #fff; right: 0;
line-height: 22px; display: flex;
display: -webkit-box; justify-content: space-between;
-webkit-box-orient: vertical; width: 46px;
-webkit-line-clamp: 2; background-color: #fff;
text-overflow: ellipsis;
overflow: hidden; span {
&.active { font-size: 14px;
display: block; color: rgba(0, 0, 0, 0.65);
overflow: visible; }
}
img {
width: 16px;
cursor: pointer;
}
&.active {
span {
opacity: 0;
} }
.arrow {
position: absolute; img {
bottom: 2px; transform: rotate(180deg);
right: 0;
display: flex;
justify-content: space-between;
width: 46px;
background-color: #fff;
span {
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
}
img {
width: 16px;
cursor: pointer;
}
&.active {
span {
opacity: 0;
}
img {
transform: rotate(180deg);
}
}
} }
}
} }
.chapters { }
margin-top: 16px;
max-height: calc(100% - 53px); .chapters {
overflow: auto; margin-top: 16px;
} max-height: calc(100% - 53px);
.chapter { overflow: auto;
margin-bottom: 20px; }
.chapter {
margin-bottom: 20px;
}
.chapterName {
color: #fff;
font-size: 14px;
}
.section {
padding: 5px 15px;
margin-top: 12px;
background-color: #121214;
}
.sectionName {
position: relative;
display: flex;
align-items: center;
padding-right: 15px;
margin: 12px 0;
font-size: 12px;
color: #999;
cursor: pointer;
img {
margin-right: 8px;
} }
.chapterName {
color: #fff; .icon {
font-size: 14px; position: absolute;
right: 0;
font-size: 14px;
color: #00c935;
} }
.section {
padding: 5px 15px; .circle {
margin-top: 12px; width: 14px;
background-color: #121214; height: 14px;
border-radius: 50%;
border: 1px solid #ccc;
} }
.sectionName {
position: relative; &.active {
display: flex; color: #fff;
align-items: center;
padding-right: 15px;
margin: 12px 0;
font-size: 12px;
color: #999;
cursor: pointer;
img {
margin-right: 8px;
}
.icon {
position: absolute;
right: 0;
font-size: 14px;
color: #00c935;
}
.circle {
width: 14px;
height: 14px;
border-radius: 50%;
border: 1px solid #ccc;
}
&.active {
color: #fff;
}
} }
}
} }
.buy { .buy {
text-align: center; text-align: center;
.tips {
margin-bottom: 10px; .tips {
font-size: 14px; margin-bottom: 10px;
} font-size: 14px;
img { }
width: 85%;
} img {
width: 85%;
}
} }
.el-image-viewer__wrapper { .el-image-viewer__wrapper {
transform: translateY(-10px); transform: translateY(-10px);
transition: transform 0.5s; transition: transform 0.5s;
&.active { &.active {
transform: translateY(0); transform: translateY(0);
} }
} }
.el-image-viewer__close { .el-image-viewer__close {
z-index: 2000; z-index: 2000;
top: 15px; top: 15px;
right: 15px; right: 15px;
&.doc-close {
i { &.doc-close {
color: #000 !important; i {
} color: #000 !important;
} }
}
} }
.list::-webkit-scrollbar { .list::-webkit-scrollbar {
width: 4px; width: 4px;
} }
.list::-webkit-scrollbar-thumb { .list::-webkit-scrollbar-thumb {
border-radius: 10px; border-radius: 10px;
background: rgba(0, 0, 0, 0.06); background: rgba(0, 0, 0, 0.06);
} }
.mask { .mask {
z-index: 9; z-index: 9;
position: absolute; position: absolute;
background-color: rgb(57, 58, 61); background-color: rgb(57, 58, 61);
} }
.word-mask { .word-mask {
z-index: 9; z-index: 9;
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
width: 100%; width: 100%;
background-color: rgb(243, 242, 241); background-color: rgb(243, 242, 241);
} }
.word-mask1 { .word-mask1 {
z-index: 9; z-index: 9;
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
width: 100%; width: 100%;
background-color: #185abd; background-color: #185abd;
} }
.word-mask2 { .word-mask2 {
z-index: 9; z-index: 9;
position: absolute; position: absolute;
background-color: transparent; background-color: transparent;
} }
.excel-mask1 { .excel-mask1 {
z-index: 9; z-index: 9;
position: absolute; position: absolute;
top: 0; top: 0;
left: 20%; left: 20%;
width: 60%; width: 60%;
background-color: #107c41; background-color: #107c41;
} }
.pdf { .pdf {
position: relative; position: relative;
.full {
position: absolute; .full {
top: 7px; position: absolute;
right: 10px; top: 7px;
cursor: pointer; right: 10px;
} cursor: pointer;
.arrow { }
padding: 10px 0;
display: flex; .arrow {
justify-content: center; padding: 10px 0;
align-items: center; display: flex;
font-size: 16px; justify-content: center;
color: #fff; align-items: center;
background-color: #333; font-size: 16px;
.turn { color: #fff;
margin: 0 10px; background-color: #333;
font-size: 18px;
cursor: pointer; .turn {
} margin: 0 10px;
} font-size: 18px;
.pdf-wrap { cursor: pointer;
width: 80%;
margin: 0 auto;
} }
}
.pdf-wrap {
width: 80%;
margin: 0 auto;
}
} }
</style> </style>

@ -6,14 +6,25 @@
<script> <script>
import Util from '@/libs/util' import Util from '@/libs/util'
import Setting from '@/setting'
export default { export default {
data () { data () {
return { return {
url: `http://121.37.12.51/exam/#/quesBankType?token=${sessionStorage.getItem('token')}` url: ''
}; };
}, },
mounted () { mounted () {
const cache = localStorage.getItem('examPath') // localStorage
let url = `${location.origin}/examination/`
if (Setting.isDev) url = `http://192.168.31.125:8098/`
if (cache) {
url += `#${cache}${cache.includes('?') ? `&` : '?'}token=${sessionStorage.getItem('token')}`
} else {
url += `#/quesBankType?token=${sessionStorage.getItem('token')}`
}
url += `&v=${Date.now()}`
localStorage.setItem('exam_token', sessionStorage.getItem('token'))
this.url = url
}, },
methods: { methods: {
@ -23,6 +34,6 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
iframe { iframe {
height: calc(100vh - 173px); height: calc(100vh - 167px);
} }
</style> </style>

Loading…
Cancel
Save