Compare commits

..

79 Commits

Author SHA1 Message Date
yujialong 87e0c2c1c8 fix 1 month ago
yujialong b7425ca1df fix 1 month ago
yujialong c9d67373d3 fix 1 month ago
yujialong 0c9e5562a1 权限 1 month ago
yujialong 429f9d672c 赛事导入人员模板更换 1 month ago
yujialong b5aa906326 fix 1 month ago
yujialong 6df319cf51 fix 1 month ago
yujialong be1ee97189 fix 1 month ago
yujialong db23e62753 fix 2 months ago
yujialong 04c306898f fix 2 months ago
yujialong 878645d672 fix 2 months ago
yujialong 2de12c8ec0 fix 2 months ago
yujialong 79a92a3410 fix 2 months ago
yujialong 08adddc010 fix 2 months ago
yujialong 3bf85a18bb 订单修复,资源库联调 2 months ago
yujialong 69fc4e49b2 fix 2 months ago
yujialong 07b36913d2 订单添加理实课程 2 months ago
yujialong 89abb11569 赛事相关 2 months ago
yujialong e467d90550 fix 2 months ago
yujialong 1d800d91b2 fix 2 months ago
yujialong b4b748d3ca fix 2 months ago
yujialong 6beec3d7e7 fix 2 months ago
yujialong 59f018f18c fix 2 months ago
yujialong 0e6e54bd81 fix 2 months ago
yujialong 28cce9dc63 课程相关 2 months ago
yujialong 38565b6669 fix 2 months ago
yujialong 9ea6496254 课程相关 2 months ago
yujialong 9356e4debe 课程 2 months ago
yujialong 0d1cbd6ed0 资源库等 2 months ago
yujialong 9dd6f20a62 新增课程修改 2 months ago
yujialong f2b6fb204f fix 2 months ago
yujialong 8f99871ad7 左侧导航 2 months ago
yujialong f508148177 整体风格调整 2 months ago
yujialong 36c1a45fe2 工作台及头部导航、主题色更改 2 months ago
yujialong 801c4683a9 工号同步职站 2 months ago
yujialong 26ec77f7de 订单修复 2 months ago
yujialong d5425d48bb fix 2 months ago
yujialong 2a1ffda11c fix 3 months ago
yujialong 24b60d7468 fix 3 months ago
yujialong 796f802fc5 fix 3 months ago
yujialong 2af18aa23c fix 3 months ago
yujialong fe4a1b7900 fix 3 months ago
yujialong 66b4c21343 fix 3 months ago
yujialong 40327a423f fix 4 months ago
yujialong a089ad2943 fix 4 months ago
yujialong 734524aab2 赛事修复 4 months ago
yujialong 4779595867 fix 4 months ago
yujialong df33b0b5eb fix 4 months ago
yujialong b692519c5d fix 4 months ago
yujialong 996a611e03 fix 4 months ago
yujialong 37eb678280 fix 4 months ago
yujialong 46eaca3745 fix 5 months ago
yujialong 56361bdd11 fix 5 months ago
yujialong f3e795125d 竞赛修复 5 months ago
yujialong d0764a64a0 赛事成绩列表实训跟理论合并,线下单独一个页面 5 months ago
yujialong a033ef3565 fix 5 months ago
yujialong f07e4ccdb2 fix 5 months ago
yujialong bf8f4093f6 评阅中心 5 months ago
yujialong dabd2f9871 fix 5 months ago
yujialong 02b22578a4 赛事修复 5 months ago
yujialong e44b2ad9b9 fix 6 months ago
yujialong 0d952de033 fix 6 months ago
yujialong 45ff98f698 fix 6 months ago
yujialong 6747314cc9 fix 6 months ago
yujialong 645e52a679 fix 6 months ago
yujialong 5a21e78cac 赛事成绩相关 6 months ago
yujialong 5c7bb7eba0 fix 6 months ago
yujialong 8eb83be7c7 赛事列表、赛事理论成绩列表 6 months ago
yujialong 89a1a63f71 理论考试实验报告联调完成 6 months ago
yujialong 3668825847 赛事选择试卷相关 6 months ago
yujialong b8a41a5e23 登录调整 6 months ago
yujialong a2b4e242b4 fix 6 months ago
yujialong 58f007cfc9 oss上传秘钥加密 7 months ago
yujialong 812f1c916a 考试平台iframe,订单、客户修复 7 months ago
yujialong b831b14302 知识点、题库分类 7 months ago
yujialong 2669f15962 理论考试系统列表、题库管理 7 months ago
yujialong 300e917d1e 订单修复 7 months ago
yujialong 6fe4a41fa1 订单:一键发货、批量修改期限、试用默认1月 7 months ago
yujialong d611d682a2 fix 8 months ago
  1. 10
      package-lock.json
  2. 2
      package.json
  3. 40
      src/App.vue
  4. 28
      src/assets/css/color-dark.css
  5. 7
      src/assets/css/default/index.scss
  6. 93
      src/assets/css/main.css
  7. 189
      src/assets/css/station.scss
  8. 29
      src/assets/css/theme-green/color-green.css
  9. BIN
      src/assets/css/theme-green/fonts/element-icons.ttf
  10. BIN
      src/assets/css/theme-green/fonts/element-icons.woff
  11. 1
      src/assets/css/theme-green/index.css
  12. BIN
      src/assets/img/ach1.png
  13. BIN
      src/assets/img/ach2.png
  14. 1
      src/assets/img/drag.svg
  15. 1
      src/assets/img/empty.svg
  16. BIN
      src/assets/img/exts/excel.png
  17. BIN
      src/assets/img/full.png
  18. BIN
      src/assets/img/project.png
  19. 1
      src/assets/img/right.svg
  20. 1
      src/assets/img/shrink.svg
  21. 1
      src/assets/img/tag-active.svg
  22. 1
      src/assets/img/tag.svg
  23. BIN
      src/assets/img/wechat-code.jpeg
  24. BIN
      src/assets/img/workbench/1.png
  25. BIN
      src/assets/img/workbench/10.png
  26. BIN
      src/assets/img/workbench/11.png
  27. BIN
      src/assets/img/workbench/12.png
  28. BIN
      src/assets/img/workbench/13.png
  29. BIN
      src/assets/img/workbench/14.png
  30. BIN
      src/assets/img/workbench/15.png
  31. BIN
      src/assets/img/workbench/16.png
  32. BIN
      src/assets/img/workbench/2.png
  33. BIN
      src/assets/img/workbench/3.png
  34. BIN
      src/assets/img/workbench/4.png
  35. BIN
      src/assets/img/workbench/5.png
  36. BIN
      src/assets/img/workbench/6.png
  37. BIN
      src/assets/img/workbench/7.png
  38. BIN
      src/assets/img/workbench/8.png
  39. BIN
      src/assets/img/workbench/9.png
  40. 1
      src/assets/img/wrong.svg
  41. 55
      src/components/Header.vue
  42. 149
      src/components/Navbar.vue
  43. 261
      src/components/Sidebar.vue
  44. 57
      src/components/quill/index.vue
  45. 23
      src/components/upload/config.js
  46. 34
      src/components/upload/index.vue
  47. 15
      src/components/upload/upload.js
  48. 50
      src/const/ques.js
  49. 28
      src/const/source.js
  50. 34
      src/const/testPaper.js
  51. 10
      src/libs/route/addRoutes.js
  52. 37
      src/libs/util.js
  53. 11
      src/main.js
  54. 150
      src/router/index.js
  55. 10
      src/setting.js
  56. 65
      src/utils/api.js
  57. 16
      src/utils/editor.js
  58. 44
      src/utils/http.js
  59. 63
      src/views/Home.vue
  60. 278
      src/views/Login.vue
  61. 436
      src/views/course/AddCurriculum.vue
  62. 204
      src/views/course/AddLink.vue
  63. 1080
      src/views/course/content/index.vue
  64. 610
      src/views/course/content/source.vue
  65. 303
      src/views/course/contentSettings.vue
  66. 1209
      src/views/course/detail.vue
  67. 199
      src/views/course/list.vue
  68. 103
      src/views/customer/AddCustomer.vue
  69. 79
      src/views/customer/Order.vue
  70. 48
      src/views/customer/Permission.vue
  71. 2
      src/views/customer/customer.vue
  72. 267
      src/views/data/Framework.vue
  73. 77
      src/views/data/Introduce.vue
  74. 271
      src/views/data/Product.vue
  75. 335
      src/views/devLogin.vue
  76. 102
      src/views/information/contentManage/contentList.vue
  77. 21
      src/views/information/contentManage/index.vue
  78. 21
      src/views/information/list/index.vue
  79. 251
      src/views/market/index.vue
  80. 35
      src/views/match/add/index.vue
  81. 351
      src/views/match/add/set.vue
  82. 62
      src/views/match/add/step1.vue
  83. 14
      src/views/match/add/step2.vue
  84. 60
      src/views/match/add/step3.vue
  85. 211
      src/views/match/add/template.vue
  86. 200
      src/views/match/list/index.vue
  87. 4
      src/views/match/manage/abnormalTeam.vue
  88. 16
      src/views/match/manage/index.vue
  89. 95
      src/views/match/manage/matchArch.vue
  90. 730
      src/views/match/manage/matchArchList.vue
  91. 34
      src/views/match/manage/matchInfo.vue
  92. 61
      src/views/match/manage/matchProgress.vue
  93. 103
      src/views/match/manage/matchRank.vue
  94. 449
      src/views/match/manage/matchReport.vue
  95. 29
      src/views/match/manage/matchSignup.vue
  96. 65
      src/views/match/manage/notice.vue
  97. 675
      src/views/match/manage/otherArchList.vue
  98. 1059
      src/views/match/manage/theoryReport.vue
  99. 426
      src/views/match/manage/trialReport.vue
  100. 651
      src/views/order/AddOrder.vue
  101. Some files were not shown because too many files have changed in this diff Show More

10
package-lock.json generated

@ -3871,6 +3871,11 @@
"randomfill": "^1.0.3"
}
},
"crypto-js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
},
"css": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz",
@ -9509,6 +9514,11 @@
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
},
"jsencrypt": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/jsencrypt/-/jsencrypt-3.3.2.tgz",
"integrity": "sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A=="
},
"jsesc": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",

@ -14,6 +14,7 @@
"babel-polyfill": "^6.26.0",
"blueimp-md5": "^2.19.0",
"clipboard": "^2.0.11",
"crypto-js": "^4.2.0",
"decimal.js": "^10.4.3",
"echarts": "^5.4.1",
"element-theme": "^2.0.1",
@ -22,6 +23,7 @@
"image-conversion": "^2.1.1",
"image-webpack-loader": "^8.1.0",
"js-cookie": "^3.0.1",
"jsencrypt": "^3.3.2",
"jszip": "^3.10.1",
"lodash": "^4.17.21",
"mavon-editor": "^2.10.4",

@ -1,30 +1,48 @@
<template>
<div id="app">
<el-radio-group v-if="Setting.isDev" class="ip" v-model="ip" @change="ipChange">
<el-radio :label="0">刘榕ip</el-radio>
<el-radio :label="1">陈赓ip</el-radio>
<el-radio :label="2">测试服ip</el-radio>
</el-radio-group>
<router-view></router-view>
</div>
</template>
<script>
export default {
import Setting from '@/setting'
export default {
name: 'App',
data () {
return {
Setting,
ip: localStorage.getItem('ip') ? +localStorage.getItem('ip') : 0,
};
},
created () {
window.exitSystem = () => {
sessionStorage.removeItem('token')
location.reload()
}
//sessionStorage
if (sessionStorage.getItem("store") ) {
this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(sessionStorage.getItem("store"))))
if (sessionStorage.getItem("store")) {
this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem("store"))))
}
//vuexsessionStorage
window.addEventListener("beforeunload",()=>{
sessionStorage.getItem("token") && sessionStorage.setItem("store",JSON.stringify(this.$store.state))
window.addEventListener("beforeunload", () => {
sessionStorage.getItem("token") && sessionStorage.setItem("store", JSON.stringify(this.$store.state))
})
},
methods: {
ipChange (val) {
localStorage.setItem('ip', val)
location.reload()
},
}
}
}
</script>
<style>
@import "./assets/css/main.css";
/* @import "./assets/css/color-dark.css"; */
/*深色主题*/
@import "./assets/css/theme-green/color-green.css";
/* 浅绿色主题 */
@import "./assets/css/main.css";
</style>

@ -1,28 +0,0 @@
.header{
background-color: #242f42;
}
.login-wrap{
background: #324157;
}
.plugins-tips{
background: #eef1f6;
}
.plugins-tips a{
color: #20a0ff;
}
.el-upload--text em {
color: #20a0ff;
}
.pure-button{
background: #20a0ff;
}
.tags-li.active {
border: 1px solid #409EFF;
background-color: #409EFF;
}
.message-title{
color: #20a0ff;
}
.collapse-btn:hover{
background: rgb(40,52,70);
}

@ -0,0 +1,7 @@
/* 改变主题色变量 */
$--color-primary: #062c87;
/* 改变 icon 字体路径变量,必需 */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";

@ -8,7 +8,7 @@ body,
#app,
.wrapper {
width: 100%;
height: 100%;
min-height: 100%;
display: flex;
flex-direction: column;
}
@ -19,6 +19,12 @@ body {
font-size: 14px;
}
.ip {
z-index: 1;
position: fixed;
top: 0;
left: 0;
}
a {
text-decoration: none;
}
@ -54,37 +60,14 @@ li {
.el-table th > .cell {
font-size: 14px;
}
.content-box {
-webkit-transition: left 0.3s ease-in-out;
transition: left 0.3s ease-in-out;
background: #f0f0f0;
flex: 1;
}
.content {
width: auto;
min-height: 100%;
padding: 20px;
box-sizing: border-box;
}
.content-collapse {
left: 65px;
}
.container {
padding: 30px;
background: #fff;
border: 1px solid #ddd;
border-radius: 5px;
}
.p-title {
padding-left: 5px;
margin-bottom: 24px;
line-height: 1;
font-size: 14px;
color: #585858;
border-left: 3px solid #9278ff;
border-left: 3px solid #062c87;
}
.el-upload-list {
width: 100%;
@ -148,7 +131,7 @@ li {
border-radius: 2px;
}
.tabs .item.active:after {
border-bottom-color: #9278ff;
border-bottom-color: #062c87;
}
.crumbs {
@ -323,9 +306,10 @@ li {
color: #fff;
}
#app .el-table th {
background-color: #9278ff !important;
background-color: #fafafc !important;
font-size: 16px;
font-weight: normal;
color: #000;
}
.el-input__inner[type='number'] {
@ -372,7 +356,7 @@ li {
}
.hr_tag {
background-color: #9278ff;
background-color: #062c87;
width: 3px;
height: 15px;
margin-right: 5px;
@ -442,12 +426,15 @@ li {
.el-switch__label span {
font-size: 12px;
}
.m-b-20 {
margin-bottom: 20px;
.m-r-5 {
margin-right: 5px;
}
.m-r-10 {
margin-right: 10px;
}
.m-b-20 {
margin-bottom: 20px;
}
@media (max-width: 720px) {
.el-message {
min-width: auto !important;
@ -455,7 +442,7 @@ li {
}
}
.el-tooltip__popper {
max-width: 500px !important;
max-width: 100% !important;
}
.no-atTheMoment > .el-picker-panel__footer > .el-button--text:first-child {
display: none;
@ -479,3 +466,47 @@ li {
.search-wrap .el-input__inner {
border-radius: 0;
}
.edui-default {
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;
}
}
.el-drawer__header > :first-child {
font-size: 16px;
font-weight: 600;
color: #333;
}

@ -0,0 +1,189 @@
.msg {
li {
margin-bottom: 10px;
border-top: 1px solid #f1f1f1;
&:first-child {
border-top: 0;
}
.li-wrap {
position: relative;
display: flex;
justify-content: space-between;
padding: 16px 0;
.avatar {
width: 48px;
height: 48px;
border-radius: 50%;
}
.texts {
flex: 1;
margin-left: 24px;
.name {
color: rgba(0, 0, 0, 0.85);
font-size: 16px;
}
.date {
color: rgba(0, 0, 0, 0.45);
font-size: 14px;
}
/deep/img {
max-width: 95%;
}
}
.reply-name {
color: #062c87;
}
.action {
display: inline-flex;
align-items: center;
margin: 15px 10px 0 0;
.icon {
margin: 0 5px;
color: #062c87;
font-size: 18px;
cursor: pointer;
&:hover {
opacity: 0.8;
}
&:first-child {
margin-right: 5px;
}
&.del {
color: rgba(0, 0, 0, 0.65);
border: 1px solid rgba(0, 0, 0, 0.15);
}
}
}
.like-wrap {
display: inline-flex;
align-items: center;
cursor: pointer;
}
}
.reply {
margin-top: 20px;
}
}
&.children {
margin-left: 72px;
padding-left: 24px;
background-color: rgba(0, 0, 0, 0.02);
border-radius: 8px;
li {
border-top-color: rgba(0, 0, 0, 0.06);
}
}
}
.toggle {
margin: 16px 0;
text-align: center;
color: #062c87;
font-size: 14px;
span {
cursor: pointer;
}
}
/deep/.quill {
background-color: #fff;
}
/deep/.timeline {
padding-left: 9%;
overflow: hidden;
.el-timeline-item {
padding-bottom: 40px;
}
.el-timeline-item__node--normal {
top: 30px;
}
.el-timeline-item__wrapper {
top: 15px;
padding-left: 40px;
}
.el-timeline-item__tail {
height: 250%;
border-left-width: 1px;
}
.sign {
position: relative;
display: inline-block;
margin-left: -12.5%;
font-size: 14px;
color: #062c87;
}
.draft {
.ver,
.sign {
color: #b1b1b1;
}
}
.ver {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 10px;
margin: -22px 0 20px;
font-size: 15px;
color: #062c87;
border-bottom: 1px dashed #bfbfbf;
}
.des {
p,
span,
em {
font-size: 14px !important;
}
}
.withdraw {
margin-right: 10px;
font-size: 13px;
color: #979797;
}
.action {
margin-left: 15px;
i {
margin-left: 8px;
font-size: 14px;
color: #062c87;
cursor: pointer;
&:hover {
opacity: 0.9;
}
}
}
.detail {
li {
margin-bottom: 20px;
}
.name {
display: flex;
align-items: center;
margin-bottom: 5px;
font-size: 15px;
font-weight: 600;
img {
width: 20px;
margin-right: 5px;
}
}
.val {
font-size: 14px;
line-height: 1.8;
white-space: pre-wrap;
p {
position: relative;
color: #6a6a6a;
&:before {
content: '';
display: inline-block;
width: 5px;
height: 5px;
margin: 0 10px 0 5px;
vertical-align: middle;
border-radius: 20px;
background-color: #c5b8ff;
}
}
}
}
}

@ -1,29 +0,0 @@
.header{
background-color: #fff;
}
.login-wrap{
background: rgba(56, 157, 170, 0.82);;
}
.plugins-tips{
background: #f2f2f2;
}
.plugins-tips a{
color: #00d1b2;
}
.el-upload--text em {
color: #00d1b2;
}
.pure-button{
background: #00d1b2;
}
.pagination > .active > a, .pagination > .active > a:hover, .pagination > .active > a:focus, .pagination > .active > span, .pagination > .active > span:hover, .pagination > .active > span:focus {
background-color: #00d1b2 !important;
border-color: #00d1b2 !important;
}
.tags-li.active {
border: 1px solid #9278FF;
background-color: #9278FF;
}
.collapse-btn:hover{
background: #00d1b2;
}

File diff suppressed because one or more lines are too long

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="1734423793915" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7651" width="16" height="16" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M362.666667 192m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="#666666" p-id="7652"></path><path d="M661.333333 192m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="#666666" p-id="7653"></path><path d="M362.666667 512m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="#666666" p-id="7654"></path><path d="M661.333333 512m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="#666666" p-id="7655"></path><path d="M362.666667 832m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="#666666" p-id="7656"></path><path d="M661.333333 832m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="#666666" p-id="7657"></path></svg>

After

Width:  |  Height:  |  Size: 946 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 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="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

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 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="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

@ -1,29 +1,16 @@
<template>
<div class="header flex-between">
<div class="logo">
<img class="cursor"
@click="goHome"
src="../assets/img/logo.png">
<img class="cursor" @click="goHome" src="../assets/img/logo.png">
</div>
<el-radio-group v-if="Setting.isDev"
v-model="ip"
@change="ipChange">
<el-radio :label="0">刘榕ip</el-radio>
<el-radio :label="1">陈赓ip</el-radio>
</el-radio-group>
<div class="header-right">
<div class="header-user-con">
<div class="user"
@click="toPerson">
<el-avatar :size="40"
:src="$store.state.avatar"></el-avatar>
<span class="user-avator">{{userName}}</span>
<div class="user" @click="toPerson">
<el-avatar :size="40" :src="$store.state.avatar"></el-avatar>
<span class="user-avator">{{ userName }}</span>
</div>
<el-divider class="ml20"
direction="vertical"></el-divider>
<el-button type="text"
class="ml20"
@click="loginout">退出</el-button>
<el-divider class="ml20" direction="vertical"></el-divider>
<el-button type="text" class="ml20" @click="logout">退出</el-button>
</div>
</div>
</div>
@ -34,9 +21,9 @@ import Setting from '@/setting'
export default {
data () {
return {
timer: null,
Setting,
userName: '',
ip: localStorage.getItem('nakadaiIp') ? +localStorage.getItem('nakadaiIp') : 0,
};
},
mounted () {
@ -48,9 +35,10 @@ export default {
this.$router.push('/person')
}
},
loginout () {
localStorage.removeItem('ms_username');
localStorage.removeItem('token');
async logout () {
await this.$post(this.api.logout)
localStorage.removeItem('ms_username')
localStorage.removeItem('token')
sessionStorage.clear()
location.reload()
},
@ -94,8 +82,8 @@ export default {
},
//
heartbeatDetection () {
setInterval(async () => {
await this.$get(this.api.heartbeatDetection)
this.timer = setInterval(async () => {
sessionStorage.getItem('token') ? await this.$get(this.api.heartbeatDetection) : clearInterval(this.timer)
}, 58 * 1000)
},
@ -112,11 +100,6 @@ export default {
Setting.isPro && this.heartbeatDetection()
}).catch(err => { })
},
ipChange (val) {
localStorage.setItem('nakadaiIp', val)
location.reload()
},
},
};
</script>
@ -129,54 +112,66 @@ export default {
font-size: 16px;
color: #333;
}
.header .logo {
float: left;
width: 170px;
height: 40px;
margin-left: 20px;
}
.header .logo img {
width: 100%;
height: 100%;
}
.header-right {
float: right;
padding-right: 50px;
}
.header-user-con {
display: flex;
height: 70px;
align-items: center;
}
.header-user-con .user {
display: inline-flex;
align-items: center;
cursor: pointer;
}
.user-avator {
cursor: pointer;
margin-left: 10px;
font-size: 12px;
}
.ml20 {
margin-left: 20px;
}
.user-avator img {
display: block;
width: 40px;
height: 40px;
border-radius: 50%;
}
/deep/.header-right .el-button--text {
color: #333;
span {
font-size: 12px;
}
}
.header-right .el-divider--vertical {
width: 2px;
height: 15px;
}
.header-right .el-divider {
background-color: #333;
}

@ -0,0 +1,149 @@
<template>
<div class="menus">
<el-menu class="nav" :default-active="onRoutes" background-color="#062c87" text-color="#fff"
active-text-color="#333" unique-opened mode="horizontal" router @select="handleSelect">
<template v-for="item in menus">
<template v-if="item.subs">
<el-submenu :index="item.index" :key="item.index">
<template slot="title">
<!-- <i :class="item.icon"></i> -->
<span slot="title">{{ item.title }}</span>
</template>
<template v-for="subItem in item.subs">
<el-submenu v-if="subItem.subs" :index="subItem.index" :key="subItem.index">
<template slot="title">{{ subItem.title }}</template>
<el-menu-item v-for="(threeItem, i) in subItem.subs" :key="i" :index="threeItem.index">{{
threeItem.title
}}</el-menu-item>
</el-submenu>
<el-menu-item v-else :index="subItem.index" :key="subItem.index">{{ subItem.title }}</el-menu-item>
</template>
</el-submenu>
</template>
<template v-else>
<el-menu-item :index="item.index" :key="item.index">
<!-- <i :class="item.icon"></i> -->
<span slot="title">{{ item.title }}</span>
</el-menu-item>
</template>
</template>
</el-menu>
</div>
</template>
<script>
import Setting from '@/setting'
import addRoutes from '@/libs/route/addRoutes'
export default {
data () {
return {
menuList: [
{
icon: 'el-icon-school',
index: '/workbench',
title: '工作台'
},
{
icon: 'el-icon-user',
index: '/customer',
title: '客户管理'
},
{
icon: 'el-icon-shopping-bag-2',
index: '/user',
title: '用户管理'
},
{
icon: 'el-icon-document-checked',
index: '/order',
title: '订单管理'
},
{
icon: 'el-icon-office-building',
index: '/system',
title: '系统配置'
},
],
menus: [],
onRoutes: this.$route.path
};
},
watch: {
"$route.path": function (val) {
this.menuList.map(e => {
if (val.replace('/', '') === e.index) {
this.handleSelect(val.replace('/', ''))
this.$forceUpdate();
}
})
}
},
mounted () {
sessionStorage.getItem('token') && this.getPer() //
},
methods: {
handleSelect (index) {
this.onRoutes = index
this.$store.commit('setInfoTab', '1')
this.$store.commit('setColumnId', '')
this.$store.commit('setCompetitionCache', null)
},
initMenu () {
if (Setting.dynamicRoute) {
this.menus = this.menuList
return false
const routes = this.$store.state.routes
const menus = []
this.menuList.map(e => {
routes.find(n => n.path === e.index) && menus.push(e)
})
this.menus = menus
} else {
this.menus = this.menuList
}
},
//
getPer () {
this.$get(`${this.api.getUserRolesPermissionMenu}?platformId=${Setting.platformId}`).then(res => {
const routes = res.permissionMenu[0].children
addRoutes(routes)
this.initMenu()
this.$store.commit('setDataPer', res.dataPermissionList)
}).catch(err => {
if (err.status === 500) {
localStorage.removeItem('ms_username');
sessionStorage.clear()
location.reload()
}
})
},
}
};
</script>
<style lang="scss" scoped>
.menus {
z-index: 2000;
position: sticky;
top: 0;
display: flex;
justify-content: center;
background-color: #062c87;
/deep/.nav {
border-bottom: 0;
&>.el-menu-item {
height: 56px;
padding: 0 30px;
line-height: 56px;
}
&>.el-menu-item.is-active {
background-color: #fff !important;
border-bottom: 0;
}
}
}
</style>

@ -1,41 +1,26 @@
<template>
<div>
<el-menu class="sidebar-el-menu"
:default-active="onRoutes"
background-color="#324157"
text-color="#bfcbd9"
active-text-color="#9278FF"
unique-opened
mode="horizontal"
router
@select="handleSelect">
<div class="sidebar">
<el-menu :default-active="active" :default-openeds="['1', '2', '3', '4']" background-color="#fff" text-color="#333"
active-text-color="#062c87" router>
<template v-for="item in menus">
<template v-if="item.subs">
<el-submenu :index="item.index"
:key="item.index">
<template v-if="item.children">
<el-submenu :index="item.index" :key="item.index">
<template slot="title">
<i :class="item.icon"></i>
<span slot="title">{{ item.title }}</span>
</template>
<template v-for="subItem in item.subs">
<el-submenu v-if="subItem.subs"
:index="subItem.index"
:key="subItem.index">
<template v-for="subItem in item.children">
<el-submenu v-if="subItem.children" :index="subItem.index" :key="subItem.index">
<template slot="title">{{ subItem.title }}</template>
<el-menu-item v-for="(threeItem,i) in subItem.subs"
:key="i"
:index="threeItem.index">{{ threeItem.title }}</el-menu-item>
<el-menu-item v-for="(threeItem, i) in subItem.children" :key="i" :index="threeItem.index">{{
threeItem.title
}}</el-menu-item>
</el-submenu>
<el-menu-item v-else
:index="subItem.index"
:key="subItem.index">{{ subItem.title }}</el-menu-item>
<el-menu-item v-else :index="subItem.index" :key="subItem.index">{{ subItem.title }}</el-menu-item>
</template>
</el-submenu>
</template>
<template v-else>
<el-menu-item :index="item.index"
:key="item.index">
<i :class="item.icon"></i>
<el-menu-item :index="item.index" :key="item.index">
<span slot="title">{{ item.title }}</span>
</el-menu-item>
</template>
@ -46,142 +31,204 @@
<script>
import Setting from '@/setting'
import addRoutes from '@/libs/route/addRoutes'
export default {
props: ['path'],
data () {
return {
menuList: [
active: '',
defaultMenus: [
{
icon: 'el-icon-school',
index: '/customer',
title: '客户管理'
index: '1',
title: '系统后台',
children: [
{
index: '/configure?id=1',
title: 'Python系统'
},
{
icon: 'el-icon-user',
index: '/user',
title: '用户管理'
index: '/theoryExam',
title: '理论考试系统'
},
{
icon: 'el-icon-shopping-bag-2',
index: '/order',
title: '订单管理'
index: '/configure?id=3',
title: '金融产品设计及数字化营销沙盘系统'
},
{
icon: 'el-icon-document-checked',
index: '/curriculum',
title: '课程管理'
index: '/configure?id=4',
title: '银行综合系统'
},
{
icon: 'el-icon-notebook-2',
index: '/data',
title: '数据管理'
index: '/configure?id=5',
title: '众筹系统'
},
]
},
{
icon: 'el-icon-tickets',
index: '/match',
title: '大赛管理'
index: '2',
title: '职站教学后台',
children: [
{
index: '/curriculum',
title: '教学课程管理'
},
{
icon: 'el-icon-takeaway-box',
index: '/theoreticalCourse',
title: '理论课程'
title: '精品课程管理'
},
{
icon: 'el-icon-box',
index: '/information',
title: '资讯管理'
},
{
icon: 'el-icon-receiving',
index: '/configure',
title: '服务配置'
index: '/resourse',
title: '资源库'
},
]
},
{
index: '3',
title: '职站商城后台',
children: [
{
icon: 'el-icon-office-building',
index: '/system',
title: '系统配置'
index: '/shop',
title: '产品管理'
},
{
icon: 'el-icon-s-check',
index: '/parner',
title: '合伙管理'
index: '/market',
title: '营销管理'
},
{
icon: 'el-icon-data-line',
index: '/parnerOperation',
title: '合伙运营'
title: '小程序内容管理'
},
{
icon: 'el-icon-s-shop',
index: '/shop',
title: '商城管理'
index: '/parner',
title: '销售代理人管理'
},
]
},
{
index: '4',
title: '运营后台',
children: [
{
index: '/match',
title: '大赛管理'
},
{
index: '/data',
title: '数据管理'
},
{
index: '/review',
title: '评阅管理'
},
]
},
],
menus: [],
onRoutes: this.$route.path
};
},
watch: {
"$route.path": function (val) {
this.menuList.map(e => {
if (val.replace('/', '') === e.index) {
this.handleSelect(val.replace('/', ''))
this.$forceUpdate();
}
})
path: {
handler (val) {
this.active = val === '/configure' ? `/configure?id=${this.$route.query.id}` : val
},
immediate: true
}
},
mounted () {
// sessionStorage.getItem('sideBar') && this.handleSelect(sessionStorage.getItem('sideBar'))
sessionStorage.getItem('token') && this.getPer() //
Setting.dynamicRoute && this.initTabs()
},
methods: {
handleSelect (index) {
this.onRoutes = index
this.$store.commit('setInfoTab', '1')
this.$store.commit('setColumnId', '')
this.$store.commit('setCompetitionCache', null)
sessionStorage.setItem('sideBar', index)
},
initMenu () {
if (Setting.dynamicRoute) {
const routes = this.$store.state.routes
const menus = []
this.menuList.map(e => {
routes.find(n => n.path === e.index) && menus.push(e)
initTabs () {
const { btns } = this.$store.state
const tabs = this.defaultMenus
btns.includes('/configure') && this.menus.push(tabs[0])
const children1 = []
btns.includes('/curriculum') && children1.push(tabs[1].children[0])
btns.includes('/theoreticalCourse') && children1.push(tabs[1].children[1])
btns.includes('/information') && children1.push(tabs[1].children[2])
btns.includes('/resourse') && children1.push(tabs[1].children[3])
this.menus.push({
index: '2',
title: '职站教学后台',
children: children1
})
this.menus = menus
} else {
this.menus = this.menuList
}
},
//
getPer () {
this.$get(`${this.api.getUserRolesPermissionMenu}?platformId=${Setting.platformId}`).then(res => {
const routes = res.permissionMenu[0].children
addRoutes(routes)
this.initMenu()
this.$store.commit('setDataPer', res.dataPermissionList)
}).catch(err => {
if (err.status === 500) {
localStorage.removeItem('ms_username');
sessionStorage.clear()
location.reload()
}
const children2 = []
btns.includes('/shop:产品管理') && children2.push(tabs[2].children[0])
btns.includes('/shop:营销推广管理') && children2.push(tabs[2].children[1])
btns.includes('/parnerOperation') && children2.push(tabs[2].children[2])
btns.includes('/parner') && children2.push(tabs[2].children[3])
this.menus.push({
index: '3',
title: '职站商城后台',
children: children2
})
const children3 = []
btns.includes('/match') && children3.push(tabs[3].children[0])
btns.includes('/data') && children3.push(tabs[3].children[1])
btns.includes('/review') && children3.push(tabs[3].children[2])
this.menus.push({
index: '4',
title: '运营后台',
children: children3
})
},
handleSelect (index) {
},
}
};
</script>
<style scoped>
<style lang="scss" scoped>
.sidebar {
min-width: 200px;
max-width: 200px;
height: calc(100vh - 116px);
overflow: auto;
// transition: .5s;
transform: translateX(-200px);
&.show {
transform: translateX(0);
}
/deep/.el-menu {
border-right: 0 !important;
.el-menu-item,
.el-submenu__title {
height: 40px;
line-height: 40px;
&.is-active {
font-weight: 600;
}
}
.el-menu .el-menu-item {
padding: 0 20px 0 40px !important;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.sidebar::-webkit-scrollbar {
width: 0;
}
.sidebar-el-menu:not(.el-menu--collapse) {
width: 100%;
}
.sidebar > ul {
.sidebar>ul {
height: 100%;
}
</style>

@ -1,39 +1,21 @@
<template>
<div>
<el-radio-group v-if="!readonly && radio"
class="type-radio"
v-model="editorType"
@change="typeChange">
<el-radio-group v-if="!readonly && radio" class="type-radio" v-model="editorType" @change="typeChange">
<el-radio label="0">富文本</el-radio>
<el-radio label="1">markdown</el-radio>
</el-radio-group>
<div v-show="editorType == 0"
class="quill"
ref="quill"
:class="classes">
<div ref="editor"
:style="styles"
v-loading="loading"></div>
<Upload :max-size="1000"
:limit="100"
@beforeUpload="beforeUpload"
@onSuccess="editorUploadSuccess"
<div v-show="editorType == 0" class="quill" ref="quill" :class="classes">
<div ref="editor" :style="styles" v-loading="loading"></div>
<Upload :max-size="1000" :limit="100" @beforeUpload="beforeUpload" @onSuccess="editorUploadSuccess"
style="display: none">
<div slot="trigger">
<el-button :id="'editorUpload' + index"
type="primary">点击上传</el-button>
<el-button :id="'editorUpload' + index" type="primary">点击上传</el-button>
</div>
</Upload>
</div>
<mavon-editor class="md"
v-model="mdVal"
v-show="editorType == 1"
ref="md"
:ishljs="true"
:subfield="false"
@change="mdChange"
@imgAdd="imgAdd" />
<mavon-editor class="md" v-model="mdVal" v-show="editorType == 1" ref="md" :ishljs="true" :subfield="false"
@change="mdChange" @imgAdd="imgAdd" />
</div>
</template>
@ -302,15 +284,18 @@ export default {
.type-radio {
margin-bottom: 20px;
}
.quill-no-border {
.ql-toolbar.ql-snow {
border: none;
border-bottom: 1px solid #e8eaec;
}
.ql-container.ql-snow {
border: none;
}
}
.else {
.ql-toolbar.ql-snow {
height: 0;
@ -319,8 +304,10 @@ export default {
border-top: 0;
}
}
/deep/.ql-snow {
position: relative;
.ql-tooltip {
position: absolute !important;
top: 0 !important;
@ -328,10 +315,30 @@ export default {
transform: translateY(10px);
}
}
.md {
max-height: 300px;
}
/deep/.v-note-wrapper .v-note-panel {
min-height: 200px;
}
/deep/.markdown-body {
ul {
list-style: disc;
li {
list-style: inherit;
}
}
ol {
list-style: decimal;
li {
list-style: inherit;
}
}
}
</style>

@ -2,14 +2,31 @@
* 阿里云oss配置
* */
export default {
import router from '@/router/index'
import { Message } from 'element-ui'
export default async function () {
try {
let RE = localStorage.getItem('osc')
if (RE) {
RE = JSON.parse(RE)
} else {
sessionStorage.removeItem('token')
Message.error('登录过期,请重新登录!')
setTimeout(() => {
router.replace('/login')
}, 1500)
return false
}
return {
// oss账号信息
config: {
region: 'oss-cn-shenzhen',
accessKeyId: 'LTAI4FzqQHnk4rozqLZ8jCNj',
accessKeySecret: 'mveW7B1OyFoKUkHm8WsxmrjHmkJWHq',
accessKeyId: RE[0],
accessKeySecret: RE[1],
bucket: 'huoran'
},
// 上传成功url前置部分(成功回调没有返回url)
preUrl: 'https://huoran.oss-cn-shenzhen.aliyuncs.com/'
}
} catch (e) { }
}

@ -1,24 +1,12 @@
<template>
<el-upload :disabled="uploading"
:before-upload="beforeUpload"
:on-remove="onRemove"
:on-error="uploadError"
:limit="limit"
action=""
:on-exceed="handleExceed"
:show-file-list="showFiles"
:file-list="fileList"
:http-request="handleRequest"
name="file">
<el-upload :disabled="uploading" :before-upload="beforeUpload" :on-remove="onRemove" :on-error="uploadError"
:limit="limit" action="" :on-exceed="handleExceed" :show-file-list="showFiles" :file-list="fileList"
:http-request="handleRequest" name="file">
<slot name="trigger">
<el-button size="small"
:loading="uploading">{{ uploading ? '正在上传' : '上传文件' }}</el-button>
<el-button size="small" :loading="uploading">{{ uploading ? '正在上传' : '上传文件' }}</el-button>
</slot>
<div slot="tip"
class="el-upload__tip">
<el-progress v-if="uploading"
class="upload-progress"
:stroke-width="3"
<div slot="tip" class="el-upload__tip">
<el-progress v-if="uploading" class="upload-progress" :stroke-width="3"
:percentage="uploadProgress"></el-progress>
<slot name="tip">
<p>支持扩展名.rar .zip .doc .docx .pdf .jpg...</p>
@ -69,7 +57,8 @@ export default {
client: null,
uploading: false,
uploadProgress: 0,
showFiles: this.showFileList
showFiles: this.showFileList,
Oss: {},
};
},
mounted () {
@ -77,8 +66,9 @@ export default {
},
methods: {
// oss
initOss () {
this.client = new OSS(OssConfig.config)
async initOss () {
this.Oss = await OssConfig()
this.client = new OSS(this.Oss.config)
},
//
beforeUpload (file) {
@ -107,7 +97,7 @@ export default {
});
this.uploading = false
const url = OssConfig.preUrl + name
const url = this.Oss.preUrl + name
this.changeFileList && this.$emit('update:fileList', [
...this.fileList,
{

@ -5,14 +5,17 @@ import OssConfig from './config'
import Util from '@/libs/util'
let client = null
let Oss
// 初始化oss
const initOss = () => {
if (!client) client = new OSS(OssConfig.config)
const initOss = async () => {
Oss = await OssConfig()
if (!client) client = new OSS(Oss.config)
}
initOss()
export default {
// 上传文件
upload(file) {
upload (file) {
initOss()
return new Promise(async (resolve, reject) => {
try {
@ -21,7 +24,7 @@ export default {
resolve({
format: Util.getFileExt(file.name),
name: file.name,
url: OssConfig.preUrl + res.name,
url: Oss.preUrl + res.name,
size: file.size,
})
} catch (error) {
@ -30,8 +33,8 @@ export default {
})
},
// 删除文件(传完整url,不是没有https的name,因为很多接口没有存name,只存url,所以统一使用url)
async del(url) {
async del (url) {
initOss()
await client.delete(url.replace(OssConfig.preUrl, ''));
await client.delete(url.replace(Oss.preUrl, ''));
}
}

@ -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,28 @@
export default {
types: [
{
id: 1,
name: '演示文稿类'
},
{
id: 2,
name: '视频类'
},
{
id: 3,
name: '图形类'
},
{
id: 4,
name: '文本类'
},
{
id: 5,
name: '音频类'
},
{
id: 6,
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,14 +3,14 @@ import generateBtnPermission from '../auth/generateBtnPermission';
const newRoutes = []
function createMeta(item){
function createMeta (item) {
let meta = { title: item.name }
return meta
}
function createRoute(data){
function createRoute (data) {
data.map(e => {
if(e.path){
if (e.path) {
let meta = createMeta(e)
newRoutes.push({
path: e.path,
@ -22,8 +22,8 @@ function createRoute(data){
})
}
export default function(data,path){
export default function (data, path) {
generateBtnPermission(data)
createRoute(data)
store.commit('addRoutes',newRoutes)
store.commit('addRoutes', newRoutes)
}

@ -172,6 +172,43 @@ const util = {
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

@ -2,17 +2,18 @@ import Vue from 'vue';
import App from './App.vue';
import router from './router';
import ElementUI from 'element-ui';
// import 'element-ui/lib/theme-chalk/index.css'; // 默认主题
import './assets/css/theme-green/index.css'; // 浅绿色主题
import "@/assets/css/default/index.scss";
import './assets/css/icon.css';
import './assets/icon/iconfont.css';
import 'babel-polyfill';
import './utils/rem';
import {post,get,del,put} from './utils/http';
import { post, get, del, put } from './utils/http';
import api from './utils/api';
import store from './store'
import { systemStatus, systemTypeStatus, systemAttributionStatus, courseTypeStatus,
hoursStatus, roleStatus, orderTypeFn, orderStatusFn, orderNatureFn, Percentage, removeByValue, isIE, encodeString, formatDate, downloadFile, dateCompatible } from './utils/core';
import {
systemStatus, systemTypeStatus, systemAttributionStatus, courseTypeStatus,
hoursStatus, roleStatus, orderTypeFn, orderStatusFn, orderNatureFn, Percentage, removeByValue, isIE, encodeString, formatDate, downloadFile, dateCompatible
} from './utils/core';
import preventReClick from './utils/preventReClick' //防多次点击,重复提交
import plugins from '@/directive';

@ -18,144 +18,120 @@ let router = new Router({
children: [
{
path: '/customer',
component: () => import( '../views/customer/customer.vue'),
// meta: { title: '客户管理' }
component: () => import('../views/customer/customer.vue'),
},
{
path: '/addcustomer',
component: () => import( '../views/customer/AddCustomer.vue'),
// meta: { title: '新增客户' }
component: () => import('../views/customer/AddCustomer.vue'),
},
{
path: '/bmOrder',
component: () => import( '../views/customer/Order.vue'),
// meta: { title: '新增客户' }
component: () => import('../views/customer/Order.vue'),
},
{
path: '/user',
component: () => import( '../views/user/User.vue'),
// meta: { title: '用户管理' }
component: () => import('../views/user/User.vue'),
},
{
path: '/adduser',
component: () => import( '../views/user/AddUser.vue'),
// meta: { title: '新增用户' }
component: () => import('../views/user/AddUser.vue'),
},
{
path: '/info',
component: () => import( '../views/user/Info.vue'),
// meta: { title: '新增用户' }
component: () => import('../views/user/Info.vue'),
},
{
path: '/order',
component: () => import( '../views/order/Order.vue'),
// meta: { title: '订单管理' }
component: () => import('../views/order/Order.vue'),
},
{
path: '/addorder',
component: () => import( '../views/order/AddOrder.vue'),
// meta: { title: '新增订单' }
component: () => import('../views/order/AddOrder.vue'),
},
{
path: '/selectClient',
component: () => import( '../views/order/selectClient.vue'),
// meta: { title: '选择订单客户' }
component: () => import('../views/order/selectClient.vue'),
},
{
path: '/configure',
component: () => import( '../views/serve/Configure.vue'),
// meta: { title: '服务配置' }
component: () => import('../views/serve/Configure.vue'),
},
{
path: '/backstage',
component: () => import( '../views/serve/backstage'),
// meta: { title: '服务配置' }
component: () => import('../views/serve/backstage'),
},
{
path: '/addModel',
component: () => import( '../views/serve/addModel'),
// meta: { title: '服务配置' }
component: () => import('../views/serve/addModel'),
},
{
path: '/addconfigure',
component: () => import( '../views/serve/AddConfigure.vue'),
// meta: { title: '新增配置' }
component: () => import('../views/serve/AddConfigure.vue'),
},
{
path: '/projectList',
component: () => import( '../views/serve/projectList.vue'),
// meta: { title: '项目管理' }
component: () => import('../views/serve/projectList.vue'),
},
{
path: '/projectAdd',
component: () => import( '../views/serve/projectAdd.vue'),
// meta: { title: '项目配置' }
component: () => import('../views/serve/projectAdd.vue'),
},
{
path: '/curriculum',
component: () => import( '../views/course/Curriculum.vue'),
// meta: { title: '课程管理' }
component: () => import('../views/course/list'),
},
{
path: '/addcurriculum',
component: () => import( '../views/course/AddCurriculum.vue'),
// meta: { title: '新建课程' }
path: '/curriculum/detail',
component: () => import('../views/course/detail'),
},
{
path: '/contentSettings',
component: () => import( '../views/course/contentSettings.vue'),
// meta: { title: '内容设置' }
},
{
path: '/addlink',
component: () => import( '../views/course/AddLink.vue'),
// meta: { title: '添加环节' }
path: '/curriculum/content',
component: () => import('../views/course/content'),
},
{
path: '/data',
component: () => import( '../views/data/Data.vue'),
// meta: { title: '数据管理' }
component: () => import('../views/data/Data.vue'),
},
{
path: '/match',
component: () => import( '../views/match/list'),
// meta: { title: '数据管理' }
component: () => import('../views/match/list'),
},
{
path: '/addMatch',
component: () => import( '../views/match/add'),
// meta: { title: '数据管理' }
component: () => import('../views/match/add'),
},
{
path: '/matchManage',
component: () => import( '../views/match/manage'),
// meta: { title: '数据管理' }
component: () => import('../views/match/manage'),
},
{
path: '/noticeDetail',
component: () => import( '../views/match/manage/noticeDetail'),
// meta: { title: '数据管理' }
component: () => import('../views/match/manage/noticeDetail'),
},
{
path: '/matchArchList',
component: () => import( '../views/match/manage/matchArchList'),
// meta: { title: '数据管理' }
path: '/otherArchList',
component: () => import('../views/match/manage/otherArchList'),
},
{
path: '/matchRank',
component: () => import( '../views/match/manage/matchRank'),
// meta: { title: '数据管理' }
component: () => import('../views/match/manage/matchRank'),
},
{
path: '/matchReport',
component: () => import( '../views/match/manage/matchReport'),
// meta: { title: '数据管理' }
path: '/trialReport',
component: () => import('../views/match/manage/trialReport'),
},
{
path: '/matchArchList',
component: () => import('../views/match/manage/matchArchList'),
},
{
path: '/theoryReport',
component: () => import('../views/match/manage/theoryReport'),
},
{
path: '/matchInfo',
component: () => import( '../views/match/manage/matchInfo'),
// meta: { title: '数据管理' }
component: () => import('../views/match/manage/matchInfo'),
},
{
path: `/theoreticalCourse`,
@ -189,33 +165,27 @@ let router = new Router({
},
{
path: '/system',
component: () => import( '../views/system'),
// meta: { title: '数据管理' }
component: () => import('../views/system'),
},
{
path: '/manageLog',
component: () => import( '../views/system/manageLog'),
// meta: { title: '数据管理' }
component: () => import('../views/system/manageLog'),
},
{
path: '/addLog',
component: () => import( '../views/system/addLog'),
// meta: { title: '数据管理' }
component: () => import('../views/system/addLog'),
},
{
path: '/permission',
component: () => import('../views/customer/Permission.vue'),
// meta: { title: '应用权限', permission: true }
},
{
path: '/person',
component: () => import('../views/setting'),
// meta: { title: '个人中心' }
},
{
path: '/parner',
component: () => import('../views/parner'),
// meta: { title: '个人中心' }
},
{
path: '/parnerOperation',
@ -234,8 +204,36 @@ let router = new Router({
component: () => import('../views/shop/list'),
},
{
path: '/shop/addProduct',
component: () => import('../views/shop/addProduct'),
path: '/shop/add',
component: () => import('../views/shop/add'),
},
{
path: '/market',
component: () => import('../views/market'),
},
{
path: '/theoryExam/list',
component: () => import('../views/theoryExam/list/index'),
},
{
path: '/theoryExam',
component: () => import('../views/theoryExam'),
},
{
path: '/review',
component: () => import('../views/review'),
},
{
path: '/workbench',
component: () => import('../views/workbench'),
},
{
path: '/resourse',
component: () => import('../views/resourse'),
},
{
path: '/station',
component: () => import('../views/station'),
},
{
path: '/404',
@ -266,7 +264,7 @@ let router = new Router({
},
{
path: '/matchPreview',
component: () => import( '../views/match/preview'),
component: () => import('../views/match/preview'),
// meta: { title: '数据管理' }
},
{
@ -281,7 +279,7 @@ let router = new Router({
]
});
router.beforeEach(function(to, from, next) {
router.beforeEach(function (to, from, next) {
// 根据路由元信息设置文档标题
window.document.title = to.meta.title || '中台';
//使用钩子函数对路由进行权限跳转

@ -5,20 +5,20 @@ const url = location.host;
const isDev = process.env.NODE_ENV === 'development' // 开发环境
const isPro = url.includes('huorantech.cn') //正式服
let jumpPath = `${location.origin}/judgmentPoint/`
let sandPath = `http://121.37.12.51/sandbox` // 沙盘地址
let jumpPath = `${location.origin}/panfen/`
let sandPath = `https://www.occupationlab.com/sandbox` // 沙盘地址
let host = `${location.origin}/`
if (isDev) {
console.log("🚀 ~ localStorage.getItem('nakadaiIp'):",localStorage.getItem('nakadaiIp'))
jumpPath = 'http://192.168.31.125:8087/' // 本地调试-需要启动本地判分点系统
// jumpPath = 'https://judgment.huorantech.cn/'
sandPath = `http://${location.hostname}:9520`
host = 'http://121.37.12.51/'
// host = 'https://huorantech.cn/'
host = localStorage.getItem('nakadaiIp') == 1 ? 'http://192.168.31.51:9000/' : 'http://192.168.31.217:9000/'
const ips = ['http://192.168.31.217:9000/', 'http://192.168.31.51:9000/', 'https://occupationlab.com/']
host = ips[+localStorage.getItem('ip')]
} else if (isPro) {
sandPath = `https://izhixinyun.com/sandbox`
jumpPath = 'https://judgment.huorantech.cn/'
// jumpPath = 'https://judgment.huorantech.cn/'
}

@ -1,7 +1,6 @@
import Setting from "@/setting";
const { uploadURL, apiBaseURL: host } = Setting
const jumpApi = Setting.isDev ? `http://121.37.12.51/` : Setting.isPro ? `https://judgment.huorantech.cn/` : `http://121.37.12.51/`
const { apiBaseURL: host } = Setting
export default {
logins: `users/users/user/login`, //登录
@ -13,13 +12,16 @@ export default {
refreshPageNotification: `nakadai/message/refreshPageNotification`,
heartbeatDetection: `nakadai/message/heartbeatDetection`,
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`,
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`, // 后台账号模板
competionPersonTemplate: `https://huoran.oss-cn-shenzhen.aliyuncs.com/%E4%B8%AD%E5%8F%B0%E4%B8%AA%E4%BA%BA%E8%B5%9B%E6%8A%A5%E5%90%8D%E4%BA%BA%E5%91%98%E5%AF%BC%E5%85%A5%E6%A8%A1%E6%9D%BF.xlsx`, // 中台个人报名人员模板
competionTeamTemplate: `https://huoran.oss-cn-shenzhen.aliyuncs.com/%E4%B8%AD%E5%8F%B0%E5%9B%A2%E9%98%9F%E8%B5%9B%E6%8A%A5%E5%90%8D%E4%BA%BA%E5%91%98%E5%AF%BC%E5%85%A5%E6%A8%A1%E6%9D%BF.xlsx`, // 中台团队报名人员模板
competionPersonTemplate: `https://www.occupationlab.com/template/中台个人赛报名人员导入模板.xlsx`, // 中台个人报名人员模板
competionTeamTemplate: `https://www.occupationlab.com/template/中台团队赛报名人员导入模板.xlsx`, // 中台团队报名人员模板
checkEmailOrPhone: `occupationlab/occupationlab/architecture/checkEmailOrPhone`, // 新增学生前:校验手机号或者邮箱
checkWorkNumOrAccount: `occupationlab/occupationlab/architecture/checkWorkNumOrAccount`, // 新增/编辑学生前:校验学号或者学生账号
@ -36,6 +38,7 @@ export default {
getOrderOtherTime: `nakadai/nakadai/orderOther/getOrderOtherTime`,
refreshCache: `data/data/myDate/refreshCache`,
getPartnerTeamRates: `nakadai/nakadai/partner-team/getPartnerTeamRates`,
getCustomerOrderRecord: `nakadai/nakadai/order/getCustomerOrderRecord`,
// 客户管理
delCustomers: `nakadai/nakadai/customer/delCustomers`,
@ -87,7 +90,8 @@ export default {
oneClickEnableVerification: `users/users/userAccount/oneClickEnableVerification`,
getValueModule: `nakadai/nakadai/valueModuleManagement/getValueModule`,
queryServiceConfig: `nakadai/nakadai/serviceConfiguration/getAllService`, //查询服务配置
queryServiceConfig: `nakadai/nakadai/serviceConfiguration/getAllService`,
workbenchSystemDemonstration: `nakadai/nakadai/serviceConfiguration/workbenchSystemDemonstration`,
// 项目管理
avgValues: `occupationlab/occupationlab/projectManage/avgValues`, // 平均分分配值
deleteProjectManage: `occupationlab/occupationlab/projectManage/deleteProjectManage`, // 新增项目管理
@ -102,8 +106,8 @@ export default {
editProjectDraft: `occupationlab/occupationlab/projectManage/editProjectDraft`, // 修改项目管理
copyProjectManage: `occupationlab/occupationlab/projectManage/copyProjectManage`, // 复制项目管理
// 判分点
getBcJudgmentPoint: `${jumpApi}judgment/judgment/bcJudgmentPoint/getBcJudgmentPoint`, // 获取编程类判分点列表(分页)
getLcJudgmentPoint: `${jumpApi}judgment/judgment/lcJudgmentPoint/queryAllJudgmentPoint`, // 获取流程类判分点列表(分页)
getBcJudgmentPoint: `${host}judgment/judgment/bcJudgmentPoint/getBcJudgmentPoint`, // 获取编程类判分点列表(分页)
getLcJudgmentPoint: `${host}judgment/judgment/lcJudgmentPoint/queryAllJudgmentPoint`, // 获取流程类判分点列表(分页)
addProjectJudgment: `occupationlab/occupationlab/projectJudgment/addProjectJudgment`, // 添加项目管理、判分点中间表
updateProjectJudgment: `occupationlab/occupationlab/projectJudgment/updateProjectJudgment`, // 判分点中间表批量更新
deleteProjectJudgment: `occupationlab/occupationlab/projectJudgment/deleteProjectJudgment`, // 判分点中间表批量删除
@ -152,7 +156,9 @@ export default {
courseProfessional: `nakadai/nakadai/subject/courseProfessional`, //课程专业
//课程管理
curriculumList: `nakadai/nakadai/curriculum/curriculumList`, //课程列表
curriculumTree: `nakadai/nakadai/curriculum/curriculumTree`,
createCurriculum: `nakadai/nakadai/curriculum/createCurriculum`, //创建课程
configureCourseProject: `nakadai/nakadai/curriculum/configureCourseProject`,
curriculumDetail: `nakadai/nakadai/curriculum/curriculumDetail`, //课程详情
modifyCourse: `nakadai/nakadai/curriculum/modifyCourse`, //编辑课程
delCourse: `nakadai/nakadai/curriculum/delCourse`, //单个、批量删除课程
@ -160,6 +166,27 @@ export default {
getInternalProjectBySystemId: `occupationlab/occupationlab/projectManage/getInternalProjectBySystemId`, //根据系统id、项目权限获取系统内置项目
checkConfig: `nakadai/nakadai/curriculum/checkConfig`,
deleteCoursePrompt: `nakadai/nakadai/curriculum/deleteCoursePrompt`,
combinationResource: `nakadai/nakadai/curriculum/combinationResource`,
replaceResource: `nakadai/nakadai/curriculum/subsection/replaceResource`,
curriculumChapter: `nakadai/nakadai/curriculum/chapter/queryChaptersAndSubsections`,
courseLearningProgress: 'nakadai/nakadai/curriculum/learning/progressprogress/courseLearningProgress',
deleteLearningProgress: 'nakadai/nakadai/curriculum/learning/progressprogress/delete',
curriculumGetSubsection: `nakadai/nakadai/curriculum/subsection/getSubsection`,
copySelfBuildCourse: `nakadai/nakadai/curriculum/copySelfBuildCourse`,
// 课程笔记
addNote: `nakadai/curriculumNotes/addNote`,
curriculumNoteList: `nakadai/curriculumNotes/curriculumNoteList`,
deleteNotes: `nakadai/curriculumNotes/deleteNotes`,
updateNote: `nakadai/curriculumNotes/updateNote`,
// 教学互动
addCommentStation: `nakadai/comment/addComment`,
commentTreeList: `nakadai/comment/commentTreeList`,
deleteAComment: `nakadai/comment/deleteAComment`,
commentAndLike: `nakadai/commentLike/commentAndLike`,
unlike: `nakadai/commentLike/unlike`,
messageNotificationList: `nakadai/notify/messageNotificationList`,
noticeRead: `nakadai/notify/noticeRead`,
// 课程章节管理
addChapter: `nakadai/nakadai/curriculum/chapter/addChapter`, //添加章节
editChapter: `nakadai/nakadai/curriculum/chapter/editChapter`, //修改章节
@ -176,6 +203,7 @@ export default {
delTheoreticalCourse: `occupationlab/occupationlab/theoreticalCourse/batchDeletion`,
findTheoreticalCourse: `occupationlab/occupationlab/theoreticalCourse/findById`,
listTheoreticalCourse: `occupationlab/occupationlab/theoreticalCourse/pageConditionalQueryCourse`,
boutiqueCurriculumTree: `occupationlab/occupationlab/theoreticalCourse/boutiqueCurriculumTree`,
saveTheoreticalCourse: `occupationlab/occupationlab/theoreticalCourse/save`,
updateTheoreticalCourse: `occupationlab/occupationlab/theoreticalCourse/update`,
disabledTheoreticalCourse: `occupationlab/occupationlab/theoreticalCourse/disabledEvents`,
@ -202,6 +230,8 @@ export default {
deleteSubsectionTheoretical: `occupationlab/occupationlab/theoreticalCourseSubsection/deleteSubsection`, // 根据id删除小节
editSubsectionTheoretical: `occupationlab/occupationlab/theoreticalCourseSubsection/editSubsection`, // 修改小节
getSubsectionTheoretical: `occupationlab/occupationlab/theoreticalCourseSubsection/getSubsection`, // 根据小节id获取预览文件地址
batchDeletionTheoretical: `occupationlab/occupationlab/theoreticalCourseSubsection/batchDeletion`,
deleteSubsectionBatch: `nakadai/nakadai/curriculum/subsection/deleteSubsectionBatch`,
// 栏目管理
addColumn: `occupationlab/occupationlab/information/column/addColumn`,
@ -337,6 +367,15 @@ export default {
checkTeamStatus: `competition/teamAbnormalInformation/checkTeamStatus`,
queryAbnormalTeam: `competition/teamAbnormalInformation/queryAbnormalTeam`,
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: `${host}occupationlab/occupationlab/achievement/exportLabReport`,
exportBankExperimentReport: `${host}occupationlab/occupationlab/achievement/exportBankExperimentReport`,
getServiceOfType: `nakadai/nakadai/serviceConfiguration/getServiceOfType`,
// 赛事内容
addCompetitionContent: `competition/competition/content/addCompetitionContent`,
@ -404,9 +443,12 @@ export default {
batchDeleteContestGrade: `competition/competition/performance/batchDeleteContestGrade`,
batchImportGrades: `${host}competition/competition/performance/batchImportGrades`,
exportExperimentalResultsInBatch: `${host}competition/competition/performance/exportExperimentalResultsInBatch`,
exportExamPaperReports: `${host}exam/exam/paper/exportExamPaperReports`,
batchExportReportsAsZip: `${host}occupationlab/occupationlab/achievement/batchExportReportsAsZip`,
performanceExportFailure: `${host}competition/competition/performance/exportFailure`,
rankExportFailure: `${host}competition/competition/rank/exportFailure`,
batchImportRanking: `${host}competition/competition/rank/batchImportRanking`,
getPaperUploadFileZip: `${host}exam/exam/paper/question/userAnswer/getPaperUploadFileZip`,
stageGradeManagementList: `competition/competition/performance/stageGradeManagementList`,
stageRaceRanking: `competition/competition/rank/stageRaceRanking`,
overallStandingsInThePointsRace: `competition/competition/rank/overallStandingsInThePointsRace`,
@ -432,6 +474,7 @@ export default {
getCompetitionStageRankingTime: `competition/competitionReleaseTime/getCompetitionStageRankingTime`,
frontOfficeCompetitionRanking: `competition/competition/rank/frontOfficeCompetitionRanking`,
cCompetitionStageFileList: `competition/cCompetitionStageFile/listByEntity`,
getPaperUploadFile: `exam/exam/paper/question/userAnswer/getPaperUploadFile`,
derive: `${host}competition/cCompetitionStageFile/deriveAll`,
allExperimentalResultsAreDerived: `${host}competition/competition/performance/allExperimentalResultsAreDerived`,
derivedRanking: `${host}competition/competition/rank/derivedRanking`,
@ -508,4 +551,10 @@ export default {
saveMarketing: `nakadai/nakadai/mall/marketing/promotion/save`,
updateMarketing: `nakadai/nakadai/mall/marketing/promotion/update`,
bannerEnableOrDisable: `nakadai/nakadai/mall/marketing/promotion/bannerEnableOrDisable`,
resourceLibrary: `nakadai/resourceLibrary/resourceLibrary`,
resourceDel: `nakadai/resourceLibrary/batchDeletion`,
resourceFind: `nakadai/resourceLibrary/findById`,
resourceSave: `nakadai/resourceLibrary/saveOrUpdate`,
getFileType: `nakadai/resourceLibrary/getFileType`,
};

@ -3,12 +3,12 @@ import { Loading } from 'element-ui'
export default {
//skin:'oxide-dark',
language:'zh_CN',
language: 'zh_CN',
language_url: './styles/tinymce/langs/zh_CN.js',
plugins: 'print powerpaste preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template advcode codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount imagetools textpattern help emoticons autosave autoresize formatpainter',
toolbar: 'code undo redo restoredraft | cut copy powerpaste pastetext | forecolor backcolor headings fontsize lineHeight bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify | \
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 | \
styleselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \
table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | indent2em formatpainter',
table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | indent2em',
style_formats: [
//新增 首行缩进与行高 配置
{
@ -206,7 +206,7 @@ export default {
// template_cdate_format: '[CDATE: %m/%d/%Y : %H:%M:%S]',
// template_mdate_format: '[MDATE: %m/%d/%Y : %H:%M:%S]',
// autosave_ask_before_unload: false,
toolbar_mode : 'wrap',
toolbar_mode: 'wrap',
// automatic_uploads: true,
// images_upload_base_path: '/demo',
// images_upload_url: 'http://10.10.11.7:10000/iasf/sysFiles/upload',
@ -248,7 +248,7 @@ export default {
let input = document.createElement('input');//创建一个隐藏的input
input.setAttribute('type', 'file');
input.setAttribute("accept", ".mp4");
input.onchange = function(){
input.onchange = function () {
let file = this.files[0];
const load = Loading.service()
Oss.upload(file).then(res => {
@ -263,8 +263,8 @@ export default {
}
},
// 初始化事件
setup: function(editor) {
editor.on('init', function(ed) {
setup: function (editor) {
editor.on('init', function (ed) {
// 设置默认字体
ed.target.editorCommands.execCommand("fontName", false, "PingFang SC")
ed.target.editorCommands.execCommand("fontSize", false, "16px")

@ -14,17 +14,17 @@ axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
// 请求拦截器
axios.interceptors.request.use(config => {
let token = sessionStorage.getItem('token')
if(token){
if (token) {
config.headers.token = token
}
let schoolId = store.state.schoolId
if(schoolId) config.headers.schoolId = store.state.schoolId
if (schoolId) config.headers.schoolId = store.state.schoolId
return config;
}, err => {
Message.error({
message: '退出登陆',
onClose: function () {
router.push({name: 'login'});
router.push({ name: 'login' });
}
})
return Promise.reject(err);
@ -35,7 +35,7 @@ let logouted = 0;
axios.interceptors.response.use(
response => {
if (response.status === 200) {
const { status } = response.data
const { status, code, msg } = response.data
if (status) {
// 接口定义的非正常返回的时候,应当处于报错状态
if (status === 10020) {
@ -47,11 +47,27 @@ axios.interceptors.response.use(
} else {
return Promise.resolve(response)
}
} else if (code === 401) {
// 账号互踢
if (!logouted) {
sessionStorage.removeItem('token')
Message.error(msg.includes('顶') ? '您的账号已在其他设备登录,您已被迫下线!' : '登录过期,请重新登录!')
setTimeout(() => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
})
logouted = 0
}, 1500)
logouted = 1
}
} else {
return Promise.resolve(response)
}
} else {
Message.error(response.message,'res');
Message.error(response.message, 'res');
return Promise.reject(response);
}
},
@ -116,7 +132,7 @@ axios.interceptors.response.use(
);
function logouts(){
function logouts () {
store.replaceState({})
localStorage.clear()
sessionStorage.clear()
@ -130,8 +146,8 @@ let tokenStatus = {
/**
* get方法对应get请求
*/
export function get(url, params){
return new Promise((resolve, reject) =>{
export function get (url, params) {
return new Promise((resolve, reject) => {
axios.get(url, {
params: params
})
@ -146,9 +162,9 @@ export function get(url, params){
/**
* post方法对应post请求
*/
export function post(url, params, config) {
export function post (url, params, config) {
return new Promise((resolve, reject) => {
axios.post(url,params, config)
axios.post(url, params, config)
.then(res => {
return resolve(res.data);
})
@ -161,8 +177,8 @@ export function post(url, params, config) {
/**
* delete方法对应delete请求
*/
export function del(url, params){
return new Promise((resolve, reject) =>{
export function del (url, params) {
return new Promise((resolve, reject) => {
axios.delete(url, {
params: params
})
@ -180,8 +196,8 @@ export function post(url, params, config) {
* @param {} url
* @param {*} params
*/
export function put(url, params){
return new Promise((resolve, reject) =>{
export function put (url, params) {
return new Promise((resolve, reject) => {
axios.put(url, params)
.then(res => {
resolve(res.data);

@ -1,38 +1,49 @@
<template>
<div class="wrapper">
<v-head></v-head>
<v-sidebar></v-sidebar>
<Navbar></Navbar>
<div class="layout">
<Sidebar :class="{ show: showSidebar }" :path.sync="path" />
<div class="content-box">
<div class="content">
<transition name="move"
mode="out-in">
<!-- <keep-alive> -->
<transition name="move" mode="out-in">
<router-view></router-view>
<!-- </keep-alive> -->
</transition>
<el-backtop target=".content"></el-backtop>
<el-backtop target=".content-box"></el-backtop>
</div>
</div>
</div>
</template>
<script>
import vHead from '../components/Header.vue';
import vSidebar from '../components/Sidebar.vue';
import Setting from "@/setting";
import util from "@/libs/util";
import vHead from '../components/Header.vue'
import Navbar from '../components/Navbar.vue'
import Sidebar from '../components/Sidebar.vue'
import Setting from "@/setting"
import util from "@/libs/util"
export default {
data () {
return {
tagsList: [],
showSidebar: false,
path: '',
};
},
components: {
vHead,
vSidebar,
Navbar,
Sidebar,
},
watch: {
'$route.path': {
handler (val) {
this.path = val
//
this.showSidebar = ['/configure', '/curriculum', '/information', '/shop', '/market', '/parnerOperation', '/parner', '/match', '/data', '/review', '/theoreticalCourse', '/resourse'].includes(val)
},
immediate: true
}
},
created () {
this.autoLogout()
},
methods: {
// ,退
@ -58,3 +69,27 @@ export default {
}
};
</script>
<style lang="scss" scoped>
.layout {
display: flex;
background: #f5f7fa;
.content-box {
width: calc(100vw - 208px);
padding: 20px;
box-sizing: border-box;
// -webkit-transition: left 0.3s ease-in-out;
// transition: left 0.3s ease-in-out;
}
.sidebar:not(.show) {
margin-left: -200px;
&+.content-box {
width: 100%;
}
}
}
</style>

@ -9,125 +9,93 @@
<div class="ms-login">
<div class="ms-title">
<!-- <p class="title">账号登录</p> -->
<el-menu :default-active="activeIndex"
class="el-menu-demo"
mode="horizontal"
@select="handleSelect">
<el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
<el-menu-item index="1">账号登录</el-menu-item>
<el-menu-item index="2">手机号/邮箱登录</el-menu-item>
</el-menu>
<el-form v-show="activeIndex==='1'"
:model="param"
:rules="rules"
ref="login"
label-width="0px"
<el-form v-show="activeIndex === '1'" :model="param" :rules="rules" ref="login" label-width="0px"
style="margin-top: 20px">
<el-form-item prop="account">
<el-input @blur="blur"
v-model="param.account"
placeholder="请输入账号"></el-input>
<el-input @blur="blur" v-model="param.account" placeholder="请输入账号"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input type="password"
placeholder="请输入密码"
v-model="param.password">
<el-input type="password" placeholder="请输入密码" v-model="param.password">
</el-input>
</el-form-item>
<el-form-item prop="code"
v-if="showVerify">
<el-input placeholder="请输入验证码"
v-model="param.code"
@keyup.enter.native="submitForm()">
<el-form-item prop="code" v-if="showVerify">
<el-input placeholder="请输入验证码" v-model="param.code" @keyup.enter.native="submitForm()">
</el-input>
<img @click="blur"
:src="verificationIMG"
class="verification"
alt="">
<img @click="blur" :src="verificationIMG" class="verification" alt="">
</el-form-item>
<div style="width:100%;display:flex;justify-content: flex-end;">
<el-button type="text"
class="forget">忘记密码?</el-button>
<el-button type="text" class="forget">忘记密码?</el-button>
</div>
<div class="login-btn">
<el-button type="primary"
@click="submitForm()">马上登录</el-button>
<el-button type="primary" @click="submitForm()">马上登录</el-button>
</div>
</el-form>
<el-form v-show="activeIndex==='2'"
:model="phoneOrEmail"
:rules="phoneOrEmailrules"
ref="phoneOrEmail"
label-width="0px"
style="margin-top: 20px">
<el-form v-show="activeIndex === '2'" :model="phoneOrEmail" :rules="phoneOrEmailrules" ref="phoneOrEmail"
label-width="0px" style="margin-top: 20px">
<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 prop="password">
<el-input type="password"
placeholder="请输入密码"
v-model="phoneOrEmail.password">
<el-input type="password" placeholder="请输入密码" v-model="phoneOrEmail.password">
</el-input>
</el-form-item>
<el-form-item prop="code"
v-if="showPhoneVerify">
<el-input placeholder="请输入验证码"
v-model="phoneOrEmail.code"
@keyup.enter.native="submitForm('phone')">
<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="">
<img @click="phoneBlur" :src="PhoneVerificationIMG" class="verification" alt="">
</el-form-item>
<div style="width:100%;display:flex;justify-content: flex-end;">
<el-button type="text"
class="forget">忘记密码?</el-button>
<el-button type="text" class="forget">忘记密码?</el-button>
</div>
<div class="login-btn">
<el-button type="primary"
@click="submitForm('phone')">马上登录</el-button>
<el-button type="primary" @click="submitForm('phone')">马上登录</el-button>
</div>
</el-form>
</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>
<el-form ref="form"
label-width="60px">
<el-form ref="form" label-width="60px">
<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 label="验证码">
<div style="display:flex;">
<el-input v-model="phoneCode"
placeholder="请输入验证码"
maxlength="6"></el-input>
<el-button style="margin-left:10px"
@click="sendPhoneCode"
:disabled="phoneDisabled">{{phoneBtnText}}</el-button>
<el-input v-model="phoneCode" placeholder="请输入验证码" maxlength="6"></el-input>
<el-button style="margin-left:10px" @click="sendPhoneCode" :disabled="phoneDisabled">{{ phoneBtnText
}}</el-button>
</div>
</el-form-item>
</el-form>
<span slot="footer"
class="dialog-footer">
<span slot="footer" class="dialog-footer">
<el-button @click="phoneVisible = false"> </el-button>
<el-button type="primary"
@click="phoneSubmit"> </el-button>
<el-button type="primary" @click="phoneSubmit"> </el-button>
</span>
</el-dialog>
<v-footer class="footer"
ref="footer"></v-footer>
<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>
</div>
</template>
@ -135,6 +103,8 @@
import vFooter from '../components/Footer'
import Setting from '@/setting'
import addRoutes from '@/libs/route/addRoutes'
import CryptoJS from 'crypto-js'
import JSEncrypt from 'jsencrypt'
export default {
data: function () {
var regPhoneOrEmail = (rule, value, callback) => {//
@ -162,7 +132,6 @@ export default {
platform: 3,
random: '',
distinguish: 1,
type: 2
},
rules: {
account: [{ required: true, message: '请输入账号', trigger: 'blur' }],
@ -174,16 +143,15 @@ export default {
showPhoneVerify: true,// -
PhoneVerificationIMG: '',//
phoneOrEmail: {
account: '',
workNumber: '',
password: '',
code: '',
platform: 3,
random: '',
distinguish: 2,
type: 2
distinguish: 1,
},
phoneOrEmailrules: {
account: [{ validator: regPhoneOrEmail, trigger: 'blur' }],
workNumber: [{ validator: regPhoneOrEmail, trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
code: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
},
@ -194,8 +162,11 @@ export default {
phoneDisabled: false,
phoneBtnText: '发送验证码',
phoneTimer: '',
phoneOpener: ''
phoneOpener: '',
userVisible: false,
users: [],
};
},
components: {
@ -229,27 +200,29 @@ export default {
let param = val === 'phone' ? this.phoneOrEmail : this.param
this.$refs[ref].validate(valid => {
if (valid) {
this.$post(this.api.logins, param).then(res => {
const { message } = res
sessionStorage.setItem('token', res.data.token)
this.$get(`${this.api.getUserRolesPermissionMenu}?platformId=${Setting.platformId}`).then(res => {
const list = res.permissionMenu
addRoutes(res.permissionMenu[0].children)
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()
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 => {
if (err.status === 30001) {
this.phoneVisible = true
} else if (err.status == 10004) {
} else if (err.status == 10004 || err.status == 10005) {
param.code = ''
this.blur()
}
});
@ -258,7 +231,55 @@ export default {
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
path: '/workbench'
});
localStorage.setItem('ms_username', this.param.username);
} catch (e) {
if (e.status === 500) {
sessionStorage.clear()
}
}
},
blur () {
this.param.random = Math.floor(Math.random() * 999999999)
@ -348,6 +369,7 @@ export default {
background-image: url(../assets/img/login-bg.png);
background-size: 100%;
}
.ms-title {
width: 548px;
position: absolute;
@ -355,6 +377,7 @@ export default {
top: 30px;
transform: translate(-50%, 0);
}
/deep/ .ms-login {
position: relative;
width: 1200px;
@ -364,12 +387,14 @@ export default {
box-shadow: 0px 0px 79px 0px rgba(11, 15, 65, 0.36);
background-repeat: no-repeat;
overflow: hidden;
.el-input__inner {
height: 80px;
line-height: 80px;
border: 1px solid rgba(220, 220, 220, 1);
border-radius: 2px;
}
.verification {
position: absolute;
top: 1px;
@ -379,14 +404,17 @@ export default {
cursor: pointer;
}
}
.title {
font-size: 16px;
text-align: center;
font-weight: bold;
}
.login-btn {
text-align: center;
}
.login-btn button {
width: 100%;
height: 88px;
@ -396,20 +424,24 @@ export default {
box-shadow: 0px 7px 27px 0px rgba(50, 129, 255, 0.51);
border-radius: 10px;
}
.login-tips {
text-align: center;
color: #999;
font-weight: bold;
}
.forget {
margin-bottom: 28px;
text-align: right;
color: #999;
font-weight: bold;
&:hover {
color: #0092ff;
}
}
.thirdParty {
width: 100%;
display: flex;
@ -426,27 +458,33 @@ export default {
align-items: center;
font-size: 18px;
}
.logo {
width: 171px;
height: 40px;
margin-left: 20px;
}
img {
width: 100%;
height: 100%;
}
.header_title {
width: 33%;
display: flex;
justify-content: space-between;
align-items: center;
}
.header_title a {
cursor: pointer;
}
.header_title a:hover {
color: blueviolet;
}
.nul {
width: 80px;
margin-right: 30px;
@ -458,26 +496,72 @@ img {
border-bottom: 0;
background-color: transparent;
}
.tips {
margin: -20px 0 20px 5px;
font-size: 14px;
text-align: center;
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) {
/deep/.ms-login {
width: 1000px;
.el-input__inner {
height: 50px;
line-height: 50px;
}
.verification {
height: 48px;
}
}
.ms-title {
width: 480px;
}
.login-btn button {
height: 60px;
}

@ -2,28 +2,19 @@
<div>
<el-row :gutter="20">
<el-col :span="24">
<el-card shadow="hover"
class="mgb20">
<el-card shadow="hover" class="mgb20">
<div class="flex-between">
<div class="per_title"
v-preventReClick
@click="back">
<div class="per_title" v-preventReClick @click="back">
<i class="el-icon-arrow-left"></i>
<span class="per_back">返回</span>
<span class="per_school"
v-text="form.cid ? '编辑课程' : '新建课程'"></span>
<span class="per_school" v-text="form.cid ? '编辑课程' : '新建课程'"></span>
</div>
<el-button type="primary"
round
class="mag"
v-preventReClick
@click="saveAdd">确定
<el-button type="primary" round class="mag" v-preventReClick @click="saveAdd">确定
</el-button>
</div>
</el-card>
<el-card shadow="hover"
class="mgb20 ">
<el-card shadow="hover" class="mgb20 ">
<div class="flex-center mgb20">
<p class="addhr_tag"></p>
<span>课程信息</span>
@ -31,112 +22,65 @@
<div class="border-b-dashed"></div>
<div>
<el-form :model="form"
:rules="rules"
ref="form"
label-width="100px">
<el-col :span="6"
:offset="5">
<el-form-item label="课程名称"
prop="curriculumName">
<el-input placeholder="请输入课程名称"
v-model.trim="form.curriculumName"></el-input>
<el-form :model="form" :rules="rules" ref="form" label-width="100px">
<el-col :span="6" :offset="5">
<el-form-item label="课程名称" prop="curriculumName">
<el-input placeholder="请输入课程名称" v-model.trim="form.curriculumName"></el-input>
</el-form-item>
<el-form-item label="学科类别"
prop="categoryId">
<el-select v-model="form.categoryId"
clearable
placeholder="请选择学科类别"
@change="getProfessionalClass()"
<el-form-item label="学科类别" prop="categoryId">
<el-select v-model="form.categoryId" clearable placeholder="请选择学科类别" @change="getProfessionalClass()"
@clear="clearsubjectType()">
<el-option v-for="(item,index) in subjectList"
:key="index"
:label="item.disciplineName"
<el-option v-for="(item, index) in subjectList" :key="index" :label="item.disciplineName"
:value="item.disciplineId"></el-option>
</el-select>
</el-form-item>
<el-form-item label="专业"
prop="professionalId">
<el-select v-model="form.professionalId"
clearable
placeholder="请选择专业"
<el-form-item label="专业" prop="professionalId">
<el-select v-model="form.professionalId" clearable placeholder="请选择专业"
:disabled="form.professionalCategoryId ? false : true">
<el-option v-for="(item,index) in ProfessionalList"
:key="index"
:label="item.professionalName"
<el-option v-for="(item, index) in ProfessionalList" :key="index" :label="item.professionalName"
:value="item.professionalId"></el-option>
</el-select>
</el-form-item>
<el-form-item label="供应厂商"
prop="supplier">
<el-select v-model="form.supplier"
clearable
placeholder="请选择供应厂商"
multiple>
<el-option v-for="(item, i) in suppliers"
:key="i"
:label="item.supplierName"
<el-form-item label="供应厂商" prop="supplier">
<el-select v-model="form.supplier" clearable placeholder="请选择供应厂商" multiple>
<el-option v-for="(item, i) in suppliers" :key="i" :label="item.supplierName"
:value="item.supplierId"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6"
:offset="2">
<el-form-item label="课程类别"
prop="curriculumType">
<el-select v-model="form.curriculumType"
clearable
placeholder="请选择课程类型">
<el-option label="理论课程"
:value="0"></el-option>
<el-option label="实训课程"
:value="1"></el-option>
<el-col :span="6" :offset="2">
<el-form-item label="课程类别" prop="curriculumType">
<el-select v-model="form.curriculumType" clearable placeholder="请选择课程类型">
<el-option label="理论课程" :value="0"></el-option>
<el-option label="实训课程" :value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item label="专业类"
prop="professionalCategoryId">
<el-select v-model="form.professionalCategoryId"
clearable
placeholder="请选择专业类"
:disabled="form.categoryId ? false : true"
@change="getProfessional()"
<el-form-item label="专业类" prop="professionalCategoryId">
<el-select v-model="form.professionalCategoryId" clearable placeholder="请选择专业类"
:disabled="form.categoryId ? false : true" @change="getProfessional()"
@clear="clearProfessionalClass()">
<el-option v-for="(item,index) in ProfessionalClassList"
:key="index"
:label="item.professionalClassName"
:value="item.professionalClassId"></el-option>
<el-option v-for="(item, index) in ProfessionalClassList" :key="index"
:label="item.professionalClassName" :value="item.professionalClassId"></el-option>
</el-select>
</el-form-item>
<el-form-item label="预计课时"
prop="expectedCourse">
<el-select v-model="form.expectedCourse"
clearable
placeholder="请选择预计课时">
<el-option label="32课时"
value="32课时"></el-option>
<el-option label="64课时"
value="64课时"></el-option>
<el-form-item label="预计课时" prop="expectedCourse">
<el-select v-model="form.expectedCourse" clearable placeholder="请选择预计课时">
<el-option label="32课时" value="32课时"></el-option>
<el-option label="64课时" value="64课时"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="14"
:offset="5">
<el-form-item label="课程简介"
prop="briefIntroduction">
<el-input type="textarea"
:autosize="{ minRows: 4 }"
placeholder="请输入课程简介"
<el-col :span="14" :offset="5">
<el-form-item label="课程简介" prop="briefIntroduction">
<el-input type="textarea" :autosize="{ minRows: 4 }" placeholder="请输入课程简介"
v-model.trim="form.briefIntroduction"></el-input>
</el-form-item>
<el-form-item label="教学目标"
prop="teachingObjectives">
<el-input type="textarea"
:autosize="{ minRows: 4 }"
placeholder="请输入教学目标"
<el-form-item label="教学目标" prop="teachingObjectives">
<el-input type="textarea" :autosize="{ minRows: 4 }" placeholder="请输入教学目标"
v-model.trim="form.teachingObjectives"></el-input>
</el-form-item>
</el-col>
@ -145,8 +89,7 @@
</el-card>
<!-- 练习项目配置 -->
<el-card shadow="hover"
class="mgb20">
<el-card shadow="hover" class="mgb20">
<div class="mgb20 flex-between">
<div class="flex-center ">
<p class="addhr_tag"></p>
@ -154,61 +97,36 @@
</div>
<div>
<el-button @click="handleBatchDelete(0)">批量移除</el-button>
<el-button @click="handleConfig(0)"
icon="el-icon-plus"
circle></el-button>
<el-button @click="handleConfig(0)" icon="el-icon-plus" circle></el-button>
</div>
</div>
<div class="border-b-dashed"></div>
<div>
<el-table :data="practiceData"
class="table"
stripe
header-align="center"
max-height="400"
<el-table :data="practiceData" class="table" header-align="center" max-height="400"
@selection-change="handleSelectionPractice">
<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 prop="projectName"
label="项目名称"
align="center"></el-table-column>
<el-table-column prop="remark"
label="备注名称"
align="center"></el-table-column>
<el-table-column prop="applicationName"
label="系统名称"
align="center">
<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 prop="projectName" label="项目名称" align="center">
<template slot-scope="scope">
{{ scope.row.applicationName || systemAll.find(e => e.systemId == scope.row.systemId).systemName }}
{{ scope.row.projectName || scope.row.paperName }}
</template>
</el-table-column>
<el-table-column label="排序"
align="center"
width="100">
<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">
<template slot-scope="scope">
<el-input v-model.trim="scope.row.sort"
@input="practiceSortChange(scope.row, scope.$index)"></el-input>
</template>
</el-table-column>
<el-table-column label="展示控制"
align="center"
width="100">
<el-table-column label="展示控制" align="center" width="100">
<template slot-scope="scope">
<el-switch v-model="scope.row.isShow"
:active-value="0"
:inactive-value="1"
<el-switch v-model="scope.row.isShow" :active-value="0" :inactive-value="1"
:disabled="scope.row.disabled">
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作"
align="center"
width="100">
<el-table-column label="操作" align="center" width="100">
<template slot-scope="scope">
<el-button :disabled="scope.row.disabled"
@click.native.prevent="handleDelete(scope.$index, practiceData)">移除
@ -220,8 +138,7 @@
</el-card>
<!-- 考核项目配置 -->
<el-card shadow="hover"
class="mgb20">
<el-card shadow="hover" class="mgb20">
<div class="mgb20 flex-between">
<div class="flex-center ">
<p class="addhr_tag"></p>
@ -229,62 +146,37 @@
</div>
<div>
<el-button @click="handleBatchDelete(1)">批量移除</el-button>
<el-button @click="handleConfig(1)"
icon="el-icon-plus"
circle></el-button>
<el-button @click="handleConfig(1)" icon="el-icon-plus" circle></el-button>
</div>
</div>
<div class="border-b-dashed"></div>
<!-- 实训配置 -->
<div>
<el-table :data="assessmentData"
class="table"
stripe
header-align="center"
max-height="400"
<el-table :data="assessmentData" class="table" header-align="center" max-height="400"
@selection-change="handleSelectionAssessment">
<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 prop="projectName"
label="项目名称"
align="center"></el-table-column>
<el-table-column prop="remark"
label="备注名称"
align="center"></el-table-column>
<el-table-column prop="applicationName"
label="系统名称"
align="center">
<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 prop="projectName" label="项目名称" align="center">
<template slot-scope="scope">
{{ scope.row.applicationName || systemAll.find(e => e.systemId == scope.row.systemId).systemName }}
{{ scope.row.projectName || scope.row.paperName }}
</template>
</el-table-column>
<el-table-column label="排序"
align="center"
width="100">
<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">
<template slot-scope="scope">
<el-input v-model.trim="scope.row.sort"
@input="assessmentSortChange(scope.row, scope.$index)"></el-input>
</template>
</el-table-column>
<el-table-column label="展示控制"
align="center"
width="100">
<el-table-column label="展示控制" align="center" width="100">
<template slot-scope="scope">
<el-switch v-model="scope.row.isShow"
:active-value="0"
:inactive-value="1"
<el-switch v-model="scope.row.isShow" :active-value="0" :inactive-value="1"
:disabled="scope.row.disabled">
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作"
align="center"
width="100">
<el-table-column label="操作" align="center" width="100">
<template slot-scope="scope">
<el-button :disabled="scope.row.disabled"
@click.native.prevent="handleDelete(scope.$index, assessmentData)">移除</el-button>
@ -295,8 +187,7 @@
</el-card>
<!-- 大赛项目配置 -->
<el-card shadow="hover"
class="mgb20">
<el-card shadow="hover" class="mgb20">
<div class="mgb20 flex-between">
<div class="flex-center ">
<p class="addhr_tag"></p>
@ -304,59 +195,36 @@
</div>
<div>
<el-button @click="handleBatchDelete(2)">批量移除</el-button>
<el-button @click="handleConfig(2)"
icon="el-icon-plus"
circle></el-button>
<el-button @click="handleConfig(2)" icon="el-icon-plus" circle></el-button>
</div>
</div>
<div class="border-b-dashed"></div>
<!-- 实训配置 -->
<div>
<el-table :data="matches"
class="table"
stripe
header-align="center"
max-height="400"
<el-table :data="matches" class="table" header-align="center" max-height="400"
@selection-change="handleSelectionMatch">
<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 prop="projectName"
label="项目名称"
align="center"></el-table-column>
<el-table-column prop="applicationName"
label="系统名称"
align="center">
<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 prop="projectName" label="项目名称" align="center">
<template slot-scope="scope">
{{ scope.row.applicationName || systemAll.find(e => e.systemId == scope.row.systemId).systemName }}
{{ scope.row.projectName || scope.row.paperName }}
</template>
</el-table-column>
<el-table-column label="排序"
align="center"
width="100">
<el-table-column prop="systemName" label="系统名称" align="center"></el-table-column>
<el-table-column label="排序" align="center" width="100">
<template slot-scope="scope">
<el-input v-model.trim="scope.row.sort"
@input="assessmentSortChange(scope.row, scope.$index)"></el-input>
</template>
</el-table-column>
<el-table-column label="展示控制"
align="center"
width="100">
<el-table-column label="展示控制" align="center" width="100">
<template slot-scope="scope">
<el-switch v-model="scope.row.isShow"
:active-value="0"
:inactive-value="1"
<el-switch v-model="scope.row.isShow" :active-value="0" :inactive-value="1"
:disabled="scope.row.disabled">
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作"
align="center"
width="100">
<el-table-column label="操作" align="center" width="100">
<template slot-scope="scope">
<el-button :disabled="scope.row.disabled"
@click.native.prevent="handleDelete(scope.$index, matches)">移除</el-button>
@ -370,29 +238,20 @@
</el-row>
<!-- 配置弹窗 -->
<el-dialog :visible.sync="configVisible"
width="1200px"
center
custom-class="config-dia">
<el-dialog :visible.sync="configVisible" width="1200px" center custom-class="config-dia">
<div class="config-wrap">
<div class="item system">
<div class="title-wrap flex-center">
<p class="addhr_tag"></p>
<span>系统列表</span>
</div>
<el-input placeholder="请输入系统名称"
prefix-icon="el-icon-search"
v-model.trim="systemKeyword"
<el-input placeholder="请输入系统名称" prefix-icon="el-icon-search" v-model.trim="systemKeyword"
clearable></el-input>
<ul class="systems">
<li v-for="(item, i) in systems"
:key="i"
:title="item.systemName">
<el-checkbox v-model="item.check"
@change="val => systemChange(val, item)"></el-checkbox>
<div :class="['name', {active: curSystem == item.systemId}]"
@click="getProject(item)">
<li v-for="(item, i) in systems" :key="i" :title="item.systemName">
<el-checkbox v-model="item.check" @change="val => systemChange(val, item)"></el-checkbox>
<div :class="['name', { active: curSystem == item.systemId }]" @click="getProject(item)">
<span>{{ item.systemName }}</span>
<i class="el-icon-arrow-right"></i>
</div>
@ -405,21 +264,15 @@
<p class="addhr_tag"></p>
<span>项目列表</span>
</div>
<el-input placeholder="请输入项目名称"
prefix-icon="el-icon-search"
v-model.trim="projectKeyword"
<el-input placeholder="请输入项目名称" prefix-icon="el-icon-search" v-model.trim="projectKeyword"
clearable></el-input>
<ul class="systems">
<el-checkbox v-if="projects.length"
v-model="checkAll"
label="全选"
<el-checkbox v-if="projects.length" v-model="checkAll" label="全选"
@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"
: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>
</li>
</ul>
@ -430,46 +283,25 @@
<p class="addhr_tag"></p>
<span>已选择项目{{ checkeds.length }}</span>
</div>
<el-input style="width: 200px;margin-bottom: 20px;"
placeholder="请输入项目名称"
prefix-icon="el-icon-search"
v-model.trim="checkedKeyword"
clearable></el-input>
<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 prop="applicationName"
label="系统名称"
align="center">
<el-input style="width: 200px;margin-bottom: 20px;" placeholder="请输入项目名称" prefix-icon="el-icon-search"
v-model.trim="checkedKeyword" clearable></el-input>
<el-table :data="checkeds" class="table" header-align="center" max-height="470">
<el-table-column type="index" width="55" label="序号" align="center"></el-table-column>
<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">
{{ scope.row.applicationName || systemAll.find(e => e.systemId == scope.row.systemId).systemName }}
{{ scope.row.type === 1 ? '流程类' : scope.row.type === 3 ? '理论' : '编程类' }}
</template>
</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">
{{ scope.row.type ? '流程类' : '编程类' }}
{{ scope.row.projectName || scope.row.paperName }}
</template>
</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">
<i :class="['el-icon-delete rm', {disabled: scope.row.disabled}]"
<i :class="['el-icon-delete rm', { disabled: scope.row.disabled }]"
@click="delProject(scope.$index, scope.row)"></i>
</template>
</el-table-column>
@ -477,11 +309,9 @@
</div>
</div>
<span slot="footer"
class="dialog-footer">
<span slot="footer" class="dialog-footer">
<el-button @click="configVisible = false"> </el-button>
<el-button type="primary"
@click="handleConfirm"> </el-button>
<el-button type="primary" @click="handleConfirm"> </el-button>
</span>
</el-dialog>
</div>
@ -585,7 +415,6 @@ export default {
systemChecked: [],
curSystem: '',
projects: [],
projectAll: [],
projectKeyword: '',
checkedKeyword: '',
checkeds: [],
@ -612,7 +441,7 @@ export default {
projectKeyword: function (val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.filterProject();
this.getProject();
}, 500);
},
checkedKeyword: function (val) {
@ -747,6 +576,7 @@ export default {
this.pageNo = 1;
this.getConfig();
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 () {
@ -779,26 +609,23 @@ export default {
}).catch(err => { })
},
//
getProject (item) {
async getProject (item, fromSystemChange) {
const checked = this.checkeds
this.curSystem = item.systemId
this.$get(`${this.api.getInternalProjectBySystemId}?permissions=${this.permissions}&systemId=${item.systemId}`).then(res => {
this.projectAll = JSON.parse(JSON.stringify(res)) //
if (item) this.curSystem = item.systemId
let res
if (!fromSystemChange) {
res = await this.$get(`${this.api.getInternalProjectBySystemId}?permissions=${this.permissions}&systemId=${this.curSystem}&keyword=${this.projectKeyword}`)
}
const result = []
res.map(e => {
const projects = fromSystemChange ? this.projects : res
projects.map(e => {
//
const include = checked.some(n => n.projectId == e.projectId && n.systemId == e.systemId)
const include = checked.some(n => (e.projectId && n.projectId == e.projectId && n.systemId == e.systemId) || (e.paperId && n.paperId == e.paperId))
e.check = include
result.push(e)
})
this.checkAll = !result.filter(e => !e.check).length
this.projects = result
}).catch(err => { })
},
//
filterProject () {
const val = this.projectKeyword
this.projects = this.projectAll.filter(e => e.projectName.includes(val))
},
//
systemChange (val, item) {
@ -810,7 +637,7 @@ export default {
})
}
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 (!this.mulSystem) {
@ -818,18 +645,18 @@ export default {
item.check = true
}
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)
}
})
} else {
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)
})
}
this.checkedAll = JSON.parse(JSON.stringify(checkeds)) //
this.getProject(item)
this.getProject(item, 1)
}).catch(err => { })
},
//
@ -841,8 +668,8 @@ export default {
},
//
projectChange (val, item) {
const { systemId } = item
const i = this.checkeds.findIndex(e => e.projectId == item.projectId && e.systemId == systemId)
const { systemId, paperId } = item
const i = this.checkeds.findIndex(e => (item.projectId && e.projectId == item.projectId && e.systemId == systemId) || (paperId && paperId == e.paperId))
// push
if (val) {
this.checkeds.push(item)
@ -855,12 +682,11 @@ export default {
})
this.checkAll = !this.projects.find(e => !e.check) //
this.checkedAll = JSON.parse(JSON.stringify(this.checkeds)) //
console.log("🚀 ~ file: AddCurriculum.vue ~ line 728 ~ projectChange ~ checkedAll", this.checkeds, item)
},
//
filterChecked () {
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) {
@ -871,9 +697,9 @@ export default {
this.checkeds.splice(i, 1)
// checkdisabled
if (e.systemId == this.curSystem) {
const { projectId } = e
const { projectId, paperId } = e
this.projects.map(n => {
if (n.projectId == projectId) {
if ((projectId && n.projectId == projectId) || (paperId && n.paperId == paperId)) {
n.check = false
}
})
@ -992,7 +818,8 @@ export default {
form.systemIdByPractice = this.practiceData.map(i => {
let obj = {
isShow: i.isShow,
projectId: i.projectId,
projectId: i.projectId || '',
paperId: i.paperId || '',
sort: Number(i.sort),
systemId: i.systemId
};
@ -1008,6 +835,7 @@ export default {
let obj = {
isShow: i.isShow,
projectId: i.projectId,
paperId: i.paperId || '',
sort: Number(i.sort),
systemId: i.systemId
};
@ -1020,6 +848,7 @@ export default {
let obj = {
isShow: i.isShow,
projectId: i.projectId,
paperId: i.paperId || '',
sort: Number(i.sort),
systemId: i.systemId
};
@ -1034,6 +863,7 @@ export default {
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
debugger
if (form.cid) {
this.$post(this.api.modifyCourse, form).then((res) => {
this.$message.success("编辑成功");
@ -1093,6 +923,7 @@ export default {
<style lang="scss" scoped>
$avatar-width: 104px;
/deep/ .avatar-uploader {
.el-upload {
position: relative;
@ -1151,28 +982,34 @@ $avatar-width: 104px;
}
}
}
.settlement {
display: flex;
align-items: center;
margin-bottom: 10px;
.label {
margin-right: 10px;
white-space: nowrap;
color: #606266;
font-size: 14px;
}
.el-input {
width: 150px;
margin-right: 30px;
}
}
/deep/.config-dia {
.config-wrap {
display: flex;
}
.title-wrap {
margin-bottom: 15px;
}
.item {
width: 250px;
max-height: 600px;
@ -1180,18 +1017,22 @@ $avatar-width: 104px;
margin-right: 20px;
overflow: hidden;
}
.system {
background-color: #f9f9f9;
}
.systems {
margin-top: 10px;
max-height: 520px;
overflow: auto;
li {
display: flex;
align-items: center;
margin: 10px 0;
}
.name {
display: inline-flex;
flex: 1;
@ -1199,10 +1040,12 @@ $avatar-width: 104px;
align-items: center;
margin-left: 5px;
cursor: pointer;
&.active,
&:hover {
color: #9076ff;
color: #062c87;
}
span {
max-width: 200px;
text-overflow: ellipsis;
@ -1211,20 +1054,25 @@ $avatar-width: 104px;
}
}
}
.checked {
flex: 1;
width: auto;
.el-table .cell {
font-size: 12px;
}
}
.rm {
font-size: 14px;
cursor: pointer;
&.disabled {
color: #ccc;
cursor: not-allowed;
}
&:hover {
color: #17161f;
}

@ -1,204 +0,0 @@
<template>
<div>
<el-row :gutter="20">
<el-col :span="24">
<el-card shadow="hover" class="mgb20">
<div class="flex-between">
<div class="per_title" @click="goback()">
<i class="el-icon-arrow-left"></i>
<span class="per_back">返回</span>
<span class="per_school">添加环节</span>
</div>
<div>
<el-button type="primary" round class="mag" @click="saveAdd('form')">确定
</el-button>
</div>
</div>
</el-card>
<el-card shadow="hover" class="mgb20">
<div class="flex-between mgb20 user_header">
<div class="flex-center">
<p class="addhr_tag"></p>
<span>环节1.1</span>
</div>
<el-button type="primary" round class="mag" @click="addcourse()">添加环节</el-button>
</div>
<div>
<el-form :model="form" ref="form" label-width="120px" class="courseware">
<ul class="mgb20">
<li v-for="(item,index) in form.courseList" :key="index" class="flex-between">
<div style="width: 50%;">
<el-form-item label="环节名称" :prop="'courseList.' + index + '.linkName'"
:rules="{required: true, message: '请输入项目课件', trigger: 'blur'}">
<el-input placeholder="请输入项目课件" v-model="item.linkName"></el-input>
</el-form-item>
<el-form-item label="资源添加" :prop="'courseList.' + index + '.fileLink'"
:rules="{required: true, message: '请添加文件', trigger: 'blur'}">
<el-upload
class="link_upload"
:headers="{token}"
:action="api.uploadFiles"
:on-remove="(file, fileList)=>{return handleRemove(file, fileList, index)}"
:on-error="uploadError"
:on-success="(response, file, fileList)=>{return uploadSuccess(response, file, fileList, index)}"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:file-list="item.uploadList">
<el-button size="medium" type="primary" icon="el-icon-upload"
class="uploadTitle">点击上传
</el-button>
</el-upload>
</el-form-item>
</div>
<div>
<el-button size="medium" type="primary" @click="delCourse(index)">删除课件
</el-button>
</div>
</li>
</ul>
</el-form>
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
data() {
return {
token: this.$store.state.loginToken,
form: {
courseList: [{
projectId: this.$store.state.systemId,
courseId: this.$store.state.courseId,
linkName: "",
fileLink: "",
uploadList: []
}]
}
};
},
mounted() {
this.getData();
},
methods: {
getData() {
let data = {
projectId: this.form.courseList[0].projectId,
courseId: this.form.courseList[0].courseId
};
this.$get(this.api.queryLinkDetails, data).then((res) => {
res.message.map(e => {
var arr = [];
arr.push({ name: e.linkName, url: e.fileLink });
this.$set(e, "uploadList", arr);
});
this.form.courseList = res.message;
}).catch((res) => {
});
},
saveAdd(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
var arr = this.form.courseList.map(v => {
var obj = {
...v
};
delete obj.uploadList;
return obj;
});
let data = {
courseLink: arr
};
this.$post(this.api.addCourseLink, data).then((res) => {
this.$message.success("添加成功!");
this.goback();
}).catch((res) => {
});
}
});
},
addcourse() {
this.form.courseList = this.form.courseList.concat({
projectId: this.$store.state.systemId,
courseId: this.$store.state.courseId,
linkName: "",
fileLink: "",
uploadList: []
});
},
//
handleExceed(files, fileList) {
this.$message.warning(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
);
},
uploadSuccess(response, file, fileList, idx) {
this.form.courseList[idx].uploadList.push({ name: file.name, url: response.message.fileUrl });
this.form.courseList[idx].fileLink = response.message.fileUrl;
},
uploadError(err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
});
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}`);
},
handleRemove(file, fileList, idx) {
let uploadList = this.form.courseList[idx].uploadList;
uploadList.forEach((item, index) => {
if (file.name == item.name) {
uploadList.splice(index, 1);
}
});
},
delCourse(index) {
this.$confirm("确定要删除该课件吗?", "提示", {
type: "warning"
})
.then(() => {
this.form.courseList.splice(index, 1);
this.$message.success("删除成功");
})
.catch(() => {
});
},
goback() {
this.$router.go(-1);
}
}
};
</script>
<style scoped>
/* .courseware ul .el-input{
width: 30%;
} */
.courseware ul li {
margin-top: 20px;
padding: 0 0 10px 0;
border-bottom: 1px dashed #eee;
}
.courseware ul li:first-child {
margin-top: 0;
}
.courseware ul li:last-child {
border-bottom: none;
}
.uploadTitle {
height: 40px !important;
font-size: 16px;
}
</style>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,610 @@
<template>
<el-drawer title="添加系统资源" :visible.sync="sourceVisible" size="1200px" :close-on-click-modal="false"
custom-class="source-dia" @closed="closeDia">
<div class="overflow" v-loading="loading">
<div class="left">
<div class="tabs mgb20">
<a class="item" v-for="(item, i) in tabs" :key="i" :class="{ active: i == active }" @click="tabChange(i)">{{
item
}}</a>
</div>
<template v-if="active !== 'tab3'">
<el-input class="mgb10" style="width: 300px" placeholder="请输入资源名称" prefix-icon="el-icon-search"
v-model="keyword" clearable></el-input>
<div class="course">
<div v-for="(course, i) in course" :key="i" class="item">
<div class="line">
<i :class="`el-icon-caret-right arrow ${course.shrink ? 'active' : ''}`"
@click="course.shrink = !course.shrink"></i>
<el-checkbox class="check" v-model="course.check" @change="checkCourse(course)"></el-checkbox>
<img v-if="course.coverUrl" class="cover" :src="course.coverUrl" alt="">
<span class="course-name">{{ course.curriculumName || course.courseName }}</span>
</div>
<div v-if="course.shrink" class="chapters">
<!-- 章节 -->
<div v-for="(chapter, j) in course.chapters" :key="j" class="">
<div class="line">
<i :class="`el-icon-caret-right arrow ${chapter.shrink ? 'active' : ''}`"
@click="chapter.shrink = !chapter.shrink"></i>
<el-checkbox class="check" v-model="chapter.check" @change="checkChapter(chapter, course)">{{
chapter.name
}}</el-checkbox>
</div>
<!-- 小节 -->
<div v-if="chapter.shrink" class="sections">
<div v-for="(section, k) in chapter.subsections" :key="k" class="line">
<el-checkbox class="check" v-model="section.check" @change="checkSection(section, chapter)">
<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'"
src="@/assets/img/exts/word.png" alt="">
<img v-else-if="section.fileType === 'xlsx' || section.fileType === 'xls'"
src="@/assets/img/exts/excel.png" alt="">
<img v-else-if="section.fileType === 'txt'" src="@/assets/img/exts/txt.png" 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 }}</el-checkbox>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<!-- 文件素材 -->
<div v-else class="materials">
<div class="types">
<div class="flex-center m-b-10">
<p class="addhr_tag"></p>
<span>资源类型</span>
</div>
<ul class="lines">
<li v-for="(item, i) in sourceType" :key="i" :class="['line', { active: curType === item.name }]"
@click="checkType(item)">{{ item.name }}</li>
</ul>
</div>
<div class="sources">
<div class="flex-center m-b-10">
<p class="addhr_tag"></p>
<span>资源列表</span>
</div>
<el-input class="m-b-10" placeholder="请输入资源名称" prefix-icon="el-icon-search" v-model="keyword"
clearable></el-input>
<ul class="lines">
<el-checkbox v-if="sources.length" v-model="checkAll" label="全选" @change="checkAllChange"></el-checkbox>
<li v-for="(item, i) in sources" :key="i" class="line">
<el-checkbox v-model="item.check" :label="item.resourceName" @change="sourceChange(item)"></el-checkbox>
</li>
</ul>
</div>
</div>
</div>
<div class="right">
<div v-if="$parent.curSection.id" class="m-b-20">
<p class="total m-b-10">原资源共1个</p>
<div v-html="$parent.curSection.name"></div>
</div>
<template v-if="checked.length">
<div class="flex-between m-b-10">
<p class="total">已选资源{{ checked.length }}</p>
<el-button type="text" @click="batchDelChecked">批量移除</el-button>
</div>
<el-input placeholder="请输入资源名称" prefix-icon="el-icon-search" v-model="checkedKeyword" clearable></el-input>
<div class="lines">
<template v-for="(item, i) in checked">
<div v-if="!item.name || item.name.includes(checkedKeyword)" :key="i" class="line">
<div class="check-left">
<el-checkbox v-model="item.check"></el-checkbox>
<span class="serial">{{ i + 1 }}</span>
<el-tooltip effect="dark" :content="item.name" placement="top-start">
<p class="checked-name ellipsis">{{ item.name }}</p>
</el-tooltip>
</div>
<i class="el-icon-delete action-icon" @click="delChecked(item)"></i>
</div>
</template>
</div>
</template>
<div v-else class="empty">
<img class="icon" src="@/assets/img/empty.svg" alt="">
<p>暂无数据</p>
</div>
</div>
</div>
<div class="btns">
<el-button @click="sourceVisible = false">取消</el-button>
<el-button type="primary" :loading="submiting" @click="submit">确定</el-button>
</div>
</el-drawer>
</template>
<script>
import Setting from '@/setting'
import Util from '@/libs/util'
import _ from 'lodash'
import SourceConst from '@/const/source'
export default {
props: ['visible'],
data () {
return {
sourceVisible: false,
active: 'tab1',
tabs: {
tab1: '教学课程',
tab2: '精品课程',
tab3: '文件素材',
},
sourceType: [],
curType: '全部',
sources: [],
checkAll: false,
keyword: '',
searchTimer: null,
checkedKeyword: '',
allSections: [],
course: [],
checked: [],
submiting: false,
loading: false,
};
},
watch: {
'keyword': function (val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(this.getCourse, 500)
},
visible () {
this.sourceVisible = this.visible
this.visible && this.init()
}
},
mounted () {
},
methods: {
//
init () {
this.checked = []
this.curType = '全部'
this.sourceType = [
{
id: '',
name: '全部'
},
...SourceConst.types
]
this.sourceType.forEach(e => {
e.check = false
})
this.getCourse()
},
//
async getCourse () {
try {
this.loading = true
this.checkAll = false
const { checked } = this
if (this.active === 'tab3') {
const { page } = await this.$post(this.api.resourceLibrary, {
pageNum: 1,
pageSize: 10000,
platformId: Setting.platformId,
type: 2,
keyword: this.keyword,
displayFileType: this.curType === '全部' ? [] : [this.curType],
})
const list = page.records
list.forEach(e => {
const cur = checked.find(m => m.resourceName && m.id === e.id)
e.name = e.resourceName
e.check = !!cur
})
this.sources = list
} else {
const { list } = await this.$post(`${this.api[this.active === 'tab1' ? 'curriculumTree' : 'boutiqueCurriculumTree']}?name=${this.keyword}`)
if (list.length) {
const all = []
list.forEach(e => {
e.shrink = false
e.check = false
e.chapters.forEach(n => {
n.shrink = false
n.check = false
all.push(...n.subsections)
n.subsections.forEach(m => {
const cur = checked.find(j => m.cid === j.cid && m.id === j.id)
m.check = !!cur
})
})
})
list.forEach(e => {
e.shrink = false
e.check = false
e.chapters.forEach(n => {
n.shrink = false
n.check = n.subsections.every(m => m.check)
})
})
list.forEach(e => {
e.shrink = false
e.check = e.chapters.every(m => m.check)
})
list[0].shrink = true
list[0].chapters[0].shrink = true
this.allSections = all
}
this.course = list
}
} finally {
this.loading = false
}
},
initData () {
this.page = 1;
this.getData();
},
tabChange (index) {
this.keyword = ''
this.active = index
this.getCourse()
},
//
checkCourse (row) {
const { check } = row
const { checked } = this
row.chapters.forEach(e => {
e.check = check
e.subsections.forEach(n => {
n.check = check
const cur = checked.findIndex(m => m.id === n.id)
if (check) {
if (cur === -1) {
const section = _.cloneDeep(n)
section.check = false
checked.push(section)
}
} else {
cur !== -1 && checked.splice(cur, 1)
}
})
})
},
//
checkChapter (row, course) {
const { check } = row
const { checked } = this
row.subsections.forEach(n => {
n.check = check
const cur = checked.findIndex(m => m.id === n.id)
if (check) {
if (cur === -1) {
const section = _.cloneDeep(n)
section.check = false
checked.push(section)
}
} else {
cur !== -1 && checked.splice(cur, 1)
}
})
course.check = course.chapters.every(e => e.check)
},
//
async checkSection (row, chapter) {
const { check } = row
const { checked } = this
const cur = checked.findIndex(m => m.id === row.id)
if (check) {
if (cur === -1) {
const section = _.cloneDeep(row)
section.check = false
this.checked.push(section)
}
} else {
cur !== -1 && this.checked.splice(cur, 1)
}
chapter.check = chapter.subsections.every(e => e.check)
},
//
checkAllChange (val) {
this.sources.map(e => {
e.check = val
this.sourceChange(e)
})
},
//
checkType ({ name }) {
this.curType = name
this.getCourse()
},
//
sourceChange (row) {
const { check } = row
const { checked } = this
const cur = checked.findIndex(m => m.id === row.id)
if (check) {
if (cur === -1) {
const section = _.cloneDeep(row)
section.check = false
this.checked.push(section)
}
} else {
cur !== -1 && this.checked.splice(cur, 1)
}
},
//
async batchDelChecked (val) {
try {
const checked = this.checked.filter(e => e.check)
if (checked.length) {
checked.map(e => {
const cur = this.allSections.find(n => n.id === e.id)
if (cur) {
cur.check = false
}
})
this.checked = this.checked.filter(e => !e.check)
} else {
Util.warningMsg('请选择数据')
}
} catch (e) { }
},
//
async delChecked (item) {
try {
const cur = this.allSections.find(e => e.id === item.id)
if (cur) cur.check = false
this.checked.splice(this.checked.findIndex(e => e.id === item.id), 1)
} catch (e) { }
},
//
async submit () {
try {
if (this.submiting) return false
const { checked } = this
if (checked.length) {
this.submiting = true
const { chapterId, id } = this.$parent
const result = checked.map(e => {
return {
chapterId,
cid: id,
resourceId: e.id,
type: e.cid ? 0 : e.resourceName ? 2 : 1,
}
})
const old = this.$parent.curSection //
if (old.id) {
//
await this.$post(this.api.replaceResource, {
chapterId: old.chapterId,
cid: +id,
subsectionId: old.id,
newResource: result
})
} else {
//
await this.$post(this.api.combinationResource, result)
}
this.sourceVisible = false
this.$parent.switchTypeVisible = false
this.$parent.getData()
this.submiting = false
} else {
Util.warningMsg('请选择资源')
}
} catch (e) {
this.submiting = false
}
},
//
closeDia () {
this.$emit('update:visible', false)
}
}
};
</script>
<style lang="scss" scoped>
/deep/.source-dia {
.el-drawer__header {
padding-bottom: 20px;
margin-bottom: 0;
border-bottom: 1px solid #eee;
}
.overflow {
display: flex;
}
.btns {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
padding: 14px 0;
text-align: center;
background-color: #fff;
box-shadow: 4px -2px 6px 0px rgba(198, 198, 198, 0.3500);
}
.empty {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
font-size: 14px;
text-align: center;
color: #a3a3a3;
}
.left {
width: 700px;
padding: 0 15px;
border-right: 1px solid #eee;
box-sizing: border-box;
.course {
height: calc(100vh - 263px);
overflow: auto;
.item {
padding: 10px;
margin-bottom: 10px;
background-color: #f9f9f9;
}
}
.line {
display: flex;
align-items: center;
}
.arrow {
font-size: 16px;
color: #9f9f9f;
cursor: pointer;
transition: .3s;
&.active {
transform: rotate(90deg);
}
}
.check {
margin: 0 10px;
img {
vertical-align: middle;
}
}
.cover {
width: 100px;
max-height: 80px;
margin-right: 15px;
border-radius: 6px;
}
.course-name {
font-size: 14px;
color: #333;
}
.chapters {
padding-left: 26px;
margin-top: 10px;
.line {
margin-bottom: 10px;
}
}
.chapter-name {
font-size: 13px;
color: #ccc;
}
.sections {
padding-left: 43px;
}
}
.right {
flex: 1;
padding: 15px;
.total {
font-size: 15px;
color: #333;
font-weight: 600;
}
.lines {
height: calc(100vh - 228px);
padding-right: 10px;
margin-top: 10px;
overflow: auto;
}
.line {
display: flex;
padding: 5px 0;
color: #333;
}
.serial {
width: 32px;
margin: 0 12px;
text-align: center;
white-space: nowrap;
}
.check-left {
display: inline-flex;
align-items: center;
}
.checked-name {
width: 360px;
margin-right: 20px;
}
.action-icon {
font-size: 14px;
cursor: pointer;
}
}
.materials {
display: flex;
gap: 20px;
}
.types {
width: 250px;
height: calc(100vh - 223px);
padding: 15px;
background-color: #f9f9f9;
box-sizing: border-box;
overflow: auto;
.line {
margin-bottom: 10px;
cursor: pointer;
&.active {
font-weight: 600;
color: #062c87;
}
}
}
.sources {
flex: 1;
padding: 10px;
.line {
margin-top: 8px;
}
}
}
</style>

@ -1,343 +1,213 @@
<template>
<div>
<el-card shadow="hover"
class="mgb20">
<el-card shadow="hover" class="mgb20">
<div class="flex-between">
<el-page-header @back="back"
:content="name + '/' + (sorting? '编辑排序' : '内容设置')"></el-page-header>
<el-page-header @back="back" :content="name + '/' + (sorting ? '编辑排序' : '内容设置')"></el-page-header>
</div>
</el-card>
<!--内容设置-->
<el-card shadow="hover"
class="mgb20">
<div class="page">
<div class="page mgb20">
<div class="relative">
<div class="p-title">内容设置</div>
<div class="btns">
<template v-if="!sorting">
<el-button type="primary"
round
@click="addChapter"
v-auth="'/curriculum:内容设置:添加章节'">添加章节</el-button>
<el-button type="primary"
round
@click="sort"
v-auth="'/curriculum:内容设置:编辑排序'">编辑顺序</el-button>
<el-button type="primary" round @click="addChapter" v-auth="'/curriculum:内容设置:添加章节'">添加章节</el-button>
<el-button type="primary" round @click="sort" v-auth="'/curriculum:内容设置:编辑排序'">编辑顺序</el-button>
</template>
<template v-else>
<el-button type="primary"
round
@click="move">批量移动</el-button>
<el-button type="primary"
round
@click="cancelSort">取消</el-button>
<el-button type="primary"
round
@click="saveSort">保存</el-button>
<el-button type="primary" round @click="move">批量移动</el-button>
<el-button type="primary" round @click="cancelSort">取消</el-button>
<el-button type="primary" round @click="saveSort">保存</el-button>
</template>
</div>
</div>
<el-divider></el-divider>
<div class="page-content">
<div class="mgb20"
v-for="(chapter,index) in chapters"
:key="chapter.id">
<div class="mgb20" v-for="(chapter, index) in chapters" :key="chapter.id">
<div class="flex-between mgb10">
<div>{{ chapter.name }}</div>
<div>
<template v-if="!sorting">
<el-button class="action-btn"
plain
@click="editChapter(chapter)"
<el-button class="action-btn" plain @click="editChapter(chapter)"
v-auth="'/curriculum:内容设置:修改章节名称'">修改章节名称</el-button>
<el-button class="action-btn"
plain
@click="addSection(chapter.id)"
<el-button class="action-btn" plain @click="addSection(chapter.id)"
v-auth="'/curriculum:内容设置:添加小节'">添加小节</el-button>
<el-button class="action-btn"
plain
@click="delChapter(chapter.id)"
<el-button class="action-btn" plain @click="delChapter(chapter.id)"
v-auth="'/curriculum:内容设置:删除章节'">删除</el-button>
</template>
<template v-else>
<i class="el-icon-top sort-icon"
:class="{disabled: index == 0}"
style="margin-right: 5px"
@click="sortChapter(chapter,'up',index == 0,index)"></i>
<i class="el-icon-bottom sort-icon"
:class="{disabled: index == chapters.length-1}"
@click="sortChapter(chapter,'down',index == chapter.length-1,index)"></i>
<i class="el-icon-top sort-icon" :class="{ disabled: index == 0 }" style="margin-right: 5px"
@click="sortChapter(chapter, 'up', index == 0, index)"></i>
<i class="el-icon-bottom sort-icon" :class="{ disabled: index == chapters.length - 1 }"
@click="sortChapter(chapter, 'down', index == chapter.length - 1, index)"></i>
</template>
</div>
</div>
<el-table :data="chapter.subsectionList"
class="table"
stripe
header-align="center"
row-key="id">
<el-table-column v-if="sorting"
width="55"
align="center">
<el-table :data="chapter.subsectionList" class="table" header-align="center" row-key="id">
<el-table-column v-if="sorting" width="55" align="center">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.check"></el-checkbox>
</template>
</el-table-column>
<el-table-column type="index"
width="100"
label="序号"
align="center"></el-table-column>
<el-table-column prop="name"
label="资源名称">
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column prop="name" label="资源名称">
</el-table-column>
<el-table-column prop="fileType"
label="资源类型"
align="center">
<el-table-column prop="fileType" label="资源类型" align="center">
<template slot-scope="scope">
{{ transferType(scope.row.fileType) }}
</template>
</el-table-column>
<el-table-column label="操作"
align="center"
width="300">
<el-table-column label="操作" align="center" width="300">
<template slot-scope="scope">
<template v-if="!sorting">
<el-button type="text"
@click="download(scope.row)"
v-auth="'/curriculum:内容设置:下载'">下载</el-button>
<el-button type="text"
@click="preview(scope.row)"
v-auth="'/curriculum:内容设置:查看'">查看</el-button>
<el-button type="text"
@click="delSection(scope.row)"
<el-button type="text" @click="download(scope.row)" v-auth="'/curriculum:内容设置:下载'">下载</el-button>
<el-button type="text" @click="preview(scope.row)" v-auth="'/curriculum:内容设置:查看'">查看</el-button>
<el-button type="text" @click="delSection(scope.row)"
v-auth="'/curriculum:内容设置:删除小节'">删除</el-button>
<el-button type="text"
@click="editSectionName(scope.row,chapter.id)"
<el-button type="text" @click="editSectionName(scope.row, chapter.id)"
v-auth="'/curriculum:内容设置:修改小节名称'">修改小节名称</el-button>
<el-button type="text"
@click="switchFile(scope.row,chapter.id)"
<el-button type="text" @click="switchFile(scope.row, chapter.id)"
v-auth="'/curriculum:内容设置:更换文件'">更换文件</el-button>
</template>
<template v-else>
<i class="el-icon-top sort-icon"
:class="{disabled: scope.$index == 0}"
style="margin-right: 5px"
@click="sortSection(index,'up',scope.$index == 0,scope.$index)"></i>
<i class="el-icon-top sort-icon" :class="{ disabled: scope.$index == 0 }" style="margin-right: 5px"
@click="sortSection(index, 'up', scope.$index == 0, scope.$index)"></i>
<i class="el-icon-bottom sort-icon"
:class="{disabled: scope.$index == chapter.subsectionList.length-1}"
@click="sortSection(index,'down',scope.$index == chapter.subsectionList.length-1,scope.$index)"></i>
:class="{ disabled: scope.$index == chapter.subsectionList.length - 1 }"
@click="sortSection(index, 'down', scope.$index == chapter.subsectionList.length - 1, scope.$index)"></i>
</template>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog :title="chapterId ? '编辑章节' : '新增章节'"
:visible.sync="chapterVisible"
width="540px"
<el-dialog :title="chapterId ? '编辑章节' : '新增章节'" :visible.sync="chapterVisible" width="540px"
:close-on-click-modal="false">
<el-form>
<el-form-item>
<el-input placeholder="请输入章节名称,便于对小节归类"
v-model="chapterName"
maxlength="50"></el-input>
<el-input placeholder="请输入章节名称,便于对小节归类" v-model="chapterName" maxlength="50"></el-input>
</el-form-item>
</el-form>
<span slot="footer"
class="dialog-footer">
<span slot="footer" class="dialog-footer">
<el-button @click="chapterVisible = false">取消</el-button>
<el-button type="primary"
@click="chapterSubmit">确定</el-button>
<el-button type="primary" @click="chapterSubmit">确定</el-button>
</span>
</el-dialog>
<el-dialog title="添加小节"
:visible.sync="sectionVisible"
width="540px"
@close="closeSection"
<el-dialog title="添加小节" :visible.sync="sectionVisible" width="540px" @close="closeSection"
:close-on-click-modal="false">
<el-form ref="form"
:model="sectionForm"
label-width="80px"
@submit.native.prevent>
<el-form ref="form" :model="sectionForm" label-width="80px" @submit.native.prevent>
<el-form-item label="资源添加">
<Upload :max-size="100000"
:file-list="uploadList"
:on-remove="handleRemove"
@beforeUpload="beforeUpload"
@onSuccess="uploadSuccess">
<Upload :max-size="100000" :file-list="uploadList" :on-remove="handleRemove"
@beforeUpload="beforeUpload" @onSuccess="uploadSuccess">
<template slot="tip">
<p>视频请上传MP4格式大小不超过150Moffice文件大小不要超过10M</p>
</template>
</Upload>
</el-form-item>
<el-form-item label="小节名称">
<el-input placeholder="请输入小节名称"
v-model.trim="sectionForm.sectionName"
maxlength="50"
<el-input placeholder="请输入小节名称" v-model.trim="sectionForm.sectionName" maxlength="50"
@keyup.enter.native="sectionSubmit()"></el-input>
</el-form-item>
</el-form>
<span slot="footer"
class="dialog-footer">
<span slot="footer" class="dialog-footer">
<el-button @click="sectionVisible = false">取消</el-button>
<el-button type="primary"
@click="sectionSubmit">确定</el-button>
<el-button type="primary" @click="sectionSubmit">确定</el-button>
</span>
</el-dialog>
<el-dialog title="更换文件"
:visible.sync="switchVisible"
width="540px"
:close-on-click-modal="false"
<el-dialog title="更换文件" :visible.sync="switchVisible" width="540px" :close-on-click-modal="false"
@close="closeSwitch">
<div style="text-align: center">
<Upload :max-size="100000"
:file-list="uploadList"
:on-remove="handleRemove"
@beforeUpload="beforeUpload"
<Upload :max-size="100000" :file-list="uploadList" :on-remove="handleRemove" @beforeUpload="beforeUpload"
@onSuccess="uploadSuccess">
<div slot="tip"></div>
</Upload>
</div>
<span slot="footer"
class="dialog-footer">
<span slot="footer" class="dialog-footer">
<el-button @click="switchVisible = false">取消</el-button>
<el-button type="primary"
@click="switchSubmit">确定</el-button>
<el-button type="primary" @click="switchSubmit">确定</el-button>
</span>
</el-dialog>
<el-dialog title="修改小节名称"
:visible.sync="sectionNameVisible"
width="540px"
:close-on-click-modal="false">
<el-dialog title="修改小节名称" :visible.sync="sectionNameVisible" width="540px" :close-on-click-modal="false">
<el-form @submit.native.prevent>
<el-form-item>
<el-input placeholder="请输入小节名称"
v-model="sectionForm.sectionName"
maxlength="50"
<el-input placeholder="请输入小节名称" v-model="sectionForm.sectionName" maxlength="50"
@keyup.enter.native="sectionNameSubmit()"></el-input>
</el-form-item>
</el-form>
<span slot="footer"
class="dialog-footer">
<span slot="footer" class="dialog-footer">
<el-button @click="sectionNameVisible = false">取消</el-button>
<el-button type="primary"
@click="sectionNameSubmit">确定</el-button>
<el-button type="primary" @click="sectionNameSubmit">确定</el-button>
</span>
</el-dialog>
<div v-show="previewImg"
class="el-image-viewer__wrapper"
:class="{active: previewImg}"
<div v-show="previewImg" class="el-image-viewer__wrapper" :class="{ active: previewImg }"
style="z-index: 2000">
<div class="el-image-viewer__mask"></div>
<span class="el-image-viewer__btn el-image-viewer__close"
@click="previewImg = ''"><i class="el-icon-circle-close"
style="color: #fff"></i></span>
<span class="el-image-viewer__btn el-image-viewer__close" @click="previewImg = ''"><i
class="el-icon-circle-close" style="color: #fff"></i></span>
<div class="el-image-viewer__canvas">
<img :src="previewImg"
class="el-image-viewer__img"
<img :src="previewImg" class="el-image-viewer__img"
style="transform: scale(1) rotate(0deg);margin-top: -1px; max-height: 100%; max-width: 100%;">
</div>
</div>
<div v-show="iframeSrc || videoSrc"
class="el-image-viewer__wrapper"
:class="{active: iframeSrc}"
<div v-show="iframeSrc || videoSrc" class="el-image-viewer__wrapper" :class="{ active: iframeSrc }"
style="z-index: 2000">
<div class="el-image-viewer__mask"></div>
<span class="el-image-viewer__btn el-image-viewer__close"
:class="{'doc-close': isWord}"
:style="{top: isWord ? '50px' : '5px'}"
@click="closeIframe"><i class="el-icon-circle-close"
<span class="el-image-viewer__btn el-image-viewer__close" :class="{ 'doc-close': isWord }"
:style="{ top: isWord ? '50px' : '5px' }" @click="closeIframe"><i class="el-icon-circle-close"
style="color: #fff"></i></span>
<div class="el-image-viewer__canvas">
<iframe v-if="iframeSrc"
class="fileIframe"
id="fileIframe"
:src="iframeSrc"
frameborder="0"></iframe>
<video v-if="videoSrc"
class="video"
width="1200"
height="600"
autoplay
controls>
<source :src="videoSrc"
type="video/mp4">
<iframe v-if="iframeSrc" class="fileIframe" id="fileIframe" :src="iframeSrc" frameborder="0"></iframe>
<video v-if="videoSrc" class="video" width="1200" height="600" autoplay controls>
<source :src="videoSrc" type="video/mp4">
您的浏览器不支持 video 标签
</video>
<template v-if="showMask">
<div class="mask"
style="width: 200px;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: 200px;height: 30px;top: 53px;right: 320px"></div>
<div class="mask" style="width: 175px;height: 30px;top: 53px;right: 5px"></div>
</template>
<template v-if="showMask1">
<div class="word-mask1"
style="width: 200px;height: 50px;"></div>
<div class="word-mask"
style="height: 40px;top: 48px;"></div>
<div class="word-mask2"
style="top: 55px;left: 28%;width: 44%;height: calc(100% - 80px);"></div>
<div class="word-mask1" style="width: 200px;height: 50px;"></div>
<div class="word-mask" style="height: 40px;top: 48px;"></div>
<div class="word-mask2" style="top: 55px;left: 28%;width: 44%;height: calc(100% - 80px);"></div>
</template>
<template v-if="showMask2 && iframeSrc">
<div class="excel-mask1"
style="height: 48px;"></div>
<div class="excel-mask1" style="height: 48px;"></div>
</template>
</div>
</div>
<div v-show="playAuth"
class="el-image-viewer__wrapper"
:class="{active: playAuth}"
style="z-index: 2000">
<div v-show="playAuth" class="el-image-viewer__wrapper" :class="{ active: playAuth }" style="z-index: 2000">
<div class="el-image-viewer__mask"></div>
<span class="el-image-viewer__btn el-image-viewer__close"
@click="closePlayer"><i class="el-icon-circle-close"
style="color: #fff"></i></span>
<div class="player"
id="player"></div>
<span class="el-image-viewer__btn el-image-viewer__close" @click="closePlayer"><i
class="el-icon-circle-close" style="color: #fff"></i></span>
<div class="player" id="player"></div>
</div>
<Pdf :visible.sync="pdfVisible"
:src.sync="pdfSrc" />
<Pdf :visible.sync="pdfVisible" :src.sync="pdfSrc" />
</div>
</div>
</el-card>
<div class="player-download"
id="playerDownload"></div>
<div class="player-download" id="playerDownload"></div>
<el-dialog title="资源移动"
:visible.sync="moveVisible"
:close-on-click-modal="false"
width="330px">
<el-dialog title="资源移动" :visible.sync="moveVisible" :close-on-click-modal="false" width="330px">
<el-form>
<el-form-item label="目标章节">
<el-select v-model="moveForm.id"
placeholder="请选择目标章节"
@change="chapterChange">
<el-option v-for="(item, i) in chapters"
:key="i"
:label="item.name"
:value="item.id"></el-option>
<el-select v-model="moveForm.id" placeholder="请选择目标章节" @change="chapterChange">
<el-option v-for="(item, i) in chapters" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="目标排序">
<el-select v-model="moveForm.sort"
placeholder="请选择目标排序">
<el-option v-for="(item, i) in sortList"
:key="i"
:label="item.name"
:value="item.id"></el-option>
<el-select v-model="moveForm.sort" placeholder="请选择目标排序">
<el-option v-for="(item, i) in sortList" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-form>
<span slot="footer"
class="dialog-footer">
<span slot="footer" class="dialog-footer">
<el-button @click="moveVisible = false">取消</el-button>
<el-button type="primary"
@click="moveConfirm">确定</el-button>
<el-button type="primary" @click="moveConfirm">确定</el-button>
</span>
</el-dialog>
</div>
@ -753,7 +623,7 @@ export default {
const { fileType, fileId } = row
// ppt
if (fileType === 'pptx') {
this.downloadFile(row.name, row.fileUrl)
this.downloadFile(row.originalFileName || row.name, row.fileUrl)
} else if (fileId) {
//
this.$get(`${this.api.getPlayAuth}/${fileId}`).then(res => {
@ -762,7 +632,7 @@ export default {
width: "100%",
autoplay: false,
vid: fileId,
playauth: res.data.playAuth,
playauth: res.playAuth,
encryptType: 1 //
}, player => {
this.downloadFile(row.name, player._urls[0].Url)
@ -777,7 +647,7 @@ export default {
//
if (row.fileId) {
this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => {
this.playAuth = res.data.playAuth;
this.playAuth = res.playAuth;
if (this.player) {
this.player.replayByVidAndPlayAuth(row.fileId, this.playAuth);
} else {
@ -952,10 +822,11 @@ export default {
max-height: calc(100vh - 420px);
overflow: auto;
}
.action-btn {
color: #9076ff;
color: #062c87;
font-size: 14px;
border: #9076ff 1px solid;
border: #062c87 1px solid;
background-color: #fff;
border-radius: 4px;
}
@ -979,10 +850,12 @@ export default {
cursor: not-allowed;
}
}
/deep/.el-progress-bar {
padding-right: 70px;
margin-right: -70px;
}
.el-upload__tip {
position: absolute;
top: -4px;
@ -990,6 +863,7 @@ export default {
width: 300px;
line-height: 1.4;
}
.el-image-viewer__wrapper {
transform: translateY(-10px);
transition: transform 0.5s;
@ -1019,6 +893,7 @@ export default {
width: 1200px !important;
height: 600px !important;
}
.player-download {
position: absolute;
top: -9999px;

File diff suppressed because it is too large Load Diff

@ -1,7 +1,6 @@
<template>
<div>
<el-card shadow="hover"
class="mgb20">
<el-card shadow="hover" class="mgb20">
<div>
<div class="flex-center mgb20">
<p class="hr_tag"></p>
@ -11,62 +10,40 @@
<el-form label-width="80px">
<el-col :span="4">
<el-form-item label="学科类别">
<el-select v-model="form.categoryId"
clearable
@change="getProfessionalClass()"
@clear="clearClass()">
<el-option v-for="(item,index) in subjectList"
:key="index"
:label="item.disciplineName"
<el-select v-model="form.categoryId" clearable @change="getProfessionalClass()" @clear="clearClass()">
<el-option v-for="(item, index) in subjectList" :key="index" :label="item.disciplineName"
:value="item.disciplineId"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="专业类">
<el-select v-model="form.professionalCategoryId"
clearable
:disabled="form.categoryId ? false : true"
@change="getProfessional()"
@clear="clearProfess()">
<el-option v-for="(item,index) in ProfessionalClassList"
:key="index"
:label="item.professionalClassName"
:value="item.professionalClassId"></el-option>
<el-select v-model="form.professionalCategoryId" clearable :disabled="form.categoryId ? false : true"
@change="getProfessional()" @clear="clearProfess()">
<el-option v-for="(item, index) in ProfessionalClassList" :key="index"
:label="item.professionalClassName" :value="item.professionalClassId"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="专业">
<el-select v-model="form.professionalId"
clearable
:disabled="form.professionalCategoryId ? false : true"
@change="getData()">
<el-option v-for="(item,index) in ProfessionalList"
:key="index"
:label="item.professionalName"
<el-select v-model="form.professionalId" clearable
:disabled="form.professionalCategoryId ? false : true" @change="getData()">
<el-option v-for="(item, index) in ProfessionalList" :key="index" :label="item.professionalName"
:value="item.professionalId"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="课程类别">
<el-select v-model="form.curriculumType"
clearable
@change="getData()">
<el-option label="理论课程"
:value="0"></el-option>
<el-option label="实训课程"
:value="1"></el-option>
<el-select v-model="form.curriculumType" clearable @change="getData()">
<el-option v-for="(item, i) in courseTypeStatus" :key="i" :label="item" :value="i"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item>
<el-input placeholder="请输入课程名称"
prefix-icon="el-icon-search"
v-model="form.curriculumName"
clearable
<el-input placeholder="请输入课程名称" prefix-icon="el-icon-search" v-model="form.curriculumName" clearable
@keyup.enter.native="onSearch"></el-input>
</el-form-item>
</el-col>
@ -75,110 +52,71 @@
</div>
</el-card>
<el-card shadow="hover"
class="card">
<el-card shadow="hover" class="card">
<div class="flex-between mgb20">
<div class="flex-center">
<p class="hr_tag"></p>
<span>课程列表</span>
</div>
<div>
<el-button type="primary"
round
@click="addcourse"
v-auth>新增课程</el-button>
<el-button type="primary"
round
@click="delAllSelection"
v-auth>批量删除</el-button>
<el-button type="primary" round @click="addcourse" v-auth="'/curriculum:新增课程'">新增课程</el-button>
<el-button type="primary" round @click="delAllSelection" v-auth="'/curriculum:批量删除'">批量删除</el-button>
</div>
</div>
<el-table v-loading="loading"
:data="courseData"
class="table"
ref="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
:row-key="getRowKeys">
<el-table-column type="selection"
width="55"
align="center"
:reserve-selection="true"></el-table-column>
<el-table-column type="index"
width="100"
label="序号"
align="center"></el-table-column>
<el-table-column prop="curriculumName"
label="课程名称"
align="center"></el-table-column>
<el-table-column prop="curriculumType"
label="课程类型"
align="center">
<el-table v-loading="loading" :data="courseData" class="table" ref="table" header-align="center"
@selection-change="handleSelectionChange" row-key="cid">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="70" label="序号" align="center"></el-table-column>
<el-table-column prop="curriculumName" label="课程名称" align="center"></el-table-column>
<el-table-column prop="curriculumType" label="课程类别" width="90" align="center">
<template slot-scope="scope">
<span class="ellipsis">{{ courseTypeStatus[scope.row.curriculumType] }}</span>
</template>
</el-table-column>
<el-table-column prop="userName"
label="创建人"
align="center"></el-table-column>
<el-table-column label="配置的实训应用"
align="center">
<el-table-column label="配置的系统" align="center">
<template slot-scope="scope">
<span class="ellipsis">{{ scope.row.sysName }}</span>
</template>
</el-table-column>
<el-table-column prop="orderVolume"
label="订单量"
align="center"></el-table-column>
<el-table-column prop="expectedCourse"
label="预计课时"
align="center"></el-table-column>
<el-table-column label="上架/下架"
align="center">
<el-table-column prop="expectedCourse" label="预计课时" width="90" align="center"></el-table-column>
<el-table-column prop="orderVolume" label="订单量" width="90" align="center"></el-table-column>
<el-table-column prop="userName" label="创建人" width="120" align="center"></el-table-column>
<el-table-column label="上架/下架" width="90" align="center">
<template slot-scope="scope">
<el-switch v-model="scope.row.isShelves"
:active-value="1"
:inactive-value="0"
@change="changeSwitch($event, scope.row)"
v-auth="'/curriculum:上下架'">
<el-switch v-model="scope.row.isShelves" :active-value="1" :inactive-value="0"
@change="changeSwitch($event, scope.row)" v-auth="'/curriculum:上下架'">
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作"
align="center">
<el-table-column label="操作" width="240" align="center">
<template slot-scope="scope">
<el-button type="text"
@click="edit(scope.row)"
v-auth>编辑</el-button>
<el-button type="text"
@click="config(scope.row)"
v-auth>内容设置</el-button>
<el-button type="text"
@click="handleDelete(scope.row)"
v-auth>删除</el-button>
<el-button type="text" @click="preview(scope.row)">预览课程</el-button>
<el-button type="text" @click="edit(scope.row)" v-auth="'/curriculum:编辑'">编辑</el-button>
<el-button type="text" @click="config(scope.row)" v-auth="'/curriculum:内容设置'">内容设置</el-button>
<el-button type="text" @click="copy(scope.row)">复制</el-button>
<el-button type="text" @click="handleDelete(scope.row)" v-auth="'/curriculum:删除'">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background
@current-change="handleCurrentChange"
:current-page="page"
layout="total, prev, pager, next"
:total="totals"></el-pagination>
<el-pagination background @current-change="handleCurrentChange" :current-page="page"
layout="total, prev, pager, next" :total="totals"></el-pagination>
</div>
</el-card>
</div>
</template>
<script>
import Setting from '@/setting'
import qs from 'qs'
import Util from '@/libs/util'
export default {
data () {
return {
courseTypeStatus: {
0: "理论课程",
1: "实训课程"
0: '理论课程',
1: '实训课程',
2: '理实课程',
},
name: localStorage.getItem("ms_username"),
courseData: [],
@ -186,7 +124,7 @@ export default {
categoryId: +this.$route.query.categoryId || '',
professionalCategoryId: +this.$route.query.professionalCategoryId || '',
professionalId: +this.$route.query.professionalId || '',
curriculumType: this.$route.query.curriculumType ? +this.$route.query.curriculumType : '',
curriculumType: this.$route.query.curriculumType || '',
curriculumName: this.$route.query.curriculumName || ''
},
page: +this.$route.query.page || 1,
@ -213,23 +151,23 @@ export default {
this.getData();
},
methods: {
getRowKeys (row) {
return row.cid;
},
//
getData () {
async getData () {
try {
const sid = this.$store.state.dataPer.find(e => e.permissionName === '课程管理')
let data = {
this.loading = true
const { page } = await this.$post(this.api.curriculumList, {
...this.form,
pageNum: this.page,
pageSize: this.pageSize,
supplierId: sid ? sid.supplierId : ''
};
this.$post(this.api.curriculumList, data).then(res => {
this.courseData = res.page.records;
this.totals = res.page.total;
this.loading = false;
}).catch(err => { });
supplierId: sid ? sid.supplierId : '',
platformId: Setting.platformId
})
this.courseData = page.records
this.totals = page.total
this.loading = false
} finally {
this.loading = false
}
},
initData () {
this.page = 1;
@ -284,17 +222,35 @@ export default {
//
addcourse () {
this.setReferrer()
this.$router.push("/addcurriculum");
this.$router.push("/curriculum/detail");
},
//
edit (row) {
this.setReferrer()
this.$router.push(`/addcurriculum?cid=${row.cid}`);
this.$router.push(`/curriculum/detail?cid=${row.cid}`);
},
//
preview (row) {
this.setReferrer()
this.$router.push(`/station?courseId=${row.cid || ''}&curriculumName=${encodeURIComponent(row.curriculumName)}&mallId=${row.mallId || ''}`)
},
//
config (row) {
this.setReferrer()
this.$router.push(`/contentSettings?cid=${row.cid}&name=${row.curriculumName}`);
this.$router.push(`/curriculum/content?cid=${row.cid}&name=${row.curriculumName}`);
},
//
async copy (row) {
this.$confirm('确定要复制吗', "提示", {
type: "warning"
}).then(async () => {
await this.$post(`${this.api.copySelfBuildCourse}?cid=${row.cid}`)
Util.successMsg('复制成功')
this.initData()
}).catch(() => { })
return
this.$router.push(`/curriculum/detail?cid=${row.cid}&copy=1`)
},
//
handleDelete (row) {
@ -374,4 +330,3 @@ export default {
min-height: calc(100vh - 300px);
}
</style>

@ -130,8 +130,8 @@
<el-button type="primary" @click="exportList">导出列表</el-button>
</div>
</div>
<el-table :data="products" class="orderTable" stripe header-align="center"
@selection-change="handleSelectionChange" row-key="id">
<el-table :data="products" class="orderTable" 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="100" label="序号" align="center">
</el-table-column>
@ -139,7 +139,7 @@
<el-table-column prop="productTypeName" label="产品分类" align="center"></el-table-column>
<el-table-column label="起止日期" align="center">
<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">
<div slot="content">
还有<span v-html="scope.row.other"></span><br>的订单还未生效
@ -173,14 +173,14 @@
<ul class="filter">
<li>
<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"
:value="item.value"></el-option>
</el-select>
</li>
<li>
<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"
:value="item.id"></el-option>
</el-select>
@ -191,8 +191,8 @@
v-model="form3.keyword"></el-input>
</div>
</div>
<el-table :data="orders" class="orderTable" stripe header-align="center"
@selection-change="handleSelectionChange" row-key="orderId">
<el-table :data="orders" class="orderTable" header-align="center" @selection-change="handleSelectionChange"
row-key="orderId">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
</el-table-column>
@ -200,7 +200,7 @@
<el-table-column prop="orderContent" label="订单内容" align="center">
<template slot-scope="scope">
<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>
<div slot="reference" class="name-wrapper">
<el-tag size="medium" class='tags'>{{ scope.row.orderContent }}</el-tag>
@ -234,7 +234,7 @@
clearable></el-input>
</div>
</div>
<el-table :data="contractInformations" class="table" stripe header-align="center">
<el-table :data="contractInformations" class="table" header-align="center">
<el-table-column type="index" width="100" label="序号" align="center">
</el-table-column>
<el-table-column prop="contractNumber" label="订单号" align="center"></el-table-column>
@ -270,7 +270,7 @@
v-model="bmsKeyword"></el-input>
</div>
</div>
<el-table :data="bms" class="table" stripe header-align="center">
<el-table :data="bms" class="table" header-align="center">
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column prop="userName" label="姓名" width="200" align="center">
<template slot-scope="scope">
@ -336,7 +336,7 @@
clearable></el-input>
<i class="el-icon-circle-plus plus-cus" @click="addCustomer"></i>
</div>
<el-table :data="customers" class="table" ref="table" stripe header-align="center" row-key="customerId">
<el-table :data="customers" class="table" ref="table" header-align="center" row-key="customerId">
<el-table-column type="index" width="100" label="序号" align="center">
<template slot-scope="scope">
{{ scope.$index + (pageCustomer - 1) * pageSizeCustomer + 1 }}
@ -401,8 +401,8 @@ export default {
customerId: "",
customerName: '',
countries: '中国',
industryClassId: '',
industryId: '',
industryClassId: 16,
industryId: 83,
provinceId: '',
account: '',
name: '',
@ -526,6 +526,7 @@ export default {
],
products: [],
productAll: [],
productAllOrigin: [],
pageProduct: this.$route.query.type === 'tab2' ? (+this.$route.query.page || 1) : 1,
pageSizeProduct: 10,
totalProduct: 0,
@ -565,7 +566,6 @@ export default {
pageSizeOrder: 10,
totalOrder: 0,
orders: [],
orderAll: [],
bmsKeyword: '',
bms: [],
@ -625,7 +625,7 @@ export default {
this.pageOrder = 1
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.handlePageOrder()
this.initOrder()
}, 500)
},
bmsKeyword: function (val) {
@ -677,6 +677,7 @@ export default {
this.getSchool()
}).catch((res) => { })
} else {
this.changIndustryData()
this.getSchool()
}
},
@ -702,7 +703,7 @@ export default {
})
//
// 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.endTime = connect ? list[list.length - 1].endTime : list[0].endTime
e.status = '未生效'
@ -716,7 +717,7 @@ export default {
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 = '已过期'
} else {
//
@ -729,7 +730,7 @@ export default {
for (const j in list) {
const i = +j
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.endTime = n.endTime
@ -744,7 +745,7 @@ export default {
})
}
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.endTime = n.endTime
@ -775,13 +776,14 @@ export default {
}
})
this.productAll = data
this.productAllOrigin = data
this.totalProduct = data.length
this.handlePage()
}).catch(res => { })
},
//
getRemain (startTime, endTime) {
return parseInt(((new Date(endTime).getTime() - new Date(startTime).getTime()) / 86400000))
return parseInt(((new Date(endTime) - new Date(startTime)) / 86400000))
},
//
handlePage () {
@ -792,6 +794,15 @@ export default {
this.handlePage()
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 () {
this.initCustomer()
@ -894,7 +905,7 @@ export default {
this.customerVisible = false
this.$message.success('添加成功')
this.getCustomer()
this.getSchool(res.schoolId || '')
this.getSchool(!this.customerId ? res.schoolId || '' : '') //
},
//
getCategory () {
@ -902,12 +913,6 @@ export default {
this.productTypeList = res.classificationList
}).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 () {
let list = this.productAll
@ -935,36 +940,32 @@ export default {
//
getOrder () {
const { orderStatus, orderType } = this.form3
this.$post(this.api.orderList, {
const { orderStatus, orderType, keyword } = this.form3
this.$post(this.api.getCustomerOrderRecord, {
customerId: this.customerId,
cityId: '',
customerName: this.form.customerName,
orderContent: keyword,
orderStatus,
orderType,
pageNo: 1,
pageSize: 10000,
pageNo: this.pageOrder,
pageSize: this.pageSizeOrder,
provinceId: ''
}).then(({ orderPage }) => {
orderPage.orders.forEach(e => {
}).then(({ orders }) => {
orders.records.forEach(e => {
e.orderType = this.orderTypeFn(e.orderType)
e.orderStatus = this.orderStatusFn(e.orderStatus)
e.orderNature = this.orderNatureFn(e.orderNature)
});
this.orderAll = orderPage.orders
this.totalOrder = orderPage.total
this.handlePageOrder()
this.orders = orders.records
this.totalOrder = orders.total
}).catch(res => { })
},
//
handlePageOrder () {
const { keyword } = this.form3
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)
initOrder () {
this.pageOrder = 1
this.getOrder()
},
handleCurrentChangeOrder (val) {
this.pageOrder = val
this.handlePageOrder()
this.getOrder()
this.$router.push(`addcustomer?id=${this.customerId}&type=tab3&page=${val}`)
},
//
@ -1013,7 +1014,7 @@ export default {
this.pageProduct = 1
this.pageOrder = 1
this.pageBm = 1
index === 'tab3' && this.handlePageOrder()
index === 'tab3' && this.initOrder()
this.updateTime = this.form.customerId ? 1 : 0
}
},
@ -1036,7 +1037,7 @@ export default {
this.$get(this.api.querySchoolData).then(({ list }) => {
this.schoolList = list
// schoolId
if (schoolId) {
if (schoolId && !this.customerId) {
const item = list.find(e => e.schoolId == schoolId)
if (item) {
this.form.schoolId = schoolId
@ -1263,12 +1264,12 @@ export default {
.radio_icon {
font-size: 26px;
color: #9278ff;
color: #062c87;
}
/deep/.warning {
margin-left: 5px;
color: #9278ff;
color: #062c87;
}
.tags {
@ -1295,7 +1296,7 @@ export default {
.plus-cus {
margin-left: 10px;
font-size: 18px;
color: #9076ff;
color: #062c87;
cursor: pointer;
}
@ -1307,7 +1308,7 @@ export default {
cursor: pointer;
&:hover {
color: #9076ff;
color: #062c87;
}
}
}

@ -1,11 +1,8 @@
<template>
<div>
<el-card shadow="hover"
class="mgb20">
<el-card shadow="hover" class="mgb20">
<div class="flex-between">
<div class="per_title"
v-preventReClick
@click="back">
<div class="per_title" v-preventReClick @click="back">
<i class="el-icon-arrow-left"></i>
<span class="per_back">返回</span>
<span class="per_school">{{ $route.query.userName }}的订单</span>
@ -13,80 +10,46 @@
</div>
</el-card>
<el-card shadow="hover"
class="card">
<el-card shadow="hover" class="card">
<div class="flex-between mgb20">
<div class="flex-center">
<p class="hr_tag"></p>
<span>订单列表</span>
</div>
<el-input style="width: 300px"
placeholder="请输入订单编号/产品名称"
prefix-icon="el-icon-search"
v-model="keyword"
<el-input style="width: 300px" placeholder="请输入订单编号/产品名称" prefix-icon="el-icon-search" v-model="keyword"
clearable></el-input>
</div>
<el-table :data="orderData"
class="table"
ref="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
:row-key="getRowKeys">
<el-table-column type="index"
width="100"
label="序号"
align="center">
<el-table :data="orderData" class="table" ref="table" header-align="center"
@selection-change="handleSelectionChange" :row-key="getRowKeys">
<el-table-column type="index" width="100" label="序号" align="center">
</el-table-column>
<el-table-column prop="orderNumber"
label="订单编号"
align="center">
<el-table-column prop="orderNumber" label="订单编号" align="center">
</el-table-column>
<el-table-column prop="customerName"
label="客户名称"
align="center">
<el-table-column prop="customerName" label="客户名称" align="center">
<template slot-scope="scope">
{{ customerName }}
</template>
</el-table-column>
<el-table-column prop="productName"
label="产品内容"
align="center"
show-overflow-tooltip></el-table-column>
<el-table-column prop="orderAmount"
label="订单金额(元)"
align="center">
<el-table-column prop="productName" label="产品内容" align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="orderAmount" label="订单金额(元)" align="center">
</el-table-column>
<el-table-column prop="createTime"
label="订单日期"
align="center">
<el-table-column prop="createTime" label="订单日期" align="center">
</el-table-column>
<el-table-column prop="orderType"
label="订单类型"
align="center">
<el-table-column prop="orderType" label="订单类型" align="center">
</el-table-column>
<el-table-column prop="orderStatus"
label="订单状态"
align="center">
<el-table-column prop="orderStatus" label="订单状态" align="center">
</el-table-column>
<el-table-column prop="orderNature"
label="订单性质"
align="center">
<el-table-column prop="orderNature" label="订单性质" align="center">
</el-table-column>
<el-table-column label="操作"
align="center">
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text"
@click="toDetail(scope.row)">查看</el-button>
<el-button type="text" @click="toDetail(scope.row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background
layout="total, prev, pager, next"
@current-change="handleCurrentChange"
:current-page="page"
:total="totals">
<el-pagination background layout="total, prev, pager, next" @current-change="handleCurrentChange"
:current-page="page" :total="totals">
</el-pagination>
</div>
</el-card>
@ -181,9 +144,11 @@ export default {
.card {
min-height: calc(100vh - 300px);
}
.mag {
margin-right: 20px;
}
.cell {
white-space: pre-wrap;
width: 140px;
@ -194,6 +159,7 @@ export default {
line-clamp: 2;
-webkit-box-orient: vertical;
}
.tags {
border: none;
background: none;
@ -208,4 +174,3 @@ export default {
-webkit-box-orient: vertical;
}
</style>

@ -6,7 +6,7 @@
<div class="per_title" v-preventReClick @click="goback()">
<i class="el-icon-arrow-left"></i>
<span class="per_back">返回</span>
<span class="per_school">{{customerName}}</span>
<span class="per_school">{{ customerName }}</span>
</div>
</el-card>
@ -44,7 +44,7 @@
<p class="addhr_tag"></p>
<span>应用列表</span>
</div>
<el-table :data="permissionData" class="table" stripe :span-method="SpanMethod" header-align="center">
<el-table :data="permissionData" class="table" :span-method="SpanMethod" header-align="center">
<el-table-column prop="id" label="序号" align="center">
</el-table-column>
<el-table-column prop="age" label="应用名称" align="center">
@ -90,10 +90,7 @@
</el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-switch
v-model="scope.row.swtich"
active-text="开启"
inactive-text="关闭"
<el-switch v-model="scope.row.swtich" active-text="开启" inactive-text="关闭"
@change="changeSwitch(scope.row)">
</el-switch>
</template>
@ -113,7 +110,7 @@
<p class="hr_tag"></p>
<span>客户列表</span>
</div>
<el-table :data="permissionData" class="table" stripe header-align="center">
<el-table :data="permissionData" class="table" header-align="center">
<el-table-column type="index" width="100" label="序号" align="center">
</el-table-column>
<el-table-column prop="age" label="服务器名称" align="center">
@ -161,8 +158,8 @@
</template>
<script>
export default {
data (){
export default {
data () {
return {
customerName: this.$route.query.name,
permissionData: [{
@ -192,10 +189,10 @@
}
},
methods: {
SpanMethod({ row, column, rowIndex, columnIndex }) {
SpanMethod ({ row, column, rowIndex, columnIndex }) {
if (rowIndex % 2 === 0) {
if (columnIndex === 6) {
if(!row.Intranet){
if (!row.Intranet) {
return [1, 2];
}
}
@ -204,40 +201,47 @@
// }
}
},
chooseIp(){
chooseIp () {
this.ipVisible = true
},
goback(){
goback () {
this.$router.go(-1)
}
}
}
}
</script>
<style scoped>
.border_lf{
.border_lf {
border-left: 1px dashed #eee;
padding: 0 60px;
}
.border_lf label{
.border_lf label {
width: 120px;
}
.pad_none{
.pad_none {
padding: 0 0 0 60px;
}
.mar_input{
.mar_input {
margin-right: 80px;
}
.marb30{
.marb30 {
margin-bottom: 30px;
}
.tab_temp label{
.tab_temp label {
width: 60px;
}
.mar10{
.mar10 {
margin-top: 10px;
}
.radio_icon{
.radio_icon {
font-size: 26px;
color: #9278FF;
}

@ -57,7 +57,7 @@
<el-button type="primary" round @click="delAllSelection" v-auth>批量删除</el-button>
</div>
</div>
<el-table :data="listData" class="table" ref="table" stripe header-align="center"
<el-table :data="listData" class="table" ref="table" header-align="center"
@selection-change="handleSelectionChange" row-key="customerId">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">

@ -5,11 +5,14 @@
<div class="plus">
<i class="el-icon-circle-plus-outline" @click.stop="addType(0)"></i>
</div>
<el-tree ref="type" :data="typeList" node-key="id" accordion :default-expanded-keys="defaultActive" :current-node-key="categoryId" :props="defaultProps" :highlight-current="true" v-loading="loadingType" @current-change="typeClick">
<el-tree ref="type" :data="typeList" node-key="id" accordion :default-expanded-keys="defaultActive"
:current-node-key="categoryId" :props="defaultProps" :highlight-current="true" v-loading="loadingType"
@current-change="typeClick">
<span class="custom-tree-node" slot-scope="{ node, data }">
<span :title="node.label">{{ node.label }}</span>
<span class="actions">
<i class="el-icon-circle-plus-outline" @click.stop="addType(node)" v-if="data.level != 6" v-auth="'/data:数据架构:新增分类'"></i>
<i class="el-icon-circle-plus-outline" @click.stop="addType(node)" v-if="data.level != 6"
v-auth="'/data:数据架构:新增分类'"></i>
<i class="el-icon-edit" @click.stop="editType(node)" v-auth="'/data:数据架构:编辑分类'"></i>
<i class="el-icon-delete" @click.stop="delType(node)" v-auth="'/data:数据架构:删除分类'"></i>
</span>
@ -21,7 +24,8 @@
<el-form label-width="80px" class="flex-between mgb20">
<div class="flex-center">
<el-form-item label="更新时间" style="margin: 0 20px 0 0">
<el-date-picker v-model="updateTime" type="date" placeholder="选择日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd" @change="initData"></el-date-picker>
<el-date-picker v-model="updateTime" type="date" placeholder="选择日期" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" @change="initData"></el-date-picker>
</el-form-item>
<el-input placeholder="请输入数据表名称" v-model="keyword" prefix-icon="el-icon-search" clearable></el-input>
</div>
@ -30,12 +34,13 @@
<el-button type="primary" round @click="delAllSelection" v-auth="'/data:数据架构:批量删除'">批量删除</el-button>
</div>
</el-form>
<el-table :data="listData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange">
<el-table :data="listData" class="table" ref="table" header-align="center"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center"></el-table-column>
<el-table-column type="index" width="70" label="序号" align="center"></el-table-column>
<el-table-column prop="tableComment" label="数据表名称" align="center">
<template slot-scope="scope">
{{scope.row.tableComment ? scope.row.tableComment : scope.row.showName}}
{{ scope.row.tableComment ? scope.row.tableComment : scope.row.showName }}
</template>
</el-table-column>
<el-table-column prop="showName" label="产品表名称" align="center"></el-table-column>
@ -43,7 +48,7 @@
<el-table-column prop="dataTotal" label="数据总量" width="100" align="center"></el-table-column>
<el-table-column prop="dataSize" label="数据大小" width="100" align="center">
<template slot-scope="scope">
{{scope.row.dataSize}}M
{{ scope.row.dataSize }}M
</template>
</el-table-column>
<el-table-column prop="updateTime" label="更新时间" width="180" align="center"></el-table-column>
@ -57,28 +62,21 @@
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :current-page="page" @current-change="handleCurrentChange" :total="total">
<el-pagination background layout="total, prev, pager, next" :current-page="page"
@current-change="handleCurrentChange" :total="total">
</el-pagination>
</div>
</div>
<!-- 导入数据 -->
<el-dialog title="导入" :visible.sync="importVisible" width="80%" center @close="closeImport" class="dialog" :close-on-click-modal="false">
<el-dialog title="导入" :visible.sync="importVisible" width="80%" center @close="closeImport" class="dialog"
:close-on-click-modal="false">
<el-container style="padding: 20px 0 20px 20px;background-color: #f0f0f0;">
<div style="overflow:auto;height: 558px;width:330px;padding:15px;background:#fff" ref="typeTreeWrap" @scroll="loadType">
<el-tree v-loading="importLoading"
ref="typeTree"
:data="importTypeList"
node-key="id"
accordion
:default-expanded-keys="defaultTypeActive"
:default-checked-keys="defaultTypeChecked"
:current-node-key="curId"
show-checkbox
:props="defaultProps"
highlight-current
@node-click="importTypeClick"
@node-expand="importTypeExpand"
>
<div style="overflow:auto;height: 558px;width:330px;padding:15px;background:#fff" ref="typeTreeWrap"
@scroll="loadType">
<el-tree v-loading="importLoading" ref="typeTree" :data="importTypeList" node-key="id" accordion
:default-expanded-keys="defaultTypeActive" :default-checked-keys="defaultTypeChecked"
:current-node-key="curId" show-checkbox :props="defaultProps" highlight-current
@node-click="importTypeClick" @node-expand="importTypeExpand">
</el-tree>
</div>
@ -88,9 +86,10 @@
<p class="hr_tag"></p>
<span>预览</span>
</div>
<el-table :data="fieldData" stripe header-align="center" v-if="fieldHead.length">
<el-table :data="fieldData" header-align="center" v-if="fieldHead.length">
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column v-for="(item,index) in fieldHead" :prop="item.field" :key="index" :label="item.comment" align="center"></el-table-column>
<el-table-column v-for="(item, index) in fieldHead" :prop="item.field" :key="index" :label="item.comment"
align="center"></el-table-column>
</el-table>
</el-card>
</el-main>
@ -102,7 +101,8 @@
</span>
</el-dialog>
<!-- 新增编辑分类 -->
<el-dialog :title="id ? '编辑分类' : '新增分类'" :visible.sync="typeVisible" width="24%" center @close="closeType" :close-on-click-modal="false">
<el-dialog :title="id ? '编辑分类' : '新增分类'" :visible.sync="typeVisible" width="24%" center @close="closeType"
:close-on-click-modal="false">
<el-input placeholder="请输入分类名称" v-model="categoryName"></el-input>
<span slot="footer" class="dialog-footer">
<el-button @click="typeVisible = false"> </el-button>
@ -111,9 +111,10 @@
</el-dialog>
<!-- 预览 -->
<el-dialog title="预览" :visible.sync="previewVisible" width="60%" center :close-on-click-modal="false">
<el-table :data="previewData" class="table" stripe header-align="center" row-key="id">
<el-table :data="previewData" class="table" header-align="center" row-key="id">
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column v-for="(item,index) in previewHead" :prop="item.field" :key="index" :label="item.comment" align="center"></el-table-column>
<el-table-column v-for="(item, index) in previewHead" :prop="item.field" :key="index" :label="item.comment"
align="center"></el-table-column>
</el-table>
</el-dialog>
<!-- 编辑产品数据表名称 -->
@ -126,19 +127,20 @@
</el-dialog>
<!-- 自定义表头 -->
<el-dialog title="自定义表头" :visible.sync="headVisible" width="60%" center :close-on-click-modal="false">
<el-table :data="previewData" class="table" stripe header-align="center" row-key="id" :key="editIndex">
<el-table :data="previewData" class="table" header-align="center" row-key="id" :key="editIndex">
<el-table-column type="index" width="100" label="序号" align="center">
<template slot-scope="scope">
<template v-if="scope.row.custom">序号</template>
<template v-else>{{ scope.$index }}</template>
</template>
</el-table-column>
<el-table-column v-for="(item,index) in previewHead" :prop="item.field" :key="index" :label="item.oldComment" align="center">
<el-table-column v-for="(item, index) in previewHead" :prop="item.field" :key="index" :label="item.oldComment"
align="center">
<template slot-scope="scope">
<template v-if="scope.row.custom">
<el-input placeholder="请输入" size="medium" v-model="item.comment"></el-input>
</template>
<template v-else>{{scope.row[item.field]}}</template>
<template v-else>{{ scope.row[item.field] }}</template>
</template>
</el-table-column>
</el-table>
@ -153,7 +155,7 @@
import { uuid } from 'vue-uuid'
import { Loading } from 'element-ui'
export default {
data() {
data () {
return {
loadingType: false,
typeList: [],
@ -206,29 +208,29 @@ export default {
};
},
watch: {
keyword: function(val) {
keyword: function (val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.initData()
},500)
}, 500)
}
},
mounted(){
mounted () {
this.getType()
},
methods: {
//
getType(){
getType () {
this.loadingType = true
this.$post(this.api.getTableByClassification).then(res => {
// ,
function handleId(data,level = 0){
function handleId (data, level = 0) {
data.map(n => {
n.id = String(n.id)
n.label = n.categoryName
n.level = level + 1
if(n.children.length){
handleId(n.children,n.level)
if (n.children.length) {
handleId(n.children, n.level)
}
})
}
@ -237,10 +239,10 @@ export default {
this.loadingType = false
// addEd
if (!this.addEd) {
if(res[0].children.length){ //
if (res[0].children.length) { //
this.categoryId = res[0].children[0].id
this.defaultActive = [res[0].children[0].id]
}else{
} else {
this.categoryId = res[0].id
this.defaultActive = [res[0].id]
}
@ -251,10 +253,10 @@ export default {
}
this.addEd = false // false
this.getData()
}).catch(res => {})
}).catch(res => { })
},
//
getData(){
getData () {
this.$post(`${this.api.getIdQueryTable}?categoryId=${this.categoryId}&showName=${this.keyword}&pageNum=${this.page}&pageSize=${this.pageSize}&updateTime=${this.updateTime ? this.updateTime : ''}`).then(res => {
const list = res.pageList.records
list.map(e => {
@ -271,32 +273,32 @@ export default {
})
this.listData = list
this.total = res.pageList.total
}).catch(res => {})
}).catch(res => { })
},
// 1
initData(){
initData () {
this.page = 1
this.getData()
},
//
typeClick(data,node){
typeClick (data, node) {
this.categoryId = data.id
this.getData()
},
//
addType(row){
addType (row) {
if (row) this.defaultActive = [row.data.id] // idrow0
this.typeVisible = true
this.levelId = row ? row.data.id : 0 // levelIdidid0
},
//
editType(row){
editType (row) {
this.typeVisible = true
this.id = row.data.id
this.categoryName = row.data.categoryName
},
//
delType(row){
delType (row) {
//
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
@ -305,16 +307,16 @@ export default {
this.$post(`${this.api.deleteCategory}?categoryId=${row.data.id}`).then(res => {
this.$message.success('删除成功')
this.getType()
}).catch(res => {})
}).catch(() => {})
}).catch(res => { })
}).catch(() => { })
},
//
confirmType(){
if(this.submited) return false //
confirmType () {
if (this.submited) return false //
this.submited = true
this.addEd = true
if(this.id){
this.$post(this.api.updateCategory,{
if (this.id) {
this.$post(this.api.updateCategory, {
id: this.id,
categoryName: this.categoryName
}).then(res => {
@ -323,12 +325,12 @@ export default {
this.typeVisible = false
setTimeout(() => {
this.submited = false
},1500)
}, 1500)
}).catch(res => {
this.submited = false
})
}else{
this.$post(this.api.saveCategory,{
} else {
this.$post(this.api.saveCategory, {
levelId: this.levelId,
categoryName: this.categoryName
}).then(res => {
@ -337,14 +339,14 @@ export default {
this.typeVisible = false
setTimeout(() => {
this.submited = false
},1500)
}, 1500)
}).catch(res => {
this.submited = false
})
}
},
//
closeType(){
closeType () {
this.id = 0
this.levelId = 0
this.categoryName = ''
@ -354,7 +356,7 @@ export default {
* @param row 行数据
* @param isEdit 是否是从自定义表头进来的
*/
preview(row, isEdit){
preview (row, isEdit) {
this.$get(`${this.api.previewData}?tableName=${row.name}&tableId=${row.id}`).then(res => {
let comment = res.comment
let previewHead = []
@ -371,33 +373,33 @@ export default {
custom: true
})
data.map(n => {
for(let i in n){
for (let i in n) {
// +0000,,
if(typeof n[i] == 'string' && n[i].endsWith('+0000')) n[i] = this.formatDate('yyyy-MM-dd hh:mm:ss',new Date(n[i]))
if (typeof n[i] == 'string' && n[i].endsWith('+0000')) n[i] = this.formatDate('yyyy-MM-dd hh:mm:ss', new Date(n[i]))
}
})
this.previewData = data
if (!isEdit) this.previewVisible = true //
}).catch(res => {})
}).catch(res => { })
},
//
delTable(row){
delTable (row) {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
}).then(() => {
this.$post(`${this.api.deleteTable}?tableIds=${row.id}`).then(res => {
this.$message.success('删除成功')
this.getData()
}).catch(res => {})
}).catch(() => {})
}).catch(res => { })
}).catch(() => { })
},
//
editName(row){
editName (row) {
this.curRow = JSON.parse(JSON.stringify(row)) //
this.nameVisible = true
},
//
confirmName(){
confirmName () {
this.$post(this.api.editTableName, {
id: this.curRow.id,
showName: this.curRow.showName,
@ -405,33 +407,33 @@ export default {
this.$message.success('修改成功')
this.nameVisible = false
this.getData()
}).catch(res => {})
}).catch(res => { })
},
//
editHead(row){
editHead (row) {
this.curRow = JSON.parse(JSON.stringify(row)) //
this.preview(row, 1)
this.editIndex++ //
this.headVisible = true
},
//
confirmHead(){
confirmHead () {
let data = JSON.parse(JSON.stringify(this.curComment))
this.$post(`${this.api.updateTableCommit}?tableName=${this.curRow.name}`, data).then(res => {
this.$message.success('修改成功')
this.headVisible = false
this.getData()
}).catch(res => {})
}).catch(res => { })
},
handleSelectionChange(val) {
handleSelectionChange (val) {
this.multipleSelection = val
},
handleCurrentChange(val) {
handleCurrentChange (val) {
this.page = val
this.getData()
},
delAllSelection() {
if(this.multipleSelection.length != ''){
delAllSelection () {
if (this.multipleSelection.length != '') {
let newArr = this.multipleSelection
let delList = newArr.map(item => {
return `tableIds=${item.id}`
@ -440,76 +442,76 @@ export default {
type: 'warning'
}).then(() => {
this.$post(`${this.api.deleteTable}?${delList.join('&')}`).then(res => {
if(delList.length == this.listData.length){
if(this.page > 1){
this.page = this.page-1
if (delList.length == this.listData.length) {
if (this.page > 1) {
this.page = this.page - 1
}
}
this.$refs.table.clearSelection()
this.$message.success('删除成功')
this.getData()
}).catch(res => {})
}).catch(() => {})
}else{
}).catch(res => { })
}).catch(() => { })
} else {
this.$message.error('请先选择数据')
}
},
//
getMoreTable(list,id){
getMoreTable (list, id) {
list.map(n => {
if(n.id == id){
this.getTable(n,1)
}else if(n.children && n.children.length){
this.getMoreTable(n.children,id)
if (n.id == id) {
this.getTable(n, 1)
} else if (n.children && n.children.length) {
this.getMoreTable(n.children, id)
}
})
},
// ,,id
renderChecked(){
renderChecked () {
let result = []
let list = this.$refs.typeTree.getCheckedNodes()
list.map((n,i) => {
if(n.tableLen && n.tableLen > n.children.length){
result = [...result,...n.children.map(n => n.id)]
}else{
list.map((n, i) => {
if (n.tableLen && n.tableLen > n.children.length) {
result = [...result, ...n.children.map(n => n.id)]
} else {
result.push(n.id)
}
})
this.$refs.typeTree.setCheckedKeys(result)
},
// ,dom,
loadType(e){
loadType (e) {
clearTimeout(this.typeTimer)
let typeTree = this.$refs.typeTreeWrap
//
this.typeTimer = setTimeout(() => {
this.typeTreeScrollTop = typeTree.scrollTop - this.typeTreeScrollTop
// ,
if(this.typeTreeScrollTop > 0 && typeTree.scrollHeight - (typeTree.clientHeight + parseInt(typeTree.scrollTop)) < 10){
this.getMoreTable(this.importTypeList,this.curExpand)
if (this.typeTreeScrollTop > 0 && typeTree.scrollHeight - (typeTree.clientHeight + parseInt(typeTree.scrollTop)) < 10) {
this.getMoreTable(this.importTypeList, this.curExpand)
Promise.all(this.tablePromises).then(_ => {
this.renderChecked()
})
}
},50)
}, 50)
},
//
getTable(n,isConcat){
this.tablePromises.push(new Promise((resolve,reject) => {
getTable (n, isConcat) {
this.tablePromises.push(new Promise((resolve, reject) => {
this.$post(`${this.api.originalListById}?categoryId=${n.realId}&pageNum=${n.typeTreePage ? n.typeTreePage : 1}&pageSize=${this.typeTreeUnit}`).then(res => {
let list = res.list.records
list.map(n => {
n.label = n.showName
n.id = String(n.id)
// ,
if(this.defaultTypeChecked.includes(n.id)){
if (this.defaultTypeChecked.includes(n.id)) {
n.disabled = true
}
})
// ,
if(isConcat){
if (isConcat) {
n.children = n.children.concat(list)
}else{
} else {
n.children = list
n.tableLen = res.list.total
}
@ -522,19 +524,19 @@ export default {
}))
},
//
batchImport(){
batchImport () {
this.importLoading = true
this.importVisible = true
//
this.$post(this.api.originalList).then(res => {
// idlabelnamekeylabelnamekey
function handleId(data){
function handleId (data) {
data.map(n => {
n.realId = n.id
// ididuuid
n.id = uuid.v4()
n.label = n.categoryName
if(n.children.length){
if (n.children.length) {
handleId(n.children)
}
})
@ -547,9 +549,9 @@ export default {
//
const handleId = data => {
data.map(n => {
if(n.children.length){
if (n.children.length) {
handleId(n.children)
}else{
} else {
// 1
n.typeTreePage = 1
this.getTable(n)
@ -580,7 +582,7 @@ export default {
})
},
//
getFields(){
getFields () {
this.$get(`${this.api.staticPreview}?tableName=${this.tableName}`).then(res => {
let comment = res.comment
let fieldHead = []
@ -592,38 +594,38 @@ export default {
let data = res.data
data.map(n => {
for(let i in n){
for (let i in n) {
// +0000,,
if(typeof n[i] == 'string' && n[i].endsWith('+0000')) n[i] = this.formatDate('yyyy-MM-dd hh:mm:ss',new Date(n[i]))
if (typeof n[i] == 'string' && n[i].endsWith('+0000')) n[i] = this.formatDate('yyyy-MM-dd hh:mm:ss', new Date(n[i]))
}
})
this.fieldData = data
}).catch(res => {})
}).catch(res => { })
this.importVisible = true
},
//
importTypeClick(data){
importTypeClick (data) {
// ,,
if(data.name){
if (data.name) {
this.tableName = data.name
this.curId = data.id
this.getFields()
}
},
//
importTypeExpand(obj,node,com){
importTypeExpand (obj, node, com) {
this.curExpand = obj.id
this.renderChecked()
},
//
closeImport(){
closeImport () {
this.$refs.typeTree.setCheckedKeys([])
this.categorys = []
},
// id
getNames(list){
getNames (list) {
const categoryId = Number(this.categoryId)
return new Promise((resolve,reject) => {
return new Promise((resolve, reject) => {
this.$get(`${this.api.getAllTableInfoByCategoryId}?categoryId=${list.join()}`).then(res => {
const list = res.tableInfo
list.map(e => {
@ -632,24 +634,24 @@ export default {
})
this.categorys = list
resolve()
}).catch(res => {})
}).catch(res => { })
})
},
//
saveSuccess() {
saveSuccess () {
this.$message.success('导入成功')
this.getData()
this.importVisible = false
setTimeout(() => {
this.submited = false
},1000)
}, 1000)
},
//
confirmImport(){
if(this.submited) return false //
confirmImport () {
if (this.submited) return false //
const checked = this.$refs.typeTree.getCheckedNodes().filter(e => !e.disabled) //
//
if(!checked.length) return this.$message.warning('请选择数据')
if (!checked.length) return this.$message.warning('请选择数据')
this.submited = true
// ididid
const typeIds = checked.filter(e => !e.name).map(e => e.realId) // idnamenameididididrealIdid
@ -683,7 +685,7 @@ export default {
// 2000item6item6item2000item6item6item2000666
if (dataList.length > 6) {
dataList.slice(0, 6).map(e => {
promiseList.push(new Promise((resolve,reject) => {
promiseList.push(new Promise((resolve, reject) => {
this.$post(this.api.saveTable, e).then(res => {
resolve()
}).catch(res => {
@ -693,7 +695,7 @@ export default {
})
Promise.all(promiseList).then(res => {
dataList.slice(6).map(e => {
promiseList.push(new Promise((resolve,reject) => {
promiseList.push(new Promise((resolve, reject) => {
this.$post(this.api.saveTable, e).then(res => {
resolve()
}).catch(res => {
@ -711,7 +713,7 @@ export default {
})
} else {
dataList.map(e => {
promiseList.push(new Promise((resolve,reject) => {
promiseList.push(new Promise((resolve, reject) => {
this.$post(this.api.saveTable, e).then(res => {
resolve()
}).catch(res => {
@ -742,28 +744,33 @@ export default {
display: flex;
height: calc(100vh - 223px);
padding: 0 24px;
.side {
width: 300px;
padding: 24px 10px 24px 0;
margin-right: 24px;
border-right: 1px solid rgba(0, 0, 0, 0.06);
}
.right {
width: calc(100% - 374px);
padding: 24px 0;
}
.plus{
.plus {
text-align: right;
color: #9278FF;
cursor: pointer;
}
.custom-tree-node{
.custom-tree-node {
flex: 1;
display: inline-flex;
justify-content: space-between;
align-items: center;
.actions{
i{
.actions {
i {
margin-left: 5px;
color: #9278FF;
}

@ -1,77 +1,51 @@
<template>
<div class="wrap">
<div class="side">
<el-tree ref="type"
:data="typeList"
node-key="id"
accordion
:default-expanded-keys="defaultActive"
:current-node-key="categoryId"
:props="defaultProps"
:highlight-current="true"
<el-tree ref="type" :data="typeList" node-key="id" accordion :default-expanded-keys="defaultActive"
:current-node-key="categoryId" :props="defaultProps" :highlight-current="true"
@current-change="typeClick"></el-tree>
</div>
<div class="right">
<div class="flex-between"
style="margin-bottom: 10px;">
<div class="flex-between" style="margin-bottom: 10px;">
<p>数据简介</p>
<el-button v-if="introduceText && !editing"
type="primary"
@click="editing = !editing"
<el-button v-if="introduceText && !editing" type="primary" @click="editing = !editing"
v-auth="'/data:数据简介:编辑'">编辑</el-button>
</div>
<div class="intro"
v-if="!introduceText && !editing">
<div class="intro" v-if="!introduceText && !editing">
<p class="text">请添加简介</p>
<div class="btn">
<el-button type="primary"
@click="edit">添加</el-button>
<el-button type="primary" @click="edit">添加</el-button>
</div>
</div>
<template v-if="introduceText || editing">
<el-input placeholder="请输入简介"
v-model="introduce"
type="textarea"
rows="5"
:disabled="!editing"></el-input>
<el-input placeholder="请输入简介" v-model="introduce" type="textarea" rows="5" :disabled="!editing"></el-input>
<div class="field">
<p class="label">数据源</p>
<el-input style="width: 250px"
placeholder="请输入数据源"
v-model="dataSource"
type="text"
<el-input style="width: 250px" placeholder="请输入数据源" v-model="dataSource" type="text"
:disabled="!editing"></el-input>
</div>
</template>
<div class="field">
<p class="label">关键字</p>
<div class="tag-add"
v-if="editing">
<el-input placeholder="请输入关键字"
size="small"
v-model="newKeyword"></el-input>
<div class="tag-add" v-if="editing">
<el-input placeholder="请输入关键字" size="small" v-model="newKeyword"></el-input>
<span v-if="editing">
<el-button @click="save"
style="color: #9076FF;border: 1px solid #9076FF;border-radius:5px;height: 25px;line-height: 0px"> </el-button>
style="color: #062c87;border: 1px solid #062c87;border-radius:5px;height: 25px;line-height: 0px">
</el-button>
</span>
</div>
<div class="tag-wrap">
<el-tag :key="tag.id"
:type="editing ? '' : 'info'"
v-for="tag in keywordList"
:closable="editing"
:disable-transitions="false"
@close="delKeyword(tag)">
{{tag.keyword}}
<el-tag :key="tag.id" :type="editing ? '' : 'info'" v-for="tag in keywordList" :closable="editing"
:disable-transitions="false" @close="delKeyword(tag)">
{{ tag.keyword }}
</el-tag>
</div>
</div>
<div class="btns"
v-if="editing">
<div class="btns" v-if="editing">
<el-button @click="editing = false"> </el-button>
<el-button type="primary"
@click="confirmData"> </el-button>
<el-button type="primary" @click="confirmData"> </el-button>
</div>
</div>
</div>
@ -245,58 +219,72 @@ export default {
display: flex;
height: calc(100vh - 223px);
padding: 0 24px;
.side {
width: 300px;
padding: 24px 10px 24px 0;
margin-right: 24px;
border-right: 1px solid rgba(0, 0, 0, 0.06);
}
.right {
width: calc(100% - 374px);
padding: 24px 0;
}
.intro {
padding: 20px;
margin: 20px 0;
border: 1px solid #dcdcdc;
border-radius: 4px;
.text {
margin-bottom: 20px;
}
}
.field {
margin-top: 20px;
text-align: left;
.label {
margin-bottom: 10px;
}
}
.tag-wrap {
display: flex;
align-items: center;
}
.btns {
margin-top: 20px;
}
}
.tag-add {
display: flex;
align-items: center;
margin-bottom: 10px;
.el-input {
width: 200px;
}
.el-button {
margin-left: 5px;
}
}
.mag {
margin-right: 20px;
margin-left: 20px;
}
.el-tag + .el-tag {
.el-tag+.el-tag {
margin-left: 10px;
}
.button-new-tag {
margin-left: 10px;
height: 32px;
@ -304,6 +292,7 @@ export default {
padding-top: 0;
padding-bottom: 0;
}
.input-new-tag {
width: 90px;
margin-left: 10px;

@ -5,12 +5,14 @@
<ul class="filter">
<li>
<label>创建日期</label>
<el-date-picker v-model="date" align="right" unlink-panels type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd" clearable></el-date-picker>
<el-date-picker v-model="date" align="right" unlink-panels type="daterange" start-placeholder="开始日期"
end-placeholder="结束日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd" clearable></el-date-picker>
</li>
<li>
<label>状态</label>
<el-select v-model="status" clearable placeholder="请选择状态" @change="initData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
<el-option v-for="(item, index) in statusList" :key="index" :label="item.name"
:value="item.value"></el-option>
</el-select>
</li>
</ul>
@ -25,7 +27,8 @@
<el-button type="primary" round @click="delAllSelection" v-auth="'/data:产品管理:批量删除'">批量删除</el-button>
</div>
</div>
<el-table :data="listData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id">
<el-table :data="listData" class="table" ref="table" 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="100" label="序号" align="center"></el-table-column>
<el-table-column prop="productName" label="产品名称" align="center"></el-table-column>
@ -36,7 +39,8 @@
<el-table-column prop="createTime" label="创建时间" align="center"></el-table-column>
<el-table-column prop="orderNature" label="状态" align="center">
<template slot-scope="scope">
<el-switch v-model="scope.row.status" :active-text="scope.row.status ? '上架' : '下架'" :active-value="1" :inactive-value="0" @change="switchOff($event,scope.row,scope.$index)" v-auth="'/data:产品管理:上架'"></el-switch>
<el-switch v-model="scope.row.status" :active-text="scope.row.status ? '上架' : '下架'" :active-value="1"
:inactive-value="0" @change="switchOff($event, scope.row, scope.$index)" v-auth="'/data:产品管理:上架'"></el-switch>
</template>
</el-table-column>
<el-table-column label="操作">
@ -48,24 +52,28 @@
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" @current-change="handleCurrentChange" :current-page="page" :total="totals"></el-pagination>
<el-pagination background layout="total, prev, pager, next" @current-change="handleCurrentChange"
:current-page="page" :total="totals"></el-pagination>
</div>
<el-dialog :title="isDetail ? '查看产品' : (id ? '编辑产品' : '新增产品')" :visible.sync="productVisible" width="600px" center @close="closeProduct" class="dialog" :close-on-click-modal="false">
<el-dialog :title="isDetail ? '查看产品' : (id ? '编辑产品' : '新增产品')" :visible.sync="productVisible" width="600px" center
@close="closeProduct" class="dialog" :close-on-click-modal="false">
<el-form ref="form" label-width="98px" :disabled="isDetail" v-loading="loading">
<el-form-item label="数据产品名称">
<el-input v-model="productName" placeholder="请输入数据产品名称"></el-input>
</el-form-item>
<el-form-item label="供应厂商" prop="supplier">
<el-select v-model="supplier" clearable placeholder="请选择供应厂商">
<el-option v-for="(item, i) in suppliers" :key="i" :label="item.supplierName" :value="item.supplierId"></el-option>
<el-option v-for="(item, i) in suppliers" :key="i" :label="item.supplierName"
:value="item.supplierId"></el-option>
</el-select>
</el-form-item>
<el-form-item label="配置数据">
<el-button type="primary" @click="configData">配置数据权限</el-button>
</el-form-item>
<div class="type-wrap" ref="typeWrap" @scroll="loadType" v-show="checkedIds.length">
<el-tree ref="type" :data="typeList" show-checkbox accordion node-key="id" :default-expanded-keys="checkedIds" :default-checked-keys="checkedIds" :props="defaultProps" @node-expand="typeExpand">
<el-tree ref="type" :data="typeList" show-checkbox accordion node-key="id" :default-expanded-keys="checkedIds"
:default-checked-keys="checkedIds" :props="defaultProps" @node-expand="typeExpand">
<span class="custom-tree-node" slot-scope="{ node, data }">
<span :title="node.label">{{ node.label }}</span>
</span>
@ -78,10 +86,13 @@
</span>
</el-dialog>
<el-dialog title="数据配置" :visible.sync="configVisible" width="70%" center @close="closeConfig" :close-on-click-modal="false">
<el-dialog title="数据配置" :visible.sync="configVisible" width="70%" center @close="closeConfig"
:close-on-click-modal="false">
<el-container style="padding: 20px 0 20px 20px;background-color: #f0f0f0;">
<el-aside width="300px">
<el-tree style="margin: 10px;" ref="typeConfig" :data="typeConfigList" show-checkbox node-key="id" accordion :default-expanded-keys="configIds" :default-checked-keys="configIds" :current-node-key="categoryId" :props="defaultProps" highlight-current @current-change="typeConfigClick">
<el-tree style="margin: 10px;" ref="typeConfig" :data="typeConfigList" show-checkbox node-key="id" accordion
:default-expanded-keys="configIds" :default-checked-keys="configIds" :current-node-key="categoryId"
:props="defaultProps" highlight-current @current-change="typeConfigClick">
<span class="custom-tree-node" slot-scope="{ node, data }">
<span :title="node.label">{{ node.label }}</span>
</span>
@ -93,12 +104,14 @@
<el-form label-width="80px" class="flex-between mgb20">
<div class="flex-center">
<el-form-item label="创建日期" style="margin: 0 20px 0 0">
<el-date-picker v-model="updateTime" type="date" placeholder="选择日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd" @change="initConfigData"></el-date-picker>
<el-date-picker v-model="updateTime" type="date" placeholder="选择日期" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" @change="initConfigData"></el-date-picker>
</el-form-item>
<el-input placeholder="请输入数据表名称" v-model="keywordConfig" prefix-icon="el-icon-search" clearable></el-input>
<el-input placeholder="请输入数据表名称" v-model="keywordConfig" prefix-icon="el-icon-search"
clearable></el-input>
</div>
</el-form>
<el-table :data="listConfigData" class="table" ref="table" stripe header-align="center">
<el-table :data="listConfigData" class="table" ref="table" header-align="center">
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column prop="showName" label="数据表名称" align="center"></el-table-column>
<el-table-column prop="dataTotal" label="数据总量" align="center"></el-table-column>
@ -111,7 +124,8 @@
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :current-page="pageConfig" @current-change="handleCurrentConfigChange" :total="totalConfig"></el-pagination>
<el-pagination background layout="total, prev, pager, next" :current-page="pageConfig"
@current-change="handleCurrentConfigChange" :total="totalConfig"></el-pagination>
</div>
</el-card>
</el-main>
@ -123,9 +137,10 @@
</el-dialog>
<el-dialog title="预览" :visible.sync="previewVisible" width="60%" center :close-on-click-modal="false">
<el-table :data="previewData" class="table" stripe header-align="center" row-key="id">
<el-table :data="previewData" class="table" header-align="center" row-key="id">
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column v-for="(item,index) in previewHead" :prop="item.field" :key="index" :label="item.comment" align="center"></el-table-column>
<el-table-column v-for="(item, index) in previewHead" :prop="item.field" :key="index" :label="item.comment"
align="center"></el-table-column>
</el-table>
</el-dialog>
</div>
@ -134,7 +149,7 @@
<script>
import { uuid } from 'vue-uuid'
export default {
data() {
data () {
return {
userName: this.$store.state.userName,
keyword: '',
@ -143,12 +158,12 @@ export default {
startTime: '',
endTime: '',
status: '',
listData:[],
listData: [],
multipleSelection: [],
statusList: [{
name: '不限',
value: ''
},{
}, {
name: '已上架',
value: 1
},
@ -202,37 +217,37 @@ export default {
};
},
watch: {
date: function(val){
if(val){
date: function (val) {
if (val) {
this.startTime = val[0]
this.endTime = val[1]
}else{
} else {
this.startTime = ''
this.endTime = ''
}
this.initData()
},
keyword: function(val) {
keyword: function (val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.initData()
},500)
}, 500)
},
keywordConfig: function(val) {
keywordConfig: function (val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.initConfigData()
},500)
}, 500)
}
},
mounted() {
mounted () {
this.getData()
// this.getSupplier()
},
methods: {
//
getData() {
this.$post(this.api.listByEntity,{
getData () {
this.$post(this.api.listByEntity, {
createTime: this.startTime,
endTime: this.endTime,
pageNum: this.page,
@ -243,24 +258,24 @@ export default {
}).then(res => {
this.listData = res.pageList.records
this.totals = res.pageList.total
}).catch(res => {})
}).catch(res => { })
},
// 1
initData(){
initData () {
this.page = 1
this.getData()
},
//
getSupplier() {
getSupplier () {
const sid = this.$store.state.dataPer.find(e => e.permissionName === '数据管理')
this.$get(this.api.getSupplierListByRole, {
permissionId: sid.permissionId
}).then(res => {
this.suppliers = res.supplierList
}).catch(res => {})
}).catch(res => { })
},
//
getTable(n,isConcat){
getTable (n, isConcat) {
this.$post(`${this.api.getIdQueryTable}?categoryId=${n.originId}&showName=&pageNum=${n.typePage}&pageSize=${this.typeUnit}&updateTime=`).then(res => {
let list = res.pageList.records
list.map(n => {
@ -269,29 +284,29 @@ export default {
n.disabled = true //
})
// ,
if(isConcat){
if (isConcat) {
n.children = n.children.concat(list)
}else{
} else {
n.children = list
n.tableLen = res.pageList.total
}
n.typePage++
}).catch(res => {})
}).catch(res => { })
},
//
getType(queryDetail){
getType (queryDetail) {
this.loading = true
this.productVisible = true
this.$post(this.api.getTableByClassification).then(res => {
const that = this
function handleId(data){
function handleId (data) {
data.map(n => {
n.originId = n.id
// ididuuidoriginIdid
n.id = uuid.v4()
n.label = n.categoryName
n.disabled = true //
if(n.children.length){
if (n.children.length) {
handleId(n.children)
}
})
@ -300,11 +315,11 @@ export default {
this.typeConfigList = JSON.parse(JSON.stringify(res)) // 使
//
function getTable(data){
function getTable (data) {
data.map(n => {
if(n.children.length){
if (n.children.length) {
getTable(n.children)
}else{
} else {
n.typePage = 1 //
n.disabled = true //
that.getTable(n)
@ -316,73 +331,73 @@ export default {
setTimeout(() => {
this.typeList = res
queryDetail ? this.getDetail() : (this.loading = false)
},500)
}, 500)
this.importVisible = true
}).catch(res => {})
}).catch(res => { })
},
//
handleType(data,typeList){
handleType (data, typeList) {
let result = data
if(typeList.length){
if (typeList.length) {
typeList.map(e => {
if(result.includes(e.id) && e.children.length){
if (result.includes(e.id) && e.children.length) {
// ,idid,,,
e.children.every(n => result.includes(n)) || result.splice(result.indexOf(e.id),1)
e.children.every(n => result.includes(n)) || result.splice(result.indexOf(e.id), 1)
}
e.children.length && this.handleType(data,e.children)
e.children.length && this.handleType(data, e.children)
})
}
return result
},
//
typeExpand(obj,node,com){
typeExpand (obj, node, com) {
this.curExpand = obj.id
},
// ,
getMoreTable(list,id){
getMoreTable (list, id) {
list.map(n => {
if(n.id == id){
this.getTable(n,1)
}else if(n.children && n.children.length){
this.getMoreTable(n.children,id)
if (n.id == id) {
this.getTable(n, 1)
} else if (n.children && n.children.length) {
this.getMoreTable(n.children, id)
}
})
},
// ,dom,
loadType(e){
loadType (e) {
clearTimeout(this.typeTimer)
let typeTree = this.$refs.typeWrap
this.typeTimer = setTimeout(() => {
this.typeScrollTop = typeTree.scrollTop - this.typeScrollTop
// ,
if(this.typeScrollTop > 0 && typeTree.clientHeight + typeTree.scrollTop == typeTree.scrollHeight){
if (this.typeScrollTop > 0 && typeTree.clientHeight + typeTree.scrollTop == typeTree.scrollHeight) {
let curExpand = this.curExpand
// ,,curExpand,
if(!curExpand){
if (!curExpand) {
let id = this.checkedIds[0]
let list = this.typeList
function handleId(data,parentId){
function handleId (data, parentId) {
data.map(n => {
if(n.id == id){
if (n.id == id) {
curExpand = parentId ? parentId : n.id
}else if(n.children && n.children.length){
handleId(n.children,n.id)
} else if (n.children && n.children.length) {
handleId(n.children, n.id)
}
})
}
handleId(list)
}
this.getMoreTable(this.typeList,curExpand)
this.getMoreTable(this.typeList, curExpand)
setTimeout(() => {
this.$nextTick(() => {
this.$refs.type.setCheckedKeys(this.checkedIds)
})
},300)
}, 300)
}
},50)
}, 50)
},
//
getDetail(){
getDetail () {
this.$post(`${this.api.findById}?id=${this.id}`).then(res => {
const data = res.product
this.productName = data.productName
@ -395,20 +410,20 @@ export default {
})
},
//
add(){
add () {
this.getType()
this.id = ''
this.checkedIds = []
},
//
edit(row){
edit (row) {
this.getType(true)
this.id = row.id
this.userId = row.userId
},
//
switchOff(val,row) {
this.$post(this.api.updateProduct,{
switchOff (val, row) {
this.$post(this.api.updateProduct, {
id: row.id,
productName: row.productName,
tableId: row.tableId,
@ -421,16 +436,16 @@ export default {
updateTime: '',
}).then(res => {
this.$message.success(val ? '上架成功' : '下架成功')
}).catch(err => {})
}).catch(err => { })
},
//
preview(row){
preview (row) {
this.getType(true)
this.isDetail = true
this.id = row.id
},
//
handleDelete(row) {
handleDelete (row) {
this.$post(`${this.api.deleteDataPrompt}?ids=${row.id}`).then(({ status }) => {
if (status === 200) {
this.$confirm('确定要删除吗?', '提示', {
@ -439,16 +454,16 @@ export default {
this.$post(`${this.api.deleteProduct}?ids=${row.id}`).then(res => {
this.$message.success('删除成功')
this.getData()
}).catch(res => {})
}).catch(() => {})
}).catch(res => { })
}).catch(() => { })
}
}).catch(err => {})
}).catch(err => { })
},
handleSelectionChange(val) {
handleSelectionChange (val) {
this.multipleSelection = val
},
delAllSelection() {
if(this.multipleSelection.length){
delAllSelection () {
if (this.multipleSelection.length) {
let ids = []
this.multipleSelection.forEach(i => {
ids.push('ids=' + i.id)
@ -461,38 +476,38 @@ export default {
type: 'warning'
}).then(() => {
this.$post(`${this.api.deleteProduct}?ids=${result.join(',')}`).then(res => {
if(result.length == this.listData.length){
if(this.page > 1){
this.page = this.page-1
if (result.length == this.listData.length) {
if (this.page > 1) {
this.page = this.page - 1
}
}
this.$refs.table.clearSelection()
this.$message.success('删除成功')
this.getData()
}).catch(res => {})
}).catch(() => {})
}).catch(res => { })
}).catch(() => { })
}
}).catch(err => {})
}else{
}).catch(err => { })
} else {
this.$message.error('请先选择数据')
}
},
handleCurrentChange(val) {
handleCurrentChange (val) {
this.page = val
this.getData()
},
//
calcProp() {
calcProp () {
const p1 = this.businessProportion
const p2 = this.manufacturerProportion
if (p1 && p2) {
if(isNaN(p1)) return this.$message.warning('商务经理占比请输入数字')
if(isNaN(p2)) return this.$message.warning('产品厂商占比请输入数字')
if(+p1 + +p2 !== 100) return this.$message.warning('比例分成总和须为100%,请重新修改')
if (isNaN(p1)) return this.$message.warning('商务经理占比请输入数字')
if (isNaN(p2)) return this.$message.warning('产品厂商占比请输入数字')
if (+p1 + +p2 !== 100) return this.$message.warning('比例分成总和须为100%,请重新修改')
}
},
//
closeProduct(){
closeProduct () {
this.productName = ''
this.supplier = ''
this.isDetail = false
@ -500,14 +515,14 @@ export default {
this.configIds = []
},
// tableId,
getIds(list){
getIds (list) {
//
this.checkedIds = []
const proList = []
this.configLoading = true
// ididid
list.map(e => {
proList.push(new Promise((resolve,reject) => {
proList.push(new Promise((resolve, reject) => {
this.$get(`${this.api.getAllTableIdBycategoryId}?categoryId=${e}`).then(res => {
res.tableId && this.checkedIds.push(...res.tableId.split(','))
resolve()
@ -525,15 +540,15 @@ export default {
})
},
//
confirm(){
if(this.submited) return false
confirm () {
if (this.submited) return false
const { productName, supplier } = this
if(!productName) return this.$message.warning('请输入数据产品名称')
if(!supplier) return this.$message.warning('请选择供应厂商')
if(!this.checkedIds.length) return this.$message.warning('请选择数据')
if (!productName) return this.$message.warning('请输入数据产品名称')
if (!supplier) return this.$message.warning('请选择供应厂商')
if (!this.checkedIds.length) return this.$message.warning('请选择数据')
this.submited = true //
let tableId = this.checkedIds
if(!tableId.length) return this.$message.warning('请选择数据')
if (!tableId.length) return this.$message.warning('请选择数据')
let data = {
id: this.id,
productName,
@ -547,8 +562,8 @@ export default {
tableNum: tableId.length,
updateTime: ''
}
if(this.id){
this.$post(this.api.updateProduct,data).then(res => {
if (this.id) {
this.$post(this.api.updateProduct, data).then(res => {
this.$message.success('编辑成功')
this.productVisible = false
this.getData()
@ -556,8 +571,8 @@ export default {
}).catch(res => {
this.submited = false
})
}else{
this.$post(this.api.saveProduct,data).then(res => {
} else {
this.$post(this.api.saveProduct, data).then(res => {
this.$message.success('新增成功')
this.productVisible = false
this.getData()
@ -568,7 +583,7 @@ export default {
}
},
//
configData(){
configData () {
this.configVisible = true
this.getConfigType()
//
@ -579,58 +594,58 @@ export default {
}
},
//
typeConfigClick(data){
typeConfigClick (data) {
this.categoryId = data.id
this.categoryOriginId = data.originId
this.getConfigTable()
},
//
closeConfig(){
closeConfig () {
//
this.$refs.typeConfig.setCheckedNodes([])
},
//
getConfigType(){
getConfigType () {
const list = this.typeConfigList
function handleId(data){
function handleId (data) {
data.map(n => {
n.disabled = false //
if(n.children.length){
if (n.children.length) {
handleId(n.children)
}
})
}
handleId(list)
if(list[0].children.length){
if (list[0].children.length) {
this.categoryId = list[0].children[0].id
}else{
} else {
this.categoryId = list[0].id
}
this.getConfigTable()
},
//
getConfigTable(){
getConfigTable () {
this.$post(`${this.api.getIdQueryTable}?categoryId=${this.categoryOriginId}&showName=${this.keywordConfig}&pageNum=${this.pageConfig}&pageSize=${this.pageSizeConfig}&updateTime=${this.updateTime ? this.updateTime : ''}`).then(res => {
let list = res.pageList.records
list.map(n => {
//
n.updateTime = n.updateTime ? this.formatDate('yyyy-MM-dd hh:mm:ss',new Date(n.updateTime)) : ''
n.updateTime = n.updateTime ? this.formatDate('yyyy-MM-dd hh:mm:ss', new Date(n.updateTime)) : ''
})
this.listConfigData = list
this.totalConfig = res.pageList.total
}).catch(res => {})
}).catch(res => { })
},
//
initConfigData(){
initConfigData () {
this.pageConfig = 1
this.getConfigTable()
},
handleCurrentConfigChange(val){
handleCurrentConfigChange (val) {
this.pageConfig = val
this.getConfigTable()
},
//
previewConfig(row){
previewConfig (row) {
this.$get(`${this.api.previewData}?tableName=${row.name}&tableId=${row.id}`).then(res => {
let comment = res.comment
let previewHead = []
@ -642,17 +657,17 @@ export default {
let data = res.data
data.map(n => {
for(let i in n){
for (let i in n) {
//
if(typeof n[i] == 'string' && n[i].endsWith('+0000')) n[i] = this.formatDate('yyyy-MM-dd hh:mm:ss',new Date(n[i]))
if (typeof n[i] == 'string' && n[i].endsWith('+0000')) n[i] = this.formatDate('yyyy-MM-dd hh:mm:ss', new Date(n[i]))
}
})
this.previewData = data
this.previewVisible = true
}).catch(res => {})
}).catch(res => { })
},
//
confirmConfig(){
confirmConfig () {
const list = this.$refs.typeConfig.getCheckedNodes().map(e => e.originId) // id
this.getIds(list).then(() => {
this.configVisible = false
@ -665,23 +680,27 @@ export default {
</script>
<style lang="scss" scoped>
/deep/.el-input--suffix .el-input__inner{
/deep/.el-input--suffix .el-input__inner {
padding-right: 56px;
}
.type-wrap{
.type-wrap {
height: 450px;
margin-left: 25px;
overflow:auto;
overflow: auto;
}
.settlement {
display: flex;
margin-bottom: 10px;
.label {
margin-right: 10px;
white-space: nowrap;
color: #606266;
font-size: 14px;
}
.el-input {
width: 150px;
margin-right: 30px;

@ -6,26 +6,19 @@
<h1>欢迎使用开发者平台</h1>
<div class="form">
<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 }"
@click="handleSelect(item.id)">{{ item.label }}</li>
</ul>
<el-form v-show="activeIndex==='1'" :model="param" :rules="rules" ref="login" label-width="0px">
<el-form v-show="activeIndex === '1'" :model="param" :rules="rules" ref="login" label-width="0px">
<el-form-item prop="account">
<el-input @blur="blur" v-model="param.account" placeholder="请输入账号"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
type="password"
placeholder="请输入密码"
v-model="param.password"
>
<el-input type="password" placeholder="请输入密码" v-model="param.password">
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="showVerify">
<el-input
placeholder="请输入验证码"
v-model="param.code"
@keyup.enter.native="submitForm()"
>
<el-input placeholder="请输入验证码" v-model="param.code" @keyup.enter.native="submitForm()">
</el-input>
<img @click="blur" :src="verificationIMG" class="verification" alt="">
</el-form-item>
@ -34,24 +27,17 @@
</div>
</el-form>
<el-form v-show="activeIndex==='2'" :model="phoneOrEmail" :rules="phoneOrEmailrules" ref="phoneOrEmail" label-width="0px">
<el-form v-show="activeIndex === '2'" :model="phoneOrEmail" :rules="phoneOrEmailrules" ref="phoneOrEmail"
label-width="0px">
<el-form-item prop="account">
<el-input @blur="phoneBlur" v-model="phoneOrEmail.account" placeholder="请输入电话/邮箱"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
type="password"
placeholder="请输入密码"
v-model="phoneOrEmail.password"
>
<el-input type="password" placeholder="请输入密码" v-model="phoneOrEmail.password">
</el-input>
</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 placeholder="请输入验证码" v-model="phoneOrEmail.code" @keyup.enter.native="submitForm('phone')">
</el-input>
<img @click="phoneBlur" :src="PhoneVerificationIMG" class="verification" alt="">
</el-form-item>
@ -71,7 +57,8 @@
<el-form-item label="验证码">
<div style="display:flex;">
<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
}}</el-button>
</div>
</el-form-item>
</el-form>
@ -80,6 +67,20 @@
<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>
<v-footer class="footer" ref="footer"></v-footer>
</div>
</template>
@ -87,14 +88,17 @@
<script>
import vFooter from '../components/Footer'
import Setting from '@/setting'
import addRoutes from '@/libs/route/addRoutes'
import CryptoJS from 'crypto-js'
import JSEncrypt from 'jsencrypt'
export default {
data: function() {
data: function () {
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 phoneReg = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/
if (value === '') {
callback(new Error('请输入手机或邮箱!'));
} else if (!emailReg.test(value)&&!phoneReg.test(value)) {
} else if (!emailReg.test(value) && !phoneReg.test(value)) {
callback(new Error('输入的手机/邮箱格式不正确!'));
} else {
callback();
@ -110,19 +114,19 @@ export default {
label: '手机号/邮箱登录'
}
],
activeIndex:"1",
activeIndex: "1",
showVerify: true,// -
verificationIMG:'',//
verificationIMG: '',//
//
param: {
account: '',
password: '',
code:'',
platform:3,
random:'',
distinguish:1,
code: '',
platform: 3,
random: '',
distinguish: 1,
type: 2
},
rules: {
@ -132,84 +136,89 @@ export default {
},
// +
showPhoneVerify:true,// -
PhoneVerificationIMG:'',//
showPhoneVerify: true,// -
PhoneVerificationIMG: '',//
phoneOrEmail: {
account: '',
password: '',
code:'',
platform:3,
random:'',
distinguish:2,
code: '',
platform: 3,
random: '',
distinguish: 2,
type: 2
},
phoneOrEmailrules:{
phoneOrEmailrules: {
account: [{ validator: regPhoneOrEmail, trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
code: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
},
phoneVisible:false,
phone:'',
phoneCode:'',
phoneDisabled:false,
phoneVisible: false,
phone: '',
phoneCode: '',
phoneDisabled: false,
phoneBtnText: '发送验证码',
phoneTimer:'',
phoneOpener:''
phoneTimer: '',
phoneOpener: '',
userVisible: false,
users: [],
};
},
components: {
vFooter
},
watch:{
verificationIMG:function(val){// --
if(val){
watch: {
verificationIMG: function (val) {// --
if (val) {
this.showVerify = true
}else{
} else {
this.showVerify = false
}
},
PhoneVerificationIMG:function(val){// --
if(val){
PhoneVerificationIMG: function (val) {// --
if (val) {
this.showPhoneVerify = true
}else{
} else {
this.showPhoneVerify = false
}
},
},
created(){
if(this.param.account){
created () {
if (this.param.account) {
this.showVerify = true
}
this.blur()
},
methods: {
submitForm(val) {
let ref = val==='phone'?'phoneOrEmail':'login'
let param = val==='phone'?this.phoneOrEmail:this.param
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(res => {
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()
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 => {
if(err.status===30001){
if (err.status === 30001) {
this.phoneVisible = true
}else if(err.status == 10004){
} else if (err.status == 10004 || err.status == 10005) {
param.code = ''
this.blur()
}
});
@ -218,17 +227,64 @@ export default {
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))
},
blur(){
this.param.random = Math.floor(Math.random()*999999999)
this.verificationIMG = this.api.verification+'?random='+`${this.param.random}`
//
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 => { })
},
phoneBlur(){
this.phoneOrEmail.random = Math.floor(Math.random()*999999999)
this.PhoneVerificationIMG = this.api.verification+'?random='+`${this.phoneOrEmail.random}`
//
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 () {
this.param.random = Math.floor(Math.random() * 999999999)
this.verificationIMG = this.api.verification + '?random=' + `${this.param.random}`
},
handleSelect(val){
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 = "";
@ -240,27 +296,27 @@ export default {
// this.blur()
this.phoneBlur()
},
sendPhoneCode(){
if(!this.phone) return this.$message.warning('请输入手机号')
if(!/^1[3456789]\d{9}$/.test(this.phone)) return this.$message.warning('请输入正确的手机号')
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.$post(this.api.sendPhoneOrEmailCode, data).then(res => {
this.phoneCountdown()//
if(res.message.opener){
if (res.message.opener) {
this.phoneOpener = res.message.opener
}else{
} else {
this.$message(res.message)
}
}).catch(res => {})
}).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('请输入验证码')
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,
@ -269,32 +325,32 @@ export default {
platform: 3,
account: this.param.account
}
this.$post(this.api.bindPhoneOrEmail,data).then(res => {
sessionStorage.setItem('token',res.token)
this.$post(this.api.bindPhoneOrEmail, data).then(res => {
sessionStorage.setItem('token', res.token)
this.$router.push({
path:'/customer'
path: '/customer'
});
localStorage.setItem('ms_username', this.param.username);
this.$message.success('绑定成功')
// this.form.phone = this.phone
// this.phoneVisible = false
}).catch(res => {})
}).catch(res => { })
},
phoneCountdown(){
phoneCountdown () {
let count = 60
if(!this.phoneTimer){
if (!this.phoneTimer) {
this.phoneDisabled = true
this.phoneTimer = setInterval(() => {
if(count > 0){
if (count > 0) {
count--
this.phoneBtnText = `${count}秒后重试`
}else{
} else {
this.phoneDisabled = false
clearInterval(this.phoneTimer)
this.phoneTimer = null
this.phoneBtnText = `发送验证码`
}
},1000)
}, 1000)
}
},
},
@ -305,24 +361,28 @@ export default {
.wrap {
min-height: 100%;
}
.logo {
z-index: 2;
position: absolute;
top: 50px;
left: 50px;
}
.login {
position: relative;
height: 100%;
height: 100vh;
background-image: url(../assets/img/devLogin.jpg);
background-size: 100%;
}
.box {
width: 448px;
position: absolute;
right: 20%;
top: 50%;
transform: translateY(-50%);
h1 {
margin-bottom: 20px;
font-size: 34px;
@ -330,22 +390,26 @@ export default {
text-align: center;
}
}
/deep/ .form {
padding: 20px 60px 0;
background-color: rgba(255, 255, 255, .3);
border-radius: 4px;
box-sizing: border-box;
border: 4px solid rgba(255, 255, 255, .2);
.el-input__inner {
height: 50px;
line-height: 50px;
border: 1px solid rgba(220, 220, 220, 1);
border-radius: 2px;
}
.el-form-item {
margin-bottom: 25px;
}
.verification{
.verification {
position: absolute;
top: 1px;
right: 1px;
@ -354,12 +418,14 @@ export default {
cursor: pointer;
}
}
.tab{
.tab {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 24px;
li{
li {
padding: 18px 5px;
margin: 0 20px;
font-size: 16px;
@ -367,23 +433,28 @@ export default {
color: #fff;
cursor: pointer;
border-bottom: 2px solid transparent;
&:last-child{
&:last-child {
margin-right: 0;
}
&.active{
&.active {
color: #fff;
border-bottom-color: #ccc;
}
}
}
.title{
.title {
font-size: 16px;
text-align: center;
font-weight: bold;
}
.login-btn {
text-align: center;
}
.login-btn button {
width: 100%;
height: 48px;
@ -393,13 +464,55 @@ export default {
border-radius: 4px;
border: 0;
}
.forget{
.forget {
margin-bottom: 28px;
text-align: right;
color: #999;
font-weight:bold;
&:hover{
font-weight: bold;
&: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>

@ -4,108 +4,54 @@
<!-- <a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == activeName}" @click="tabChange(index)">{{item}}</a>-->
<!-- </div>-->
<div class="btn-wrap">
<el-button v-auth="'内容管理:保存排序'"
class="action-btn"
type="primary"
@click="sortSubmit">保存排序</el-button>
<el-button v-auth="'内容管理:批量删除'"
class="action-btn"
type="primary"
@click="delAllData">批量删除</el-button>
<el-button v-auth="'内容管理:新增文章'"
class="action-btn"
type="primary"
@click="addArticle">新增文章</el-button>
<el-button v-auth="'内容管理:保存排序'" class="action-btn" type="primary" @click="sortSubmit">保存排序</el-button>
<el-button v-auth="'内容管理:批量删除'" class="action-btn" type="primary" @click="delAllData">批量删除</el-button>
<el-button v-auth="'内容管理:新增文章'" class="action-btn" type="primary" @click="addArticle">新增文章</el-button>
</div>
<div class="page-content"
style="padding-top: 24px">
<el-table ref="table"
:data="list"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
<div class="page-content" style="padding-top: 24px">
<el-table ref="table" :data="list" class="table" header-align="center" @selection-change="handleSelectionChange"
row-key="id">
<el-table-column type="selection"
width="80"
align="center"
:reserve-selection="true"></el-table-column>
<el-table-column type="index"
width="60"
label="序号"
align="center">
<el-table-column type="selection" width="80" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="60" label="序号" align="center">
<template slot-scope="scope">
{{ scope.$index + (pageNo - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="title"
label="标题"
show-overflow-tooltip
align="center">
<el-table-column prop="title" label="标题" show-overflow-tooltip align="center">
</el-table-column>
<el-table-column prop="title"
label="栏目"
show-overflow-tooltip
align="center">
<el-table-column prop="title" label="栏目" show-overflow-tooltip align="center">
{{ columnName }}
</el-table-column>
<el-table-column prop="name"
label="排序值"
width="80"
align="center">
<el-table-column prop="name" label="排序值" width="80" align="center">
<template slot-scope="scope">
<el-input class="sort-input"
width="120"
min="1"
v-model.number="scope.row.sort"
type="number"></el-input>
<el-input class="sort-input" width="120" min="1" v-model.number="scope.row.sort" type="number"></el-input>
<span>{{ scope.row.sort }}</span>
</template>
</el-table-column>
<el-table-column prop="date"
label="添加日期"
align="center">
<el-table-column prop="date" label="添加日期" align="center">
<template slot-scope="scope">
{{ transferDate(scope.row.date) }}
</template>
</el-table-column>
<el-table-column label="操作"
align="center"
width="170">
<el-table-column label="操作" align="center" width="170">
<template slot-scope="scope">
<el-button v-auth="'内容管理:编辑'"
type="text"
@click="editArticle(scope)">编辑</el-button>
<el-divider v-auth="'内容管理:编辑'"
direction="vertical"></el-divider>
<el-button v-auth="'内容管理:删除'"
type="text"
@click="delData(scope.row)">删除</el-button>
<el-button v-auth="'内容管理:编辑'" type="text" @click="editArticle(scope)">编辑</el-button>
<el-divider v-auth="'内容管理:编辑'" direction="vertical"></el-divider>
<el-button v-auth="'内容管理:删除'" type="text" @click="delData(scope.row)">删除</el-button>
</template>
</el-table-column>
<el-table-column prop="name"
label="文章发布状态"
width="120"
align="center">
<el-table-column prop="name" label="文章发布状态" width="120" align="center">
<template slot-scope="scope">
<el-switch v-auth="'内容管理:禁用'"
class="off"
v-model="scope.row.status"
:active-value="0"
:inactive-value="1"
style="margin: 0 5px"
:active-text="scope.row.status ? '关' : '开'"
@change="switchOff($event,scope.row,scope.$index)"></el-switch>
<el-switch v-auth="'内容管理:禁用'" class="off" v-model="scope.row.status" :active-value="0" :inactive-value="1"
style="margin: 0 5px" :active-text="scope.row.status ? '关' : '开'"
@change="switchOff($event, scope.row, scope.$index)"></el-switch>
<span>{{ scope.row.status ? "禁用" : "启用" }}</span>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background
layout="total, prev, pager, next"
:total="totals"
@current-change="handleCurrentChange"
:current-page="pageNo">
<el-pagination background layout="total, prev, pager, next" :total="totals"
@current-change="handleCurrentChange" :current-page="pageNo">
</el-pagination>
</div>
</div>
@ -270,11 +216,11 @@ export default {
}
}
.sort-input + span {
.sort-input+span {
display: none;
}
.off + span {
.off+span {
display: none;
}
</style>

@ -2,19 +2,11 @@
<!-- 内容管理 -->
<div class="flex">
<div class="menu-con">
<el-tree ref="column"
:data="menuList"
:props="{ label: 'name' }"
highlight-current
:expand-on-click-node="false"
default-expand-all
node-key="id"
@node-click="handleSelect"></el-tree>
<el-tree ref="column" :data="menuList" :props="{ label: 'name' }" highlight-current :expand-on-click-node="false"
default-expand-all node-key="id" @node-click="handleSelect"></el-tree>
</div>
<div class="right">
<ContentList ref="content"
v-show="menuList.length"
:columnId="columnId" />
<ContentList ref="content" v-show="menuList.length" :columnId="columnId" />
</div>
</div>
</template>
@ -102,15 +94,18 @@ export default {
height: calc(100vh - 250px);
border-right: solid 1px #e6e6e6;
background-color: #f2f6fc;
/deep/.el-tree-node__content {
height: 50px;
}
}
.right {
flex: 1;
}
/deep/.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
/deep/.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
color: #fff;
background-color: #9278ff;
background-color: #062c87;
}
</style>

@ -2,17 +2,11 @@
<!-- 资讯管理 -->
<div class="page">
<ul class="column-tab">
<li :class="{active: tabsName == 1}"
@click="handleClick(1)"><i class="el-icon-collection-tag"></i> 栏目管理</li>
<li :class="{active: tabsName == 2}"
@click="handleClick(2)"><i class="el-icon-document"></i> 内容管理</li>
<li :class="{ active: tabsName == 1 }" @click="handleClick(1)"><i class="el-icon-collection-tag"></i> 栏目管理</li>
<li :class="{ active: tabsName == 2 }" @click="handleClick(2)"><i class="el-icon-document"></i> 内容管理</li>
</ul>
<columnManage class="flex-1"
ref="content1"
v-if="tabsName == 1" />
<ContentManage class="flex-1"
ref="content2"
v-if="tabsName == 2" />
<columnManage class="flex-1" ref="content1" v-if="tabsName == 1" />
<ContentManage class="flex-1" ref="content2" v-if="tabsName == 2" />
</div>
</template>
@ -75,23 +69,28 @@ export default {
.flex-1 {
flex: 1;
}
.page {
display: flex;
}
.column-tab {
width: 120px;
border-right: solid 1px #e6e6e6;
li {
display: flex;
align-items: center;
height: 60px;
cursor: pointer;
i {
margin-right: 5px;
}
&:hover,
&.active {
color: #9278ff;
color: #062c87;
}
}
}

@ -0,0 +1,251 @@
<template>
<div class="page">
<div style="margin-bottom: 10px;text-align: right;">
<el-button v-auth="'/shop:营销推广管理:新增'" type="primary" round @click="add">新增</el-button>
</div>
<el-table :data="list" class="table" ref="table" header-align="center" row-key="id">
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column prop="courseName" label="图片" min-width="150" align="center">
<template slot-scope="scope">
<img width="100" :src="scope.row.banner" alt="">
</template>
</el-table-column>
<el-table-column prop="title" label="标题" min-width="150" align="center"></el-table-column>
<el-table-column prop="subheading" label="副标题" min-width="150" align="center"></el-table-column>
<el-table-column prop="url" label="链接" min-width="150" align="center"></el-table-column>
<el-table-column label="操作" align="center" width="250">
<template slot-scope="scope">
<el-switch v-model="scope.row.isOpen" :active-value="0" :inactive-value="1"
@change="switchOff($event, scope.row)" v-auth="'/shop:营销推广管理:禁用'">
</el-switch>
<el-button style="margin-left: 10px;" v-auth="'/shop:营销推广管理:编辑'" type="text"
@click="edit(scope.row)">编辑</el-button>
<el-button v-auth="'/shop:营销推广管理:删除'" type="text" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog :title="(form.id ? '编辑' : '新增') + 'banner'" :visible.sync="bannerVisible" width="500px" class="dialog"
:close-on-click-modal="false">
<el-form ref="form" label-width="60px">
<el-form-item label="图片">
<el-upload class="avatar-uploader" accept=".jpg,.png,.jpeg,.gif" :on-change="changeFile"
:show-file-list="false" action="" :auto-upload="false">
<img v-if="form.banner" :src="form.banner" class="avatar">
<div class="uploader-default" v-else>
<i class="el-icon-plus"></i>
<p>上传图片</p>
</div>
</el-upload>
</el-form-item>
<el-form-item label="标题">
<el-input v-model="form.title" placeholder="请输入标题" maxlength="100"></el-input>
</el-form-item>
<el-form-item label="副标题">
<el-input v-model="form.subheading" placeholder="请输入副标题" maxlength="100"></el-input>
</el-form-item>
<el-form-item label="链接">
<el-input v-model="form.url" placeholder="请输入链接" maxlength="100"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="bannerVisible = false">取消</el-button>
<el-button type="primary" @click="submitBanner">确定</el-button>
</span>
</el-dialog>
<!-- 剪裁组件弹窗 -->
<el-dialog title="图片裁剪" append-to-body :visible.sync="cropperModel" width="1100px" :close-on-click-modal="false">
<Cropper ref="cropper" :img-file.sync="file" :is-upload="isUpload" :fixed="true" :fixedNumber.sync="fixedNumber"
:autoCropWidth="500" :autoCropHeight="138.8" @upload="customUpload" />
</el-dialog>
</div>
</template>
<script>
import Util from "@/libs/util";
import Setting from '@/setting'
import Cropper from '@/components/img-upload/Cropper'
import Axios from 'axios'
import Oss from '@/components/upload/upload.js'
export default {
data () {
return {
headers: {
token: sessionStorage.getItem("token")
},
list: [],
bannerVisible: false,
form: {
id: '',
banner: '',
title: '',
subheading: '',
url: '',
},
cropperModel: false,
isUpload: false,
fixedNumber: [5.4, 1],
file: ''
};
},
components: {
Cropper
},
mounted () {
this.getList()
},
methods: {
getList () {
this.$post(this.api.listMarketing, {
pageNum: 1,
pageSize: 1000
}).then(({ page }) => {
this.list = page.records;
this.total = page.total;
}).catch(res => {
});
},
//
customUpload (data) {
data.name = this.file.name
this.imgUpload(data)
},
//
imgUpload (formData) {
this.isUpload = true
Oss.upload(formData).then(res => {
this.form.banner && Oss.del(this.form.banner)
this.form.banner = res.url
})
this.$refs.cropper.isDisabled = false
this.isUpload = false
this.cropperModel = false
},
//
changeFile (file) {
const { size, name } = file
const ext = name.substring(name.lastIndexOf('.') + 1)
if (!Util.isImg(ext)) {
this.$message.error('请上传图片!')
return false
}
this.file = file
this.cropperModel = true
this.$nextTick(() => {
this.$refs.cropper.updateImg({
url: window.URL.createObjectURL(file.raw),
size: file.size
})
})
},
add () {
this.form = {
id: '',
banner: '',
title: '',
subheading: '',
url: '',
}
this.bannerVisible = true
},
edit (row) {
this.form = JSON.parse(JSON.stringify(row))
this.bannerVisible = true
},
// banner
submitBanner () {
const { form } = this
if (!form.banner) return Util.errorMsg('请上传图片')
this.$post(this.api[form.id ? 'updateMarketing' : 'saveMarketing'], form).then(res => {
this.getList()
this.bannerVisible = false
}).catch(res => { })
},
handleDelete (row) {
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
})
.then(() => {
this.$post(`${this.api.delMarketing}?ids=${row.id}`).then(res => {
Util.successMsg("删除成功");
this.getList();
}).catch(res => {
});
})
.catch(() => {
});
},
switchOff (val, row) {
this.$post(`${this.api.bannerEnableOrDisable}?id=${row.id}&isDisable=${row.isOpen}`).then(res => { }).catch(err => { })
}
}
};
</script>
<style lang="scss" scoped>
.m-l-10 {
margin-left: 10px;
}
$avatar-width: 104px;
/deep/ .avatar-uploader {
.el-upload {
position: relative;
width: $avatar-width;
height: $avatar-width;
border: 1px dashed #d9d9d9;
border-radius: 2px;
cursor: pointer;
overflow: hidden;
&:hover {
border-color: #409eff;
}
.uploader-default {
display: flex;
flex-direction: column;
justify-content: center;
width: $avatar-width !important;
height: $avatar-width;
text-align: center;
background: rgba(0, 0, 0, 0.04);
i {
font-size: 20px;
font-weight: bold;
color: #8c939d;
}
p {
margin-top: 10px;
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
line-height: 1;
}
}
.avatar {
width: $avatar-width;
height: $avatar-width;
display: block;
}
}
.el-upload__tip {
margin-top: 0;
p {
font-size: 14px;
color: rgba(0, 0, 0, 0.45);
line-height: 1;
&:first-child {
margin-bottom: 5px;
}
}
}
}
</style>

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

@ -1,103 +1,141 @@
<template>
<div>
<el-card shadow="hover"
class="m-b-20">
<el-card shadow="hover" class="m-b-20">
<div>
<p class="m-b-20">比赛名称</p>
{{ form.stageName }}
</div>
</el-card>
<el-card shadow="hover"
class="m-b-20">
<el-card shadow="hover" class="m-b-20">
<div>
<p class="m-b-20">比赛时间</p>
<div class="date-inputs">
起止时间
<div style="display: inline-flex;align-items: center;">
<el-date-picker v-model="form.time"
type="datetimerange"
range-separator="~"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-dd HH:mm:ss"
<el-date-picker v-model="form.time" type="datetimerange" range-separator="~" 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-alert style="width: auto;padding: 4px 16px;margin-left: 10px;"
:title="'(请设置在 ' + step1.playStartTime + ' ~ ' + step1.playEndTime + '间)'"
type="error"
:closable="false"
:title="'(请设置在 ' + step1.playStartTime + ' ~ ' + step1.playEndTime + '间)'" type="error" :closable="false"
effect="dark">
</el-alert>
</div>
</div>
</div>
</el-card>
<el-card shadow="hover"
class="mgr20 m-b-20">
<!-- 理论系统选择试卷库非理论则选择系统 -->
<el-card shadow="hover" class="m-b-20">
<div>
<p class="m-b-20">课程</p>
<el-radio-group class="m-b-20" v-model="courseSystem" @change="courseSystemChange">
<el-radio :label="0">从课程中选择</el-radio>
<el-radio :label="1">从系统中选择</el-radio>
</el-radio-group>
<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"
<!-- 选择系统 -->
<el-select v-if="courseSystem" v-model="systemId" placeholder="请选择系统" @change="getProject">
<el-option v-for="(item, i) in services" :key="i" :label="item.systemName" :value="item.systemId">
</el-option>
</el-select>
<template v-else>
<!-- 理论 && 选择课程 -->
<el-select v-if="isTheory && !courseSystem" v-model="libraryId" placeholder="请选择试卷库" @change="getProject">
<el-option v-for="(item, i) in paperLibraries" :key="i" :label="item.libraryName" :value="item.libraryId">
</el-option>
</el-select>
<!-- 实训 && 选择课程 -->
<el-cascader v-else-if="!isTheory && !courseSystem" ref="cur" v-model="mallIds" :options="curs"
:props="{ checkStrictly: true, value: 'id' }" popper-class="course-cas" @expand-change="curChange"
@change="curChange"></el-cascader>
</template>
</div>
</div>
</el-card>
<el-card shadow="hover"
class="m-b-20">
<!-- 理论系统 -->
<el-card v-if="isTheory" 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>
</div>
</div>
<p v-if="form.paperName" style="margin-bottom: 20px">
已选试卷{{ form.paperName }}
<el-button type="primary" size="mini" @click="previewPaper(form)">预览</el-button>
</p>
<el-table :data="projects" class="table" header-align="center">
<el-table-column width="60" label="选择" align="center">
<template slot-scope="scope">
<el-radio v-model="form.paperId" :label="scope.row.paperId" @change="paperChange">&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="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"></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>
</el-card>
<el-card v-else 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>
<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>
<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">
<el-table :data="projects" class="table" 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>
<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">
<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">
<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 prop="createTime" label="创建时间" align="center"></el-table-column>
<!-- <el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="showProject(scope.row)">查看</el-button>
@ -105,42 +143,54 @@
</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>
<el-pagination background :page-size="pageSize" @current-change="handleCurrentChange"
layout="total,prev, pager, next" :total="total"></el-pagination>
</div>
</el-card>
<div style="text-align: center">
<el-button @click="back">返回</el-button>
<el-button type="primary"
@click="save">保存</el-button>
<el-button type="primary" @click="save">保存</el-button>
</div>
</div>
</template>
<script>
import util from "@/libs/util";
import Util from '@/libs/util'
import { Loading } from 'element-ui'
import TestPaperConst from '@/const/testPaper'
export default {
props: ['form', 'step1'],
data () {
return {
difficults: TestPaperConst.difficults,
paperTypes: TestPaperConst.paperTypes,
loadIns: null,
mallIds: [],
systemId: '',
curs: [],
paperLibraries: [],
services: [],
keyword: '',
projects: [],
page: 1,
pageSize: 5,
total: 0,
libraryId: '',
sysId: '',
paperId: '',
paperName: '',
permissionsKeys: ['练习', '考核', '竞赛'],
timeInvalid: false
timeInvalid: false,
courseSystem: 1,
};
},
computed: {
//
isTheory () {
return this.form.method === 1
},
},
watch: {
// ,
form: {
@ -152,22 +202,27 @@ export default {
keyword: function (val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.initData();
}, 500);
this.initData()
}, 500)
}
},
mounted () {
this.getCourse()
// this.isTheory ? this.getLibrary() : this.getCourse()
this.getSystem()
},
methods: {
//
async getCourse () {
const sid = this.$store.state.dataPer.find(e => e.permissionName === '服务配置')
const { serviceList } = await this.$post(this.api.queryServiceConfig, {
//
const res = await this.$post(this.api.queryServiceConfig, {
pageNum: 1,
pageSize: 1000,
supplierId: sid ? sid.supplierId : ''
})
const services = res.serviceList.records
//
const { page } = await this.$post(this.api.listOfGoods, {
pageNum: 1,
pageSize: 10000,
@ -179,14 +234,14 @@ export default {
const { records } = page
const { mallId, cid, systemId } = this.form
if (records.length) {
serviceList.records.map(e => {
services.map(e => {
e.id = +e.systemId
e.label = e.systemName
})
records.map(e => {
e.id = +e.mallId
e.label = e.productName
e.children = serviceList.records.filter(n => e.systemId.split(',').includes(n.systemId)) //
e.children = services.filter(n => e.systemId && e.systemId.split(',').includes(n.systemId)) //
})
this.curs = records
@ -201,6 +256,27 @@ export default {
this.getProject()
}
},
//
async getSystem () {
const res = await this.$get(this.api.getServiceOfType, {
type: this.isTheory ? 3 : 1
})
res.serviceList.forEach(e => e.systemId = +e.systemId)
this.services = res.serviceList
if (this.services.length) {
this.systemId = this.form.systemId || this.services[0].systemId
this.getProject()
this.loadIns = Loading.service()
}
},
//
courseSystemChange (val) {
if (val) {
this.getSystem()
} else {
this.isTheory ? this.getLibrary() : this.getCourse()
}
},
//
curChange (val) {
const id = val[0]
@ -216,31 +292,77 @@ export default {
this.loadIns = Loading.service()
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 () {
this.$post(this.api.getProjectAssessmentByCompetition, {
// /
async getProject () {
try {
//
if (this.courseSystem) {
const res = await this.$get(`${this.api.getInternalProjectBySystemId}?permissions=2&systemId=${this.systemId}&keyword=${this.keyword}`)
if (this.isTheory) {
res.forEach(e => {
e.name = e.paperName
})
}
this.projects = res
}
else {
if (this.isTheory) {
//
const res = await this.$post(this.api.examPaperList, {
pageNum: this.page,
pageSize: this.pageSize,
type: 1,
keyWord: this.keyword,
libraryId: this.libraryId,
isDisable: 0,
status: 1
})
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
}).then(({ data }) => {
permissions: 2,
})
this.projects = data.records
this.total = data.total
}
}
} finally {
this.loadIns.close()
}).catch(err => {
this.loadIns.close()
});
}
},
initData () {
this.page = 1;
this.getProject();
this.page = 1
this.getProject()
},
handleCurrentChange (val) {
this.page = val;
this.getProject();
this.page = val
this.getProject()
},
//
toProject () {
@ -250,7 +372,17 @@ export default {
form,
curStep
})
this.$router.push(`/projectList?systemId=${this.mallIds[1]}&show=1&name=${this.$refs.cur.getCheckedNodes()[0].label}`)
let { systemId } = this
let name
if (systemId) {
const cur = this.services.find(e => e.systemId === systemId)
if (cur) name = cur.systemName
}
if (!this.courseSystem && this.mallIds.length > 1) {
systemId = this.mallIds[1]
name = this.$refs.cur.getCheckedNodes()[0].label
}
this.$router.push(`/projectList?systemId=${systemId}&custom=1&name=${name}`)
},
//
timeChange (val) {
@ -260,7 +392,7 @@ export default {
const { playStartTime, playEndTime } = this.step1
if (startTime < new Date(playStartTime) || endTime > new Date(playEndTime)) {
this.timeInvalid = true
return util.warningMsg('设置的阶段比赛时间必须要在第一步设置的竞赛时间范围内,请重新设置。')
return Util.warningMsg('设置的阶段比赛时间必须要在第一步设置的竞赛时间范围内,请重新设置。')
}
this.timeInvalid = false
const { form, curStep } = this.$parent
@ -270,29 +402,67 @@ export default {
const time1 = new Date(form[i].startTime)
const time2 = new Date(form[i].endTime)
if ((startTime >= time1 && startTime <= time2) || (endTime >= time1 && endTime <= time2)) {
util.warningMsg('请注意,所设置的时间与已设置的阶段时间重合。')
Util.warningMsg('请注意,所设置的时间与已设置的阶段时间重合。')
break
}
}
}
}
},
//
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 () {
const { form } = this
if (!form.time.length) return util.warningMsg('请选择比赛时间')
const { form, courseSystem } = this
if (!form.time.length) return Util.warningMsg('请选择比赛时间')
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 (!form.cid) return util.warningMsg('请选择课程')
if (!form.projectId) return util.warningMsg('请选择项目')
if (new Date(form.time[0]) < new Date(playStartTime) || new Date(form.time[1]) > new Date(playEndTime)) return Util.warningMsg('设置的阶段比赛时间必须要在第一步设置的竞赛时间范围内,请重新设置。')
//
if (this.isTheory) {
// if (!this.libraryId) return Util.warningMsg('')
if (!form.paperId) return Util.warningMsg('请选择试卷')
form.libraryId = courseSystem ? '' : this.libraryId
form.systemId = courseSystem ? this.systemId : ''
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
}
if (courseSystem) {
form.mallId = ''
form.cid = ''
}
form.startTime = form.time[0]
form.endTime = form.time[1]
this.handlePaper()
this.$emit('hideSet', this.form)
},
//
async handlePaper () {
const { form } = this
// id
if (this.isTheory && 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 () {
this.$emit('update:form', this.$parent.curOriginForm)
@ -302,5 +472,4 @@ export default {
};
</script>
<style scoped lang="scss">
</style>
<style scoped lang="scss"></style>

@ -37,6 +37,8 @@
<el-input placeholder="请输入竞赛名称" v-model="form.name" clearable></el-input>
</div>
</el-form-item>
<template v-if="!isPractice">
<el-form-item class="req" label="主办方">
<div class="inline-input">
<div class="input-wrap" v-for="(item, index) in sponsorList" :key="index">
@ -72,6 +74,7 @@
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
:picker-options="pickerOptions"></el-date-picker>
</el-form-item>
</template>
<el-form-item class="req" label="竞赛时间">
<el-date-picker v-model="playTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange"
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
@ -92,6 +95,7 @@
</template>
</div>
</el-form-item>
<template v-if="!isPractice">
<el-form-item class="req" label="竞赛类型">
<el-radio v-model="form.completeCompetitionSetup.competitionType" :label="0">个人赛</el-radio>
<el-radio v-model="form.completeCompetitionSetup.competitionType" :label="1">团队赛</el-radio>
@ -128,6 +132,7 @@
<el-button v-if="form.completeCompetitionSetup.isNeedCode === 1" @click="randomInv">随机</el-button>
</div>
</el-form-item>
</template>
<el-form-item class="req" label="竞赛详情">
<quill v-if="quillShow" :border="true" v-model="form.description" :height="400"
:readonly="!editing && form.id !== ''" />
@ -136,6 +141,56 @@
<Upload :limit="5" :file-list.sync="fileList" :on-remove="handleAnnexRemove"
@onSuccess="uploadAnnexSuccess" />
</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" 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>
</div>
</div>
@ -161,7 +216,7 @@
</template>
<script>
import Util from "@/libs/util";
import Util from '@/libs/util'
import quill from "@/components/quill";
import Upload from '@/components/upload';
import Oss from '@/components/upload/upload.js'
@ -293,6 +348,11 @@ export default {
quill,
Upload
},
computed: {
isPractice () {
return this.$parent.releaseType === 2
},
},
watch: {
editing: function (val) {
this.quillShow = false

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

@ -22,6 +22,7 @@
</el-alert>
</div>
</el-form-item>
<!-- 其他赛事 -->
<template v-if="item.method === 2">
<el-form-item class="req" label="比赛地点">
<el-input v-model="item.offlineAddress" style="width: 80%"></el-input>
@ -70,12 +71,23 @@
</el-form-item>
</template>
<template v-else>
<template v-if="item.method === 0">
<el-form-item class="req" prop="cid" label="课程系统">
{{ item.systemName }}
</el-form-item>
<el-form-item class="req" prop="assessmentId" label="已选择考核">
{{ item.projectName }}
</el-form-item>
</template>
<el-form-item v-else 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>
<el-form-item class="req" prop="resultAnnouncementTime" label="比赛地点">
<div class="line">
<el-checkbox v-model="item.onlineButton">线上</el-checkbox>
@ -94,12 +106,11 @@
</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"
custom-class="tips-dia">
<p style="font-size: 17px;text-align: center;color: #9076ff;">编辑发布成功</p>
<p style="font-size: 17px;text-align: center;color: #062c87;">编辑发布成功</p>
<p style="margin: 5px 0px 10px;line-height: 1.6">
温馨提示报名结束后更改报名时间或赛程规则不影响已分配的阶段参赛人员且后续添加的人员不会自动分配如需重新自动分配所有团队请到报名列表执行全员重新分配操作
</p>
@ -113,11 +124,13 @@
</template>
<script>
import Set from './set'
import Oss from '@/components/upload/upload.js'
import Setting from '@/setting'
import Util from '@/libs/util'
import set from './set'
export default {
props: ['setupId', 'competitionId', 'editing'],
components: { Set },
data () {
return {
headers: {
@ -151,6 +164,8 @@ export default {
stageId: '',
startTime: '',
systemId: '',
paperId: '',
paperName: '',
offlineAddress: '',
offlineButton: 0,
onlineAddress: '',
@ -166,9 +181,6 @@ export default {
tipsVisible: false,
};
},
components: {
set
},
watch: {
// ,
form: {
@ -237,8 +249,10 @@ export default {
form.method = e.method
form.stageId = e.stageId
form.stageName = e.stageName
if (form.paperName) form.originPaperName = form.paperName //
this.form.push(form)
})
this.resumeData()
this.$nextTick(() => {
this.updateTime = 0
@ -258,6 +272,19 @@ export default {
this.setVisible = false
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) {
if (val.length) {
@ -363,6 +390,7 @@ export default {
this.$confirm('团队赛发布成功,由于您设置的报名时间已结束,如需自动分配阶段参赛人员,请前往报名人员列表进行设置', '提示', {
confirmButtonText: '关闭',
type: 'success',
showCancelButton: false,
closeOnClickModal: false,
dangerouslyUseHTMLString: true,
showClose: false,
@ -377,6 +405,10 @@ export default {
this.$emit('next', next)
}
},
// websocket
async sendSocket () {
await this.$post(`${this.api.refreshPageNotification}?content=1`)
},
//
save (status, next = 0) {
const { form } = this
@ -401,9 +433,14 @@ export default {
Util.errorMsg('设置的阶段比赛时间必须要在第一步设置的竞赛时间范围内,请重新设置。')
break
}
if (e.method !== 2 && !e.cid) {
if (e.method === 0 && !e.projectId) {
invalid = 1
Util.errorMsg('请选择课程')
Util.errorMsg('请选择项目')
break
}
if (e.method === 1 && !e.paperId) {
invalid = 1
Util.errorMsg('请选择试卷')
break
}
if (e.method === 2) { // 线
@ -470,7 +507,10 @@ export default {
}).then(res => {
this.$parent.hideLoad()
//
status && this.publish(status)
if (status) {
this.publish(status)
this.sendSocket()
}
Util.successMsg((status ? '发布' : '保存') + '成功')
this.updateTime = 0
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" 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">
<ul class="filter">
<li>
<label>赛来源</label>
<el-select v-model="form.platformSource" clearable @change="sourceChange">
<label>赛来源</label>
<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-select>
</li>
<li>
<label>大赛范围</label>
<el-select v-model="form.competitionScope" clearable @change="initData">
<label>发布类型</label>
<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-select>
</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>
<div>
<el-button type="primary" round @click="add" v-auth>创建竞赛</el-button>
@ -47,7 +65,7 @@
</div>
</div>
<el-table ref="table" :data="matchData" class="table" stripe header-align="center"
<el-table ref="table" :data="matchData" class="table" 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">
@ -55,35 +73,40 @@
{{ scope.$index + (page - 1) * pageSize + 1 }}
</template>
</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="competitionName" min-width="160" label="竞赛名称" align="center"></el-table-column>
<el-table-column prop="name" label="竞赛来源" width="90" align="center">
<template slot-scope="scope">
{{ scope.row.competitionType ? '团队赛' : '个人赛' }}
{{ sourceList.find(e => e.id === scope.row.platformSource).name }}
</template>
</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">
{{ sourceList.find(e => e.id === scope.row.platformSource).name }}
{{ scope.row.releaseType ? '设置完整比赛' : '练习赛' }}
</template>
</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">
{{ rangeList.find(e => e.id === scope.row.competitionScope).name }}
</template>
</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="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="90"></el-table-column>
<el-table-column prop="status" label="状态" align="center" width="60">
<template slot-scope="scope">
{{ scope.row.publishStatus ? '已发布' : '未发布' }}
</template>
</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">
{{ scope.row.playStartTime }} ~ {{ scope.row.playEndTime }}
</template>
</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">
<template slot-scope="scope">
<el-button type="text" @click="copy(scope.row)">复制</el-button>
@ -104,7 +127,7 @@
</div>
<el-dialog title="修改当前阶段结束时间" :visible.sync="modifyVisible" width="900px" :close-on-click-modal="false">
<el-table :data="curRow.playingStages" class="table" ref="table" stripe header-align="center">
<el-table :data="curRow.playingStages" class="table" ref="table" header-align="center">
<el-table-column prop="stageName" label="阶段名称" min-width="100" align="center"></el-table-column>
<el-table-column label="竞赛起止时间" width="300" align="center">
<template slot-scope="scope">
@ -128,7 +151,7 @@
</template>
<script>
import util from "@/libs/util";
import Util from '@/libs/util'
import Bus from '@/libs/bus'
import qs from 'qs'
export default {
@ -150,11 +173,25 @@ export default {
name: "院校创建"
}
],
rangeList: [
releaseTypes: [
{
id: '',
name: "不限"
},
{
id: 0,
name: '发布信息'
},
{
id: 1,
name: '完整比赛'
}
],
rangeList: [
{
id: null,
name: "不限"
},
{
id: 1,
name: "全平台"
@ -168,14 +205,45 @@ export default {
name: "校内"
}
],
competitionTypes: [
{
id: '',
name: '不限'
},
{
id: 0,
name: '个人赛'
},
{
id: 1,
name: '团队赛'
}
],
publishStatus: [
{
id: '',
name: '不限'
},
{
id: 0,
name: '未发布'
},
{
id: 1,
name: '已发布'
}
],
matchData: [],
form: {
keyWord: this.$route.query.keyWord || null,
month: +this.$route.query.month || '',
startTime: this.$route.query.startTime || '',
endTime: this.$route.query.endTime || '',
platformSource: this.$route.query.platformSource === 'null' ? null : (+this.$route.query.platformSource || 0), // (01)
competitionScope: this.$route.query.competitionScope ? +this.$route.query.competitionScope : '', // (0: 1: 2.)
keyWord: null,
month: '',
startTime: null,
endTime: null,
releaseType: '',
publishStatus: '',
competitionType: '',
platformSource: 0, // (01)
competitionScope: null, // (0: 1: 2.)
},
multipleSelection: [],
dateList: [
@ -215,13 +283,14 @@ export default {
}]
},
loading: false,
now: '',
};
},
watch: {
"form.month": function (val) {
if (val) {
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 {
this.date = [];
}
@ -246,6 +315,18 @@ export default {
mounted () {
const { query } = this.$route
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(() => { })
}
@ -260,53 +341,57 @@ export default {
})
},
methods: {
getData () {
async getData () {
this.loading = true
try {
const { form } = this
this.$post(this.api.CompetitionPageConditionQueryByNakadai, {
const { data } = await this.$post(this.api.CompetitionPageConditionQueryByNakadai, {
pageNum: this.page,
pageSize: this.pageSize,
competitionScope: form.competitionScope === '' ? null : form.competitionScope,
endTime: form.endTime || null,
keyWord: form.keyWord,
platformSource: form.platformSource,
startTime: form.startTime || null,
}).then(({ data }) => {
const list = data.records
//
...form
})
this.matchData = data.records
this.now = await Util.getNow()
clearInterval(this.timer)
this.handleBeganStage()
this.timer = setInterval(() => {
const now = new Date()
list.map(e => {
this.now = new Date(this.now.setSeconds(this.now.getSeconds() + 1))
this.handleBeganStage()
}, 1000)
this.total = data.total
this.$refs.table.clearSelection()
this.loading = false
if (!this.matchData.length && this.total) {
this.page--
this.getData()
}
} catch (e) {
this.loading = false
}
},
//
async handleBeganStage () {
this.matchData.map(e => {
if (!e.playingStages) {
this.$set(e, 'playingStages', [])
} else {
e.playingStages = []
}
//
if (now >= new Date(e.playStartTime) && now <= new Date(e.playEndTime)) {
if (this.now >= new Date(e.playStartTime) && this.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)) {
if (this.now >= new Date(n.startTime) && this.now <= new Date(n.endTime)) {
e.playingStages.push(n)
}
}
}
}
})
}, 1000)
this.matchData = list
this.total = data.total
this.$refs.table.clearSelection()
this.loading = false
if (!this.matchData.length && this.total) {
this.page--
this.getData()
}
}).catch(res => {
this.loading = false
})
},
initData () {
this.page = 1;
@ -326,7 +411,7 @@ export default {
type: "warning"
}).then(async () => {
await this.$post(`${this.api.copyCompetition}?competitionId=${row.id}`)
util.successMsg('复制成功')
Util.successMsg('复制成功')
this.initData()
}).catch(() => { })
},
@ -349,7 +434,7 @@ export default {
competitionContents: data
}).then(async res => {
await this.$post(`${this.api.refreshPageNotification}?content=1`)
util.successMsg('修改成功')
Util.successMsg('修改成功')
this.modifyVisible = false
this.getData()
}).catch(err => { })
@ -374,7 +459,7 @@ export default {
})
.then(() => {
this.$post(`${this.api.batchDeleteCompetition}?competitionIds=${row.id}`).then(res => {
util.successMsg("删除成功");
Util.successMsg("删除成功");
this.getData();
}).catch(res => {
});
@ -419,7 +504,7 @@ export default {
isOpen: val,
type: 0 // (01)
}).then(res => {
util.successMsg(val == 1 ? '禁用成功' : '启用成功')
Util.successMsg(val == 1 ? '禁用成功' : '启用成功')
}).catch(err => { })
await this.$post(`${this.api.refreshPageNotification}?content=1`)
@ -430,7 +515,12 @@ export default {
<style lang="scss" scoped>
/deep/ .tool {
margin-bottom: 0;
.filter {
flex-wrap: wrap;
li {
margin-bottom: 15px;
}
.el-input {
min-width: 190px;
}

@ -23,8 +23,8 @@
</div>
</div>
<el-table ref="table" :data="listData" class="table" stripe header-align="center"
@selection-change="handleSelectionChange" row-key="id" v-loading="loading" @sort-change="sortChange">
<el-table ref="table" :data="listData" class="table" header-align="center" @selection-change="handleSelectionChange"
row-key="id" v-loading="loading" @sort-change="sortChange">
<el-table-column type="selection" width="80" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="60" label="序号" align="center">
<template slot-scope="scope">

@ -42,7 +42,6 @@ export default {
tab3: "竞赛进展",
tab4: "公告通知",
tab5: "报名人员",
tab6: '查看异常团队'
}
};
},
@ -55,7 +54,11 @@ export default {
AbnormalTeam
},
mounted () {
Setting.dynamicRoute && this.initTabs()
// if (Setting.dynamicRoute) {
this.initTabs()
// } else {
// this.active = this.$route.query.tab || 'tab1'
// }
},
methods: {
async initTabs () {
@ -73,7 +76,12 @@ export default {
tab3 || this.$delete(this.tabs, 'tab3')
tab4 || this.$delete(this.tabs, 'tab4')
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 keys = Object.keys(this.tabs)
@ -117,7 +125,7 @@ export default {
// tab
tabSwitch (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
backOrTab (i) {

@ -1,61 +1,57 @@
<template>
<!-- 报名人员 -->
<div class="page-content"
style="padding: 24px">
<el-table ref="table"
:data="list"
class="table"
stripe
header-align="center"
row-key="stageId">
<el-table-column type="index"
width="60"
label="序号"
align="center">
<div class="page-content" style="padding: 24px">
<el-table ref="table" :data="list" class="table" header-align="center" row-key="stageId">
<el-table-column type="index" width="60" label="序号" align="center">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="stageName"
label="阶段名称"
align="center"></el-table-column>
<el-table-column prop="methodName"
label="比赛方式"
align="center"></el-table-column>
<el-table-column prop="founderName"
label="比赛形式"
align="center">
<el-table-column prop="stageName" label="阶段名称" align="center"></el-table-column>
<el-table-column prop="competitionContent" label="比赛内容" align="center"></el-table-column>
<el-table-column prop="methodName" label="比赛方式" align="center"></el-table-column>
<el-table-column label="竞赛类型" align="center">
<template slot-scope="scope">
{{ scope.row.competitionType ? '团队赛' : '个人赛' }}
</template>
</el-table-column>
<el-table-column prop="ruleName"
label="赛制"
align="center"></el-table-column>
<el-table-column prop="status"
label="状态"
align="center"></el-table-column>
<el-table-column label="竞赛起止时间"
width="290"
align="center">
<el-table-column prop="ruleName" label="赛制" align="center"></el-table-column>
<el-table-column prop="status" label="大赛状态" align="center"></el-table-column>
<el-table-column prop="reviewStatus" label="评阅情况" align="center"></el-table-column>
<el-table-column label="竞赛时间" width="290" align="center">
<template slot-scope="scope">
{{ scope.row.startTime + ' ~ ' + scope.row.endTime }}
</template>
</el-table-column>
<el-table-column label="操作"
align="center"
width="260">
<el-table-column label="操作" align="center" width="280">
<template slot-scope="scope">
<el-button type="primary"
@click="toRank(scope.row, scope.$index)">排名</el-button>
<el-button @click="toArch(scope.row, scope.$index)">成绩管理</el-button>
<el-button type="text" @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> -->
<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>
</el-table-column>
</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>
</template>
<script>
import Setting from '@/setting'
import Const from '@/const/match'
export default {
name: "matchArch",
@ -66,6 +62,8 @@ export default {
form: {},
timer: null,
curStep: [],
reviewVisible: false,
reviewUrl: '',
};
},
mounted () {
@ -125,7 +123,16 @@ export default {
this.$store.commit('setInnerReferrer', this.$route.fullPath)
const cur = this.form.competitionStage[i]
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
}
}
};
@ -136,12 +143,26 @@ export default {
font-size: 16px;
color: #333;
}
.line {
display: flex;
justify-content: space-around;
align-items: center;
span {
margin-right: 30px;
}
}
/deep/.review-dia {
.el-drawer__close-btn {
position: absolute;
top: 20px;
right: 20px;
}
iframe {
height: 100%;
}
}
</style>

@ -1,309 +1,252 @@
<template>
<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">
<el-page-header @back="back"
content="成绩管理"></el-page-header>
<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">
<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>
<p class="val">{{ isNaN(statData.totalNumber) ? '' : statData.attendance + '/' + statData.totalNumber }}
</p>
</div>
<div class="item">
<p class="name">实验平均分</p>
<p class="val">{{ avgScore }}</p>
<p class="name">平均分</p>
<p class="val">{{ (+statData.avgScore).toFixed(2) }}</p>
</div>
<div class="item">
<p class="name">最高分</p>
<p class="val">{{ statData.maxScore }}
</p>
</div>
<div class="item">
<p class="name">最低分</p>
<p class="val">{{ statData.minScore }}</p>
</div>
<div class="chart"
id="chart"></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>
<el-card shadow="hover" class="m-b-20">
<div class="tabs m-b-20">
<a class="item" v-for="(item, i) in tabs" :key="i" :class="{ active: item.id === active }"
@click="tabChange(item.id)">{{ item.name }}</a>
</div>
<div class="flex-between m-b-20">
<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 v-if="active">
<label>评阅状态</label>
<el-select v-model="filter.reviewStatus" clearable placeholder="请选择评阅状态" @change="initData">
<el-option value="待评阅"></el-option>
<el-option value="已评阅"></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>
<el-input size="small"
placeholder="请输入学校/学生姓名"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
style="width: 300px"></el-input>
</div>
<div v-if="!active">
<el-button v-if="method == 2"
type="primary"
@click="batchImport">上传成绩</el-button>
<el-button type="primary"
: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>
<template v-if="active && method === 1">
<el-button v-auth="'/review:分配评阅任务'" type="primary" size="mini"
@click="showReview('/allocationReview')">分配评阅任务</el-button>
<el-button v-if="showMyReviewTask" type="primary" size="mini"
@click="showReview('/myReview/records')">我的评阅任务</el-button>
<el-button type="primary" size="mini" @click="exportFiles">导出答题文件</el-button>
</template>
<el-button type="primary" size="mini" :loading="exportingList" @click="exportList">{{ exportingList ? '正在导出'
:
'导出成绩列表'
}}</el-button>
<template v-if="active">
<el-button type="primary" size="mini" :loading="exportingReport" @click="exporReport">{{ exportingReport ?
'正在导出' :
'导出成绩报告'
}}</el-button>
<el-button type="primary" size="mini" @click="delAllData">批量删除</el-button>
</template>
</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">
<el-table :data="list" class="table" :key="1" ref="table" header-align="center"
@selection-change="handleSelectionChange" row-key="id" @sort-change="sortChange">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="60" label="序号" align="center">
<template slot-scope="scope">
{{ scope.$index + (page - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="schoolName"
label="学生账号归属"
min-width="100"
<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="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">
<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" sortable="custom">
<template slot-scope="scope">
{{ scope.row.submitTime ? scope.row.score : '--' }}
</template>
</el-table-column>
<el-table-column prop="timeSum"
label="耗时"
width="90"
align="center">
<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">
<el-table-column prop="submitTime" label="提交时间" min-width="150" align="center" sortable="custom">
<template slot-scope="scope">
{{ scope.row.submitTime || '--' }}
</template>
</el-table-column>
<el-table-column label="状态"
width="100"
align="center">
<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">
<el-table-column prop="evaluationStatus" label="评阅状态" align="center" width="90">
<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>
<span v-if="scope.row.reviewStatus === '-'">-</span>
<el-tag v-else :type="scope.row.reviewStatus === '待评阅' ? 'danger' : 'success'">{{ scope.row.reviewStatus
}}</el-tag>
</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>
<el-table-column v-if="active" label="操作" align="center" width="300">
<template v-if="scope.row.reportId" slot-scope="scope">
<template v-if="method === 1">
<el-popover placement="top" trigger="click" popper-class="files-tip">
<div>
<ul class="match-files">
<li v-for="(file, i) in scope.row.files" :key="i" @click="preview(file.attachmentUrl)">{{
file.attachmentName }}</li>
</ul>
</div>
<el-button slot="reference" :disabled="!scope.row.hasFile" type="text"
@click="showFiles(scope.row)">查看答题文件</el-button>
</el-popover>
<el-button style="margin-left: 10px;" :disabled="!scope.row.hasFile" type="text"
@click="downloadFile(scope.row)">下载答题文件</el-button>
</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="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>
<el-button v-if="method != 2" type="text" @click="toReport(scope.row)">查看成绩报告</el-button>
<el-button 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="total1"
@current-change="handleCurrentChange1"
:current-page="page1">
<el-pagination background layout="total, prev, pager, next" :total="total"
@current-change="handleCurrentChange" :current-page="page">
</el-pagination>
</div>
</template>
</el-card>
</div>
<el-dialog title="批量导入"
:visible.sync="importVisible"
width="24%"
:close-on-click-modal="false"
<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>
<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="{
<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-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;"
style="margin-bottom: 10px;font-size: 14px;color: #062c87;text-decoration: underline;cursor: pointer;"
@click="showFaild">部分数据导入失败查看失败原因</p>
</template>
</div>
<span v-if="uploading"
slot="footer"
class="dialog-footer">
<span v-if="uploading" slot="footer" class="dialog-footer">
<el-button @click="cancelUpload">停止导入</el-button>
</span>
</el-dialog>
<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>
<el-dialog title="图片预览" :visible.sync="previewImgVisible" width="800px" :close-on-click-modal="false">
<el-image style="max-width: 100px; max-height: 100px" :src="previewImg" :preview-src-list="[previewImg]">
</el-image>
</el-dialog>
<PdfDia :key="pdfVisible" :visible.sync="pdfVisible" :src.sync="pdfSrc" />
</div>
</template>
<script>
import util from "@/libs/util";
import Setting from '@/setting'
import PdfDia from '@/components/pdf'
import Util from '@/libs/util'
import * as echarts from "echarts";
import axios from 'axios';
import Zip from '@/libs/zip'
export default {
components: {
PdfDia
},
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,
showMyReviewTask: +this.$route.query.showMyReviewTask,
isCompress: Util.isCompress,
filter: {
provinceId: '',
cityId: '',
realSchoolId: '',
reviewStatus: '',
scoreSortOrder: '',
submitTimeSortOrder: '',
},
provinces: [],
cities: [],
schools: [],
keyword: this.$route.query.keyword || '',
searchTimer: null,
list: [],
@ -326,12 +269,34 @@ export default {
headers: {
token: sessionStorage.getItem("token")
},
statData: {},
tabs: ['成绩列表', '文件列表'],
active: 0,
statData: {
avgScore: 0,
maxScore: 0,
minScore: 0,
},
tabs: [
{
id: 1,
name: '已提交'
},
{
id: 0,
name: '未提交'
}
],
active: 1,
loading: false,
exporting: false,
exporting1: false,
exportingFiles: false,
exportingList: false,
exportingReport: false,
previewImgVisible: false,
previewImg: '',
pdfVisible: false,
pdfSrc: '',
reviewVisible: false,
reviewUrl: '',
};
},
watch: {
@ -351,76 +316,141 @@ export default {
},
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,
})
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
isNakadai: 1,
participatingState: this.active,
...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()
}
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
},
//
sortChange (column) {
if (column.prop === 'score') this.filter.scoreSortOrder = column.order ? column.order === 'ascending' ? 'ASC' : 'DESC' : ''
if (column.prop === 'submitTime') this.filter.scoreSortOrder = column.order ? column.order === 'ascending' ? 'ASC' : 'DESC' : ''
this.getData()
},
//
async showFiles (row) {
const { data } = await this.$get(this.api.getPaperUploadFile, {
reportId: row.reportId
})
this.$set(row, 'files', data)
},
//
async downloadFile (row) {
const res = await axios.post(this.api.getPaperUploadFileZip, {
reportIds: [row.reportId],
// reportIds: [3785],
stageId: this.stageId
}, {
headers: this.headers,
responseType: 'blob'
})
const name = res.headers['content-disposition']
Util.downloadFileDirect(name ? decodeURI(name) : '答题文件.zip', new Blob([res.data]))
},
//
show (row) {
this.$router.push(`/matchReport?reportId=${row.reportId}`)
toReport (row) {
this.$router.push(`/${this.method === 1 ? 'theoryReport' : 'trialReport'}?reportId=${row.reportId}`)
},
//
showReview (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=${this.stageId}`
localStorage.setItem('review_token', sessionStorage.getItem('token'))
this.reviewUrl = url
this.reviewVisible = true
},
// ()
async exportData () {
//
async exportFiles () {
if (this.list.length) {
this.exporting = true
this.exportingFiles = true
const list = this.multipleSelection
const ids = []
if (list.length) {
list.forEach(e => {
e.reportId && ids.push(e.reportId)
})
}
const res = await axios.post(this.api.getPaperUploadFileZip, {
reportIds: ids,
// reportIds: [3785],
stageId: this.stageId
}, {
headers: this.headers,
responseType: 'blob'
})
const name = res.headers['content-disposition']
Util.downloadFileDirect(name ? decodeURI(name) : '答题文件.zip', new Blob([res.data]))
this.exportingFiles = false
}
},
// ()
async exportList () {
if (this.list.length) {
this.exportingList = 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
Util.downloadFileDirect(`赛事成绩.xls`, new Blob([res.data]))
this.exportingList = false
} else if (this.list.length) {
const res = await axios.post(this.api.allExperimentalResultsAreDerived, {
pageNum: 1,
@ -428,40 +458,70 @@ export default {
competitionId: this.id,
isNakadai: 1,
stageId: this.stageId,
participatingState: this.active,
}, {
headers: this.headers,
responseType: 'blob'
})
util.downloadFileDirect(`赛事成绩.xls`, new Blob([res.data]))
this.exporting = false
Util.downloadFileDirect(`赛事成绩.xls`, new Blob([res.data]))
this.exportingList = false
}
}
},
// ()
exportData1 () {
this.exporting1 = true
let list = this.list1
if (this.multipleSelection1.length) {
list = this.multipleSelection1
// ()
async exporReport () {
if (this.list.length) {
this.exportingReport = true
const list = this.multipleSelection
const ids = []
if (list.length) {
list.forEach(e => {
e.reportId && ids.push(e.reportId)
})
}
Zip('批量导出', list, () => {
this.exporting1 = false
let res
//
if (this.method) {
res = await axios.post(this.api.exportExamPaperReports, {
ids,
stageId: list.length ? '' : this.stageId
}, {
headers: this.headers,
responseType: 'blob'
})
Util.downloadFileDirect('成绩报告.zip', new Blob([res.data]))
this.exportingReport = false
} else {
//
res = await axios.post(this.api.batchExportReportsAsZip, {
reportIds: ids,
stageId: this.stageId,
competitionId: this.id,
}, {
headers: this.headers,
responseType: 'blob'
})
Util.downloadFileDirect('成绩报告.zip', new Blob([res.data]))
this.exportingReport = false
}
}
},
handleDelete (row) { //
this.$confirm("确定要删除吗?", "提示", {
type: "warning"
}).then(() => {
this.$post(this.api.batchDeleteContestGrade, {
async handleDelete (row) { //
await this.$confirm(`<p>确认要删除【${row.userName}】的成绩记录吗?</p><p style="color: #f56c6c;">删除后成绩数据不可恢复,自动变为未提交</p>`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
dangerouslyUseHTMLString: true,
})
await 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(() => { });
})
Util.successMsg("删除成功")
this.getData()
},
delAllData () { //
const list = this.multipleSelection
@ -483,7 +543,7 @@ export default {
await this.$post(this.api.batchDeleteContestGrade, data)
this.multipleSelection = [];
this.$refs.table.clearSelection();
util.successMsg("删除成功");
Util.successMsg("删除成功");
this.getData();
}).catch(() => { });
},
@ -505,16 +565,8 @@ export default {
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])
}
const { fractionalSegmentCounts: data } = this.statData
let myChart = echarts.init(document.getElementById("chart"));
myChart.setOption({
title: { text: "实验分数分布图" },
@ -524,7 +576,7 @@ export default {
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"]
data: data.map(e => e.range)
},
yAxis: {
name: "人数",
@ -532,9 +584,13 @@ export default {
minInterval: 10
},
series: [{
data,
data: data.map(e => e.count),
type: "line",
areaStyle: {},
label: {
show: true,
position: 'top'
},
color: ["#8191fd"]
}]
});
@ -551,12 +607,12 @@ export default {
headers: this.headers,
responseType: 'blob'
}).then((res) => {
util.downloadFileDirect('赛事成绩导入模板.xlsx', new Blob([res.data]))
Util.downloadFileDirect('赛事成绩导入模板.xlsx', new Blob([res.data]))
}).catch(res => { })
},
//
handleExceed (files, fileList) {
util.warningMsg(
Util.warningMsg(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
)
},
@ -566,7 +622,7 @@ export default {
headers: this.headers,
responseType: 'blob'
}).then((res) => {
util.downloadFileDirect(`批量导入成绩管理失败数据导出.xls`, new Blob([res.data]))
Util.downloadFileDirect(`批量导入成绩管理失败数据导出.xls`, new Blob([res.data]))
}).catch(res => { })
},
uploadSuccess (res) {
@ -579,11 +635,11 @@ export default {
this.faildData = data
this.uploadFaild = true
} else {
util.successMsg(data.tip, 3000)
Util.successMsg(data.tip, 3000)
this.importVisible = false
}
} else {
util.errorMsg(res.message || '上传失败,请检查数据')
Util.errorMsg(res.message || '上传失败,请检查数据')
}
},
uploadError (err, file, fileList) {
@ -613,29 +669,23 @@ export default {
},
// tab
tabChange (i) {
this.multipleSelection = []
this.$refs.table.clearSelection()
this.active = i
this.getData()
this.initData()
},
//
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()
preview (url) {
const ext = url.split('.').pop()
if (Util.isDoc(ext)) {
window.open('https://view.officeapps.live.com/op/view.aspx?src=' + url)
} else if (Util.isImg(ext)) {
this.previewImgVisible = true
this.previewImg = url
} else if (ext === 'pdf') {
this.pdfVisible = true
this.pdfSrc = url
}
},
back () {
this.$router.push(this.$store.state.innerReferrer)
@ -663,12 +713,31 @@ export default {
}
}
.tool {
align-items: flex-start;
margin-bottom: 10px;
.filter {
flex-wrap: wrap;
}
li {
margin-bottom: 10px;
}
/deep/.el-select {
width: 140px;
}
}
.stat {
display: flex;
.nums {
display: flex;
flex-wrap: wrap;
align-items: center;
width: 640px;
margin-right: 20px;
.item:nth-child(1) {
@ -679,6 +748,14 @@ export default {
background-image: url('../../../assets/img/avg.png');
}
.item:nth-child(3) {
background-image: url('../../../assets/img/ach1.png');
}
.item:nth-child(4) {
background-image: url('../../../assets/img/ach2.png');
}
.item {
width: 300px;
min-height: 145px;
@ -703,10 +780,11 @@ export default {
}
.chart {
flex: 1;
width: calc(100% - 660px);
height: 300px;
}
}
/deep/.import-file {
.el-progress__text,
.el-progress,
@ -714,4 +792,16 @@ export default {
display: none !important;
}
}
/deep/.review-dia {
.el-drawer__close-btn {
position: absolute;
top: 20px;
right: 20px;
}
iframe {
height: 100%;
}
}
</style>

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

@ -1,74 +1,43 @@
<template>
<!-- 竞赛进展 -->
<div class="page-content"
style="padding: 24px">
<el-table ref="table"
:data="listData"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
<div class="page-content" style="padding: 24px">
<el-table ref="table" :data="listData" class="table" header-align="center" @selection-change="handleSelectionChange"
row-key="id">
<el-table-column type="index"
width="60"
label="序号"
align="center">
<el-table-column type="index" width="60" label="序号" align="center">
<template slot-scope="scope">
{{ scope.$index + (pageNo - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="name"
label="标题">
<el-table-column prop="name" label="标题">
<template slot-scope="scope">
<el-input placeholder="请输入标题"
:disabled="!scope.row.operate"
v-model="scope.row.title"></el-input>
<el-input placeholder="请输入标题" :disabled="!scope.row.operate" v-model="scope.row.title"></el-input>
</template>
</el-table-column>
<el-table-column prop="name"
label="详情描述">
<el-table-column prop="name" label="详情描述">
<template slot-scope="scope">
<el-input placeholder="请输入详情描述"
:disabled="!scope.row.operate"
type="textarea"
<el-input placeholder="请输入详情描述" :disabled="!scope.row.operate" type="textarea"
v-model="scope.row.description"></el-input>
</template>
</el-table-column>
<el-table-column prop="name"
label="状态"
width="150">
<el-table-column prop="name" label="状态" width="150">
<template slot-scope="scope">
<el-select v-model="scope.row.status"
:disabled="!scope.row.operate"
clearable
placeholder="请选择状态">
<el-option v-for="(item,index) in statusList"
:key="index"
:label="item.name"
<el-select v-model="scope.row.status" :disabled="!scope.row.operate" clearable placeholder="请选择状态">
<el-option v-for="(item, index) in statusList" :key="index" :label="item.name"
:value="item.value"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="操作"
align="center"
width="170">
<el-table-column label="操作" align="center" width="170">
<template slot-scope="scope">
<el-button v-if="!scope.row.operate"
type="text"
@click="operateIt(scope.row)"
<el-button v-if="!scope.row.operate" type="text" @click="operateIt(scope.row)"
v-auth="'/match:管理:竞赛进展:编辑'">编辑</el-button>
<el-button v-else
type="text"
@click="saveData(scope.row)">保存</el-button>
<el-button type="text"
@click="handleDelete(scope.row, scope.$index)"
<el-button v-else type="text" @click="saveData(scope.row)">保存</el-button>
<el-button type="text" @click="handleDelete(scope.row, scope.$index)"
v-auth="'/match:管理:竞赛进展:删除'">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="plus"
@click="addData"
v-auth="'/match:管理:竞赛进展:新增'">
<div class="plus" @click="addData" v-auth="'/match:管理:竞赛进展:新增'">
<i class="el-icon-circle-plus-outline"></i>
</div>
</div>

@ -1,7 +1,7 @@
<template>
<div>
<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>
</div>
@ -14,15 +14,41 @@
@click="tabChange(item.stageId)">{{ item.stageName }}排名</a>
</template>
</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">
<el-radio v-model="type" :label="0" @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>
</div>
<div style="display: inline-flex;align-items: center">
<ul class="filter" style="flex: none;">
<li>
<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>
<template v-else>
<span style="margin-right: 10px;white-space: nowrap;">{{ publishTime }}发布排名</span>
@ -31,10 +57,11 @@
<el-button v-if="list.length" type="primary" :loading="exporting" @click="exportData">{{ exporting ? '正在导出' :
'批量导出'
}}</el-button>
</ul>
</div>
</div>
<el-table :data="list" class="table" ref="table" stripe row-key="scoreId"
@selection-change="handleSelectionChange" header-align="center">
<el-table :data="list" class="table" ref="table" row-key="scoreId" @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="index" width="60" label="排名" align="center">
<template slot-scope="scope">
@ -46,6 +73,8 @@
<el-table-column prop="leaderName" label="队长" min-width="150" align="center"></el-table-column>
</template>
<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="realSchool" label="学生所在院校" min-width="100" align="center"></el-table-column>
<el-table-column prop="timeSum" label="用时" width="90" align="center">
@ -100,7 +129,7 @@
<template v-if="item.accountId">
<td>{{ i + 1 }}</td>
<td>{{ item.userName }}</td>
<td>{{ item.schoolName }}</td>
<td>{{ item.realSchool }}</td>
<td>{{ item.timeSum }}min</td>
<td>{{ item.score }}</td>
<td>
@ -147,7 +176,7 @@
<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;"
style="margin-bottom: 10px;font-size: 14px;color: #062c87;text-decoration: underline;cursor: pointer;"
@click="showFaild">部分数据导入失败查看失败原因</p>
</template>
</div>
@ -178,10 +207,18 @@ export default {
id: +this.$route.query.id,
stageId: +this.$route.query.stageId,
index: +this.$route.query.index,
method: this.$route.query.method,
method: +this.$route.query.method,
competitionType: +this.$route.query.competitionType,
rule: +this.$route.query.rule,
searchTimer: null,
filter: {
provinceId: '',
cityId: '',
realSchoolId: '',
},
provinces: [],
cities: [],
schools: [],
keyword: this.$route.query.keyword || '',
teamCalculationMethods: [
{
@ -262,6 +299,8 @@ export default {
}
},
mounted () {
this.getProvince()
this.getSchool()
this.getStage()
},
methods: {
@ -275,6 +314,7 @@ export default {
},
//
getRank () {
const { filter } = this
this.loading = true
//
if (this.type) {
@ -284,7 +324,8 @@ export default {
competitionId: this.id,
isOverallRanking: this.active ? 0 : 1,
stageId: this.active || this.stageId,
keyword: this.keyword
keyword: this.keyword,
...filter
}).then(({ message, publishStatus }) => {
// isRelease 01
this.published = publishStatus
@ -307,7 +348,8 @@ export default {
publicationType: this.type,
locationStageId: this.stageId,
stageIds: ids.splice(0, ids.length - 1),
keyword: this.keyword
keyword: this.keyword,
...filter
}).then(({ page, publishStatus, total }) => {
this.published = publishStatus
this.list = page || []
@ -319,7 +361,7 @@ export default {
})
} 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.list = page
this.total = total
@ -367,6 +409,39 @@ export default {
this.active = i
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) {
this.teams = []
@ -449,7 +524,7 @@ export default {
},
//
toReport (row) {
this.$router.push(`/matchReport?reportId=${row.reportId}`)
this.$router.push(`/${this.method !== 1 ? 'trialReport' : 'theoryReport'}?reportId=${row.reportId}`)
},
handleSelectionChange (val) { //
this.multipleSelection = val;
@ -717,7 +792,7 @@ export default {
.score {
font-size: 16px;
font-weight: 600;
color: #9076ff;
color: #062c87;
}
}

@ -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>
</ul>
<div>
<el-button v-show="loaded && info.completeCompetitionSetup.competitionType" type="primary" round
:disabled="hasReport" :loading="allocating" @click="autoAllocationConfirm">{{ !notBeginSign && allocated ?
<template v-if="loaded && info.completeCompetitionSetup.competitionType">
<el-button type="primary" round :disabled="hasReport" :loading="allocating" @click="autoAllocationConfirm">{{
!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="add" v-auth="'/match:管理:报名人员:新增'">新增</el-button>
<el-button type="primary" round :loading="exporting" @click="exportAll"
@ -28,8 +41,8 @@
</div>
</div>
<el-table ref="table" :data="listData" class="table" stripe header-align="center"
@selection-change="handleSelectionChange" row-key="id" v-loading="loading" @sort-change="sortChange">
<el-table ref="table" :data="listData" class="table" header-align="center" @selection-change="handleSelectionChange"
row-key="id" v-loading="loading" @sort-change="sortChange">
<el-table-column type="selection" width="80" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="60" label="序号" align="center">
<template slot-scope="scope">
@ -44,7 +57,7 @@
<el-table-column prop="username" :label="info.completeCompetitionSetup.competitionType ? '队长/成员' : '学生姓名'"
min-width="140" align="center">
</el-table-column>
<el-table-column prop="workNumber" :label="info.completeCompetitionSetup.competitionType ? '队长/成员学号' : '学号'"
<el-table-column prop="account" :label="info.completeCompetitionSetup.competitionType ? '队长/成员账号' : '账号'"
min-width="140" align="center">
</el-table-column>
<el-table-column prop="phone" :label="info.completeCompetitionSetup.competitionType ? '队长/成员手机号' : '手机号'"
@ -69,11 +82,13 @@
</el-table-column>
<el-table-column label="操作" align="center" width="270">
<template slot-scope="scope">
<template v-if="!scope.row.isDel">
<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">
<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"
style="margin: 0 10px 0 5px" @change="switchOff($event, scope.row, scope.$index)"></el-switch>
</template>
@ -172,7 +187,7 @@
<template v-else>
<p style="margin: -10px 0 13px;font-size: 14px;color: #e90000;">{{ uploadTips }}</p>
<p type="primary"
style="margin-bottom: 10px;font-size: 14px;color: #9076FF;text-decoration: underline;cursor: pointer;"
style="margin-bottom: 10px;font-size: 14px;color: #062c87;text-decoration: underline;cursor: pointer;"
@click="showFaild">部分数据导入失败查看失败原因</p>
</template>
</div>

@ -1,70 +1,40 @@
<template>
<!-- 报名人员 -->
<div class="page-content"
style="padding: 24px">
<div class="tool"
style="justify-content: flex-end">
<el-button type="primary"
round
@click="add"
v-auth="'/match:管理:公告通知:新增'">新增</el-button>
<div class="page-content" style="padding: 24px">
<div class="tool" style="justify-content: flex-end">
<el-button type="primary" round @click="add" v-auth="'/match:管理:公告通知:新增'">新增</el-button>
</div>
<el-table ref="table"
:data="listData"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
<el-table ref="table" :data="listData" class="table" header-align="center" @selection-change="handleSelectionChange"
row-key="id">
<el-table-column type="index"
width="60"
label="序号"
align="center">
<el-table-column type="index" width="60" label="序号" align="center">
<template slot-scope="scope">
{{ scope.$index + (pageNo - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="announcementTitle"
label="标题名称">
<el-table-column prop="announcementTitle" label="标题名称">
</el-table-column>
<el-table-column prop="createTime"
label="创建时间">
<el-table-column prop="createTime" label="创建时间">
</el-table-column>
<el-table-column prop="updateTime"
label="发布时间">
<el-table-column prop="updateTime" label="发布时间">
</el-table-column>
<el-table-column prop="phone"
label="状态">
<el-table-column prop="phone" label="状态">
<template slot-scope="scope">
{{ scope.row.status ? '已发布' : '草稿' }}
</template>
</el-table-column>
<el-table-column label="操作"
align="center"
width="250">
<el-table-column label="操作" align="center" width="250">
<template slot-scope="scope">
<el-button type="text"
@click="edit(scope.row)"
v-auth="'/match:管理:公告通知:编辑'">编辑</el-button>
<el-button type="text"
@click="del(scope.row)"
v-auth="'/match:管理:公告通知:删除'">删除</el-button>
<el-switch v-auth="'/match:管理:公告通知:启用'"
v-model="scope.row.isOpen"
:active-text="scope.row.isOpen ? '关' : '开'"
:active-value="0"
:inactive-value="1"
style="margin: 0 10px 0 5px"
@change="switchOff($event,scope.row,scope.$index)"></el-switch>
<el-button type="text" @click="edit(scope.row)" v-auth="'/match:管理:公告通知:编辑'">编辑</el-button>
<el-button type="text" @click="del(scope.row)" v-auth="'/match:管理:公告通知:删除'">删除</el-button>
<el-switch v-auth="'/match:管理:公告通知:启用'" v-model="scope.row.isOpen" :active-text="scope.row.isOpen ? '' : ''"
:active-value="0" :inactive-value="1" style="margin: 0 10px 0 5px"
@change="switchOff($event, scope.row, scope.$index)"></el-switch>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background
layout="total, prev, pager, next"
:total="totals"
@current-change="handleCurrentChange"
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange"
:current-page="pageNo">
</el-pagination>
</div>
@ -162,5 +132,4 @@ export default {
};
</script>
<style scoped>
</style>
<style scoped></style>

@ -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" 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" 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: #062c87;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,426 @@
<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" :loading="exporting" @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 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 Setting from '@/setting'
import Util from '@/libs/util'
import Axios from 'axios'
export default {
data () {
return {
reportId: this.$route.query.reportId,
headers: {
token: sessionStorage.getItem('token')
},
title: "实验报告",
form: {
className: "",
instructor: "",
period: "",
projectName: "",
summarize: "",
},
infoData: {},
expData: [],
editing: false,
exporting: false,
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
},
async exportPage () {
this.exporting = true
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, '')
try {
const res = await Axios.post(this.api[this.project ? 'exportBankExperimentReport' : 'exportLabReport'], {
...form,
experimentalData: list
}, {
headers: this.headers,
responseType: 'blob'
})
const name = res.headers['content-disposition']
Util.downloadFileDirect(name ? decodeURI(name) : `实验报告.docx`, new Blob([res.data]))
} finally {
this.exporting = false
}
},
}
};
</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>

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save