Branch_d40a2540
yujialong 2 years ago
parent 186618506f
commit d5f8a827dd
  1. 13
      src/api/index.js
  2. BIN
      src/assets/img/ach1.png
  3. BIN
      src/assets/img/ach2.png
  4. BIN
      src/assets/img/match-bg1.png
  5. BIN
      src/assets/img/match-bg2.png
  6. 52
      src/pages/achievement/teach/index.vue
  7. 122
      src/pages/activity/add/index.vue
  8. 17
      src/pages/activity/list/index.vue
  9. 40
      src/pages/activity/manage/index.vue
  10. 26
      src/pages/activity/manage/matchProgress.vue
  11. 5
      src/pages/activity/manage/matchSignup.vue
  12. 23
      src/pages/activity/manage/notice.vue
  13. 17
      src/pages/activity/manage/noticeDetail.vue
  14. 808
      src/pages/activity/preview/index.vue
  15. 44
      src/pages/match/manage/index.vue
  16. 163
      src/pages/product/list/index.vue
  17. 261
      src/pages/product/show/index.vue
  18. 4
      src/pages/project/add/index.vue
  19. 4
      src/pages/screen/index.vue
  20. 2
      src/pages/station/list/index.vue
  21. 40
      src/pages/station/preview/index.vue
  22. 11
      src/router/modules/activity.js
  23. 4
      src/setting.js
  24. 10
      src/styles/common.scss

@ -343,6 +343,19 @@ export default {
disableActivityApplicant: `occupationlab/occupationlab/activity/applicant/disableRegistration`, disableActivityApplicant: `occupationlab/occupationlab/activity/applicant/disableRegistration`,
excelExportApplicant: `${host}occupationlab/occupationlab/activity/applicant/excelExport`, excelExportApplicant: `${host}occupationlab/occupationlab/activity/applicant/excelExport`,
exportDataInBatchesApplicant: `${host}occupationlab/occupationlab/activity/applicant/exportDataInBatches`, exportDataInBatchesApplicant: `${host}occupationlab/occupationlab/activity/applicant/exportDataInBatches`,
addActivityProgress: `occupationlab/occupationlab/activity/progress/addCompetitionProgress`,
delActivityProgress: `occupationlab/occupationlab/activity/progress/batchDeletion`,
findActivityProgress: `occupationlab/occupationlab/activity/progress/findById`,
listActivityProgress: `occupationlab/occupationlab/activity/progress/getCompetitionProgress`,
updateActivityProgress: `occupationlab/occupationlab/activity/progress/update`,
addActivityAnnouncement: `occupationlab/occupationlab/activity/announcement/addAnnouncement`,
updateActivityAnnouncement: `occupationlab/occupationlab/activity/announcement/amendmentAnnouncement`,
delActivityAnnouncement: `occupationlab/occupationlab/activity/announcement/deleteAnnouncement`,
disableActivityAnnouncement: `occupationlab/occupationlab/activity/announcement/disableAnnouncement`,
listActivityAnnouncement: `occupationlab/occupationlab/activity/announcement/queryAnnouncementByCompetitionId`,
findActivityAnnouncement: `occupationlab/occupationlab/activity/announcement/queryAnnouncementDetails`,
delActivityAnnouncementAnnex: `occupationlab/occupationlab/activity/announcement/annex/delete`,
saveActivityAnnouncementAnnex: `occupationlab/occupationlab/activity/announcement/annex/save`,
// 数据看板 // 数据看板
curriculumListForBeforeLogin: `nakadai/nakadai/curriculum/curriculumListForBeforeLogin`, curriculumListForBeforeLogin: `nakadai/nakadai/curriculum/curriculumListForBeforeLogin`,

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

@ -17,15 +17,15 @@
<p class="name">实验总人数</p> <p class="name">实验总人数</p>
<p class="val">{{ peopleNum }}</p> <p class="val">{{ peopleNum }}</p>
</div> </div>
<div class="item"> <div class="item item2">
<p class="name">实验平均分</p> <p class="name">实验平均分</p>
<p class="val">{{ avgScore }}</p> <p class="val">{{ avgScore }}</p>
</div> </div>
<div class="item"> <div class="item item3">
<p class="name">实验最高分</p> <p class="name">实验最高分</p>
<p class="val">{{ maxScore }}</p> <p class="val">{{ maxScore }}</p>
</div> </div>
<div class="item"> <div class="item item4">
<p class="name">实验最低分</p> <p class="name">实验最低分</p>
<p class="val">{{ minScore }}</p> <p class="val">{{ minScore }}</p>
</div> </div>
@ -331,16 +331,12 @@ export default {
dataZoom: [// dataZoom: [//
{ {
// xAxisIndex: 0,//X0 // xAxisIndex: 0,//X0
show: true,//使 show: true,
type: 'slider', // dataZoom slider dataZoom type: 'slider',
start: 0, // start: 0,
end: 50, // 6 end: 150,
xAxisIndex: [0], xAxisIndex: [0],
bottom: -10, bottom: -10,
// handleStyle: {
// borderWidth: 0
// }
} }
], ],
xAxis: [{ xAxis: [{
@ -439,7 +435,6 @@ export default {
} }
.stat { .stat {
display: flex; display: flex;
.nums { .nums {
display: flex; display: flex;
align-items: center; align-items: center;
@ -447,48 +442,45 @@ export default {
width: 640px; width: 640px;
margin-right: 20px; margin-right: 20px;
.item:nth-child(odd) {
background-image: url('../../../assets/img/total.png');
}
.item:nth-child(even) {
background-image: url('../../../assets/img/avg.png');
}
.item { .item {
width: 300px; width: 300px;
padding: 30px 30px; padding: 30px 30px;
margin: 0 10px; margin: 0 10px;
box-sizing: border-box; box-sizing: border-box;
border-radius: 8px; border-radius: 8px;
background-size: 100% 100%; background: url('../../../assets/img/total.png') 0 0/100% 100% no-repeat;
background-repeat: no-repeat;
p { p {
font-size: 18px; font-size: 18px;
color: #ffffff; color: #ffffff;
} }
.val { .val {
margin-top: 10px; margin-top: 10px;
color: #ffffff; color: #ffffff;
font-size: 36px; font-size: 36px;
} }
} }
.item:nth-child(2) {
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');
}
} }
.chart { .chart {
flex: 1; width: calc(100% - 660px);
} }
} }
.wrong { .wrong {
// padding-left: 25%;
.line { .line {
display: flex; display: flex;
justify-content: center; // justify-content: center;
margin-bottom: 10px; width: 920px;
margin: 0 auto 10px;
.jud-name { .jud-name {
width: 400px; width: 500px;
margin-right: 100px; margin-right: 100px;
} }
} }

@ -13,9 +13,13 @@
class="avatar-uploader" class="avatar-uploader"
accept=".jpg,.png,.jpeg,.gif" accept=".jpg,.png,.jpeg,.gif"
:on-success="uploadSuccess" :on-success="uploadSuccess"
:limit="1"
:action="this.api.fileupload" :action="this.api.fileupload"
:headers="headers" :headers="headers"
:limit="1"
:on-exceed="handleExceed"
:before-remove="beforeRemove"
:on-remove="handleRemove"
:on-error="uploadError"
name="file" name="file"
> >
<img v-if="form.coverUrl" :src="form.coverUrl" class="avatar"> <img v-if="form.coverUrl" :src="form.coverUrl" class="avatar">
@ -33,9 +37,13 @@
class="avatar-uploader avatar-uploader-lg" class="avatar-uploader avatar-uploader-lg"
accept=".jpg,.png,.jpeg,.gif" accept=".jpg,.png,.jpeg,.gif"
:on-success="uploadLgSuccess" :on-success="uploadLgSuccess"
:limit="1"
:action="this.api.fileupload" :action="this.api.fileupload"
:headers="headers" :headers="headers"
:limit="1"
:on-exceed="handleExceed"
:before-remove="beforeRemove"
:on-remove="handleCarouselRemove"
:on-error="uploadError"
name="file" name="file"
> >
<img v-if="form.carouselUrl" :src="form.carouselUrl" class="avatar-lg"> <img v-if="form.carouselUrl" :src="form.carouselUrl" class="avatar-lg">
@ -98,12 +106,15 @@
</el-form-item> </el-form-item>
<el-form-item label="附件"> <el-form-item label="附件">
<el-upload <el-upload
:on-remove="handleAnnexRemove"
:on-error="uploadError"
:before-upload="beforeUpload" :before-upload="beforeUpload"
:on-success="uploadAnnexSuccess" :on-success="uploadAnnexSuccess"
:on-exceed="handleExceedAnnex"
:limit="5" :limit="5"
:action="this.api.fileupload" :action="this.api.fileupload"
:headers="headers" :headers="headers"
:file-list="fileList" :file-list="form.activityFileList"
name="file" name="file"
> >
<el-button size="small" type="primary">点击上传</el-button> <el-button size="small" type="primary">点击上传</el-button>
@ -117,7 +128,7 @@
<div class="btns"> <div class="btns">
<el-button @click="save(0)">保存</el-button> <el-button @click="save(0)">保存</el-button>
<el-button type="primary" @click="save(1)">发布</el-button> <el-button type="primary" @click="save(1)">发布</el-button>
<el-button type="danger" @click="preview" v-auth="'/activity/list:管理:大赛详情:预览'">预览</el-button> <el-button type="danger" @click="preview">预览</el-button>
<el-button @click="back">取消</el-button> <el-button @click="back">取消</el-button>
</div> </div>
</div> </div>
@ -147,6 +158,7 @@ export default {
activityFileList: [], // activityFileList: [], //
initiator: '', initiator: '',
isNeedCode: 0, isNeedCode: 0,
invitationCode: '',
maximumNumber: 0, maximumNumber: 0,
signUpStartTime: '', signUpStartTime: '',
signUpEndTime: '', signUpEndTime: '',
@ -167,6 +179,7 @@ export default {
sponsorList: [""], sponsorList: [""],
fileList: [], fileList: [],
submiting: false, submiting: false,
pass: false,
updateTime: 0, updateTime: 0,
}; };
}, },
@ -202,6 +215,27 @@ export default {
} }
} }
}, },
//
beforeRouteLeave(to, from, next) {
if (this.submiting) {
next()
} else if (!this.pass) {
//
if (this.updateTime) {
this.$confirm(`所填写内容暂未保存,是否保存?`, '提示', {
type: 'warning'
}).then(() => {
this.save(this.form.publishStatus)
}).catch(() => {
next()
})
} else {
next()
}
} else {
next()
}
},
mounted() { mounted() {
this.getData() this.getData()
}, },
@ -215,24 +249,38 @@ export default {
// //
const fileList = data.activityFileList const fileList = data.activityFileList
if (fileList) { if (fileList) {
const files = []
fileList.map(e => { fileList.map(e => {
files.push({ e.name = e.fileName
name: e.fileName, e.url = e.filePath
url: e.filePath
})
}) })
this.fileList = files
} else { } else {
data.activityFileList = [] data.activityFileList = []
} }
this.form = data this.form = data
this.$nextTick(() => { this.$nextTick(() => {
this.updateTime = 0 this.updateTime = 0
}) })
}).catch(err => {}) }).catch(err => {})
}, },
handleExceed(files, fileList) {
util.warningMsg(`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`);
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}`);
},
handleRemove(file, fileList) {
this.form.coverUrl = ''
},
handleCarouselRemove(file, fileList) {
this.form.carouselUrl = ''
},
uploadError(err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
})
},
uploadSuccess(res) { uploadSuccess(res) {
this.form.coverUrl = res.data.filesResult.fileUrl this.form.coverUrl = res.data.filesResult.fileUrl
}, },
@ -242,14 +290,19 @@ export default {
// //
uploadAnnexSuccess(res) { uploadAnnexSuccess(res) {
const file = res.data.filesResult const file = res.data.filesResult
const { id } = this.form const url = file.fileUrl || file.fileId
const data = { const data = {
activityId: id || '', activityId: this.form.id || '',
fileName: this.fileName, fileName: this.fileName,
filePath: file.fileUrl || file.fileId name: this.fileName,
filePath: url,
url
} }
this.form.activityFileList.push(data) this.form.activityFileList.push(data)
}, },
handleExceedAnnex(files, fileList) {
util.warningMsg(`当前限制选择 5 个文件,如需更换,请删除一个文件再重新选择!`);
},
// //
beforeUpload(file) { beforeUpload(file) {
const isLt2M = file.size / 1024 / 1024 < 10 const isLt2M = file.size / 1024 / 1024 < 10
@ -262,7 +315,7 @@ export default {
} }
}, },
handleAnnexRemove(file, fileList) { handleAnnexRemove(file, fileList) {
this.form.activityFileList = fileList
}, },
// //
randomInv() { randomInv() {
@ -270,7 +323,7 @@ export default {
for (let i = 0; i < 4; i++) { for (let i = 0; i < 4; i++) {
result += Math.floor(Math.random() * 10); result += Math.floor(Math.random() * 10);
} }
this.form.completeCompetitionSetup.invitationCode = result this.form.invitationCode = result
}, },
// //
save(status) { save(status) {
@ -293,24 +346,28 @@ export default {
} }
form.publishStatus = status form.publishStatus = status
form.id = this.$route.query.id form.id = this.$route.query.id
if (this.submiting) return false
this.submiting = true
if (form.id) { if (form.id) {
this.$post(this.api.updateActivity, form).then(res => { this.$post(this.api.updateActivity, form).then(res => {
this.updateTime = 0 this.backList()
this.$router.back()
util.successMsg("修改成功"); util.successMsg("修改成功");
}).catch(err => {}); }).catch(err => {
this.submiting = false
});
} else { } else {
this.$post(this.api.saveActivity, form).then(res => { this.$post(this.api.saveActivity, form).then(res => {
this.updateTime = 0 this.backList()
this.$router.back()
util.successMsg("创建成功"); util.successMsg("创建成功");
}).catch(err => {}); }).catch(err => {
this.submiting = false
});
} }
}, },
// //
preview() { preview() {
util.local.set('activity', this.form) util.local.set('activity', this.form)
window.open(this.$router.resolve('/matchPreview').href) window.open(this.$router.resolve('preview').href)
}, },
addSponsor() { addSponsor() {
this.sponsorList.push(""); this.sponsorList.push("");
@ -318,25 +375,26 @@ export default {
delSponsor(index) { delSponsor(index) {
this.sponsorList.splice(index, 1); this.sponsorList.splice(index, 1);
}, },
backList() {
this.pass = true
this.updateTime = 0
this.$router.push(`/activity?page=${this.$store.state.activity.page}`)
},
back() { back() {
this.pass = true
// //
const { updateTime } = this.$refs['step' + this.step] if (this.updateTime) {
console.log("🚀 ~ file: index.vue:142 ~ back ~ updateTime", updateTime)
if (this.step < 4 && updateTime) {
this.$confirm(`编辑的内容未保存,是否保存?`, '提示', { this.$confirm(`编辑的内容未保存,是否保存?`, '提示', {
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
this.save(0) this.save(this.form.publishStatus)
}).catch(() => { }).catch(() => {
this.backPage() this.backList()
}) })
} else { } else {
this.backPage() this.backList()
} }
}, },
backPage() {
this.$router.push(`/activity?page=${this.$store.state.activity.page}`)
}
} }
}; };
</script> </script>

@ -257,15 +257,18 @@ export default {
// redis // redis
getRedis() { getRedis() {
this.$post(this.api.getRedisCacheActivity).then(({ data }) => { this.$post(this.api.getRedisCacheActivity).then(({ data }) => {
data && this.getList() if (data) {
localStorage.getItem('activityTimestamp') !== data && this.getList() // redis
localStorage.setItem('activityTimestamp', data)
}
}).catch(res => {}) }).catch(res => {})
}, },
getData() { getData() {
this.getList() this.getList()
if (!Setting.isDev) { // if (!Setting.isDev) {
clearInterval(this.redisTimer) clearInterval(this.redisTimer)
this.redisTimer = setInterval(this.getRedis, 1000) this.redisTimer = setInterval(this.getRedis, 1000)
} // }
}, },
add() { add() {
this.$router.push("/activity/add"); this.$router.push("/activity/add");
@ -278,7 +281,7 @@ export default {
type: "warning" type: "warning"
}) })
.then(() => { .then(() => {
this.$post(`${this.api.batchDeletionActivity}?ids=${row.id}`).then(res => { this.$post(this.api.batchDeletionActivity, [row.id]).then(res => {
util.successMsg("删除成功"); util.successMsg("删除成功");
this.getData(); this.getData();
}).catch(res => { }).catch(res => {
@ -296,8 +299,8 @@ export default {
this.$confirm("确定要删除吗?", "提示", { this.$confirm("确定要删除吗?", "提示", {
type: "warning" type: "warning"
}).then(() => { }).then(() => {
let ids = this.multipleSelection.map(i => 'ids=' + i.id); let ids = this.multipleSelection.map(e => e.id);
this.$post(`${this.api.batchDeletionActivity}?${ids.join('&')}`).then(res => { this.$post(this.api.batchDeletionActivity, this.multipleSelection.map(e => e.id)).then(res => {
this.getData(); this.getData();
this.$message.success("删除成功"); this.$message.success("删除成功");
this.$refs.table.clearSelection() this.$refs.table.clearSelection()
@ -306,7 +309,7 @@ export default {
}).catch(() => { }).catch(() => {
}); });
} else { } else {
this.$message.warning("请先选择赛事 !"); this.$message.warning("请先选择项目 !");
} }
}, },
handleCurrentChange(val) { handleCurrentChange(val) {

@ -27,7 +27,6 @@ import notice from "./notice";
import MatchSignup from "./matchSignup"; import MatchSignup from "./matchSignup";
import { mapState } from "vuex"; import { mapState } from "vuex";
export default { export default {
name: "matchManage",
data() { data() {
return { return {
name: this.$route.query.name, name: this.$route.query.name,
@ -54,29 +53,24 @@ export default {
'btns' 'btns'
]) ])
}, },
beforeRouteLeave(to, from, next) {
const detail = this.$refs.detail
if (detail && detail.updateTime) {
this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示.......', {
type: 'warning'
}).then(() => {
detail.save(detail.form.publishStatus)
}).catch(() => {
next()
})
} else {
next()
}
},
mounted() { mounted() {
Setting.dynamicRoute && this.initTabs()
}, },
methods: { methods: {
initTabs() {
const { btns } = this
const tab1 = btns.includes('/activity/list:管理:大赛详情')
const tab3 = btns.includes('/activity/list:管理:竞赛进展')
const tab4 = btns.includes('/activity/list:管理:公告通知')
const tab5 = btns.includes('/activity/list:管理:报名人员')
tab1 || this.$delete(this.tabs, 'tab1')
tab3 || this.$delete(this.tabs, 'tab3')
tab4 || this.$delete(this.tabs, 'tab4')
tab5 || this.$delete(this.tabs, 'tab5')
const type = this.$route.query.tab
const keys = Object.keys(this.tabs)
this.active = keys.includes(type) ? type : keys[0]
},
//
hideArch() {
this.$delete(this.tabs, 'tab2')
},
back() { back() {
this.handleSave(0) && this.backPage() this.handleSave(0) && this.backPage()
}, },
@ -85,11 +79,11 @@ export default {
// //
if (this.active === 'tab1') { if (this.active === 'tab1') {
const detail = this.$refs.detail const detail = this.$refs.detail
if (detail.step < 4 && detail.$refs['step' + detail.step].updateTime) { if (detail && detail.updateTime) {
this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示', { this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示', {
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
detail.save(1, 1) detail.save(detail.form.publishStatus)
this.backOrTab(i) this.backOrTab(i)
}).catch(() => { }).catch(() => {
this.backOrTab(i) this.backOrTab(i)

@ -26,13 +26,13 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" width="170"> <el-table-column label="操作" align="center" width="170">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-if="!scope.row.operate" type="text" @click="operateIt(scope.row)" v-auth="'/activity:管理:竞赛进展:编辑'">编辑</el-button> <el-button v-if="!scope.row.operate" type="text" @click="operateIt(scope.row)">编辑</el-button>
<el-button v-else type="text" @click="saveData(scope.row)">保存</el-button> <el-button v-else type="text" @click="saveData(scope.row)">保存</el-button>
<el-button type="text" @click="handleDelete(scope.row, scope.$index)" v-auth="'/activity/list:管理:竞赛进展:删除'">删除</el-button> <el-button type="text" @click="handleDelete(scope.row, scope.$index)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="plus" @click="addData" v-auth="'/activity/list:管理:竞赛进展:新增'"> <div class="plus" @click="addData">
<i class="el-icon-circle-plus-outline"></i> <i class="el-icon-circle-plus-outline"></i>
</div> </div>
</div> </div>
@ -77,10 +77,10 @@ export default {
row.operate = true row.operate = true
}, },
getData() { getData() {
this.$get(this.api.getCompetitionProgress, { this.$get(this.api.listActivityProgress, {
competitionId: this.id activityId: this.id
}).then(res => { }).then(res => {
this.listData = res.competitionProgressList; this.listData = res.activityProgressList;
for(let index=0; index<this.listData.length; index++) { for(let index=0; index<this.listData.length; index++) {
// //
this.$set(this.listData, index, { operate: false, ...this.listData[index]}) this.$set(this.listData, index, { operate: false, ...this.listData[index]})
@ -93,14 +93,14 @@ export default {
let data = row; let data = row;
if (data.title.length) { if (data.title.length) {
if (row.id) { if (row.id) {
this.$put(this.api.editCompetitionProgress, data).then(res => { this.$post(this.api.updateActivityProgress, data).then(res => {
this.touchTime = this.touchTime-1 this.touchTime = this.touchTime-1
util.successMsg("修改成功"); util.successMsg("修改成功");
this.getData(); this.getData();
}).catch(res => { }).catch(res => {
}); });
} else { } else {
this.$post(this.api.addCompetitionProgress, data).then(res => { this.$post(this.api.addActivityProgress, data).then(res => {
this.touchTime = this.touchTime-1 this.touchTime = this.touchTime-1
util.successMsg("创建成功"); util.successMsg("创建成功");
this.getData(); this.getData();
@ -114,10 +114,6 @@ export default {
handleSelectionChange(val) { handleSelectionChange(val) {
this.multipleSelection = val; this.multipleSelection = val;
}, },
onSearch() {
this.pageNo = 1;
this.getData();
},
handleCurrentChange(val) { handleCurrentChange(val) {
this.pageNo = val; this.pageNo = val;
this.getData(); this.getData();
@ -131,7 +127,7 @@ export default {
util.successMsg("删除成功"); util.successMsg("删除成功");
}else { }else {
this.touchTime = this.touchTime+1 this.touchTime = this.touchTime+1
this.$del(`${this.api.deleteCompetitionProgress}?competitionProgressId=${row.id}`).then(res => { this.$post(this.api.delActivityProgress, [row.id]).then(res => {
util.successMsg("删除成功"); util.successMsg("删除成功");
this.getData(); this.getData();
}).catch(res => { }).catch(res => {
@ -147,7 +143,7 @@ export default {
if (this.listData.length) { if (this.listData.length) {
if (this.listData[this.listData.length - 1].id) { if (this.listData[this.listData.length - 1].id) {
this.listData.push({ this.listData.push({
competitionId: this.id, activityId: this.id,
id: "", id: "",
title: "", title: "",
description: "", description: "",
@ -160,7 +156,7 @@ export default {
} }
} else { } else {
this.listData.push({ this.listData.push({
competitionId: this.id, activityId: this.id,
id: "", id: "",
title: "", title: "",
description: "", description: "",

@ -8,14 +8,14 @@
<el-input placeholder="请输入姓名/手机号/学号" prefix-icon="el-icon-search" v-model="keyword" clearable size="mini" style="width: 250px"></el-input> <el-input placeholder="请输入姓名/手机号/学号" prefix-icon="el-icon-search" v-model="keyword" clearable size="mini" style="width: 250px"></el-input>
</li> </li>
<li> <li>
<label>参赛人员状态</label> <label>报名人员状态</label>
<el-select v-model="isDisable" @change="initData"> <el-select v-model="isDisable" @change="initData">
<el-option v-for="(item, i) in statusList" :key="i" :label="item.name" :value="item.id"></el-option> <el-option v-for="(item, i) in statusList" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select> </el-select>
</li> </li>
</ul> </ul>
<div> <div>
<el-button type="primary" round @click="exportAll" v-auth="'/activity/list:管理:报名人员:批量导出'">批量导出</el-button> <el-button type="primary" round @click="exportAll">批量导出</el-button>
</div> </div>
</div> </div>
@ -37,7 +37,6 @@
<el-table-column label="操作" align="center" width="320"> <el-table-column label="操作" align="center" width="320">
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch <el-switch
v-auth="'/activity/list:管理:报名人员:禁用'"
v-model="scope.row.isDisable" v-model="scope.row.isDisable"
:active-text="scope.row.isDisable ? '关' : '开'" :active-text="scope.row.isDisable ? '关' : '开'"
:active-value="0" :active-value="0"

@ -2,7 +2,7 @@
<!-- 报名人员 --> <!-- 报名人员 -->
<div class="page-content" style="padding: 24px"> <div class="page-content" style="padding: 24px">
<div class="tool" style="justify-content: flex-end"> <div class="tool" style="justify-content: flex-end">
<el-button type="primary" round @click="add" v-auth="'/activity/list:管理:公告通知:新增'">新增</el-button> <el-button type="primary" round @click="add">新增</el-button>
</div> </div>
<el-table ref="table" :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> <el-table ref="table" :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id">
@ -24,10 +24,9 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" width="250"> <el-table-column label="操作" align="center" width="250">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" @click="edit(scope.row)" v-auth="'/activity/list:管理:公告通知:编辑'">编辑</el-button> <el-button type="text" @click="edit(scope.row)">编辑</el-button>
<el-button type="text" @click="del(scope.row)" v-auth="'/activity/list:管理:公告通知:删除'">删除</el-button> <el-button type="text" @click="del(scope.row)">删除</el-button>
<el-switch <el-switch
v-auth="'/activity/list:管理:公告通知:启用'"
v-model="scope.row.isOpen" v-model="scope.row.isOpen"
:active-text="scope.row.isOpen ? '关' : '开'" :active-text="scope.row.isOpen ? '关' : '开'"
:active-value="0" :active-value="0"
@ -76,7 +75,7 @@ export default {
}, },
methods: { methods: {
getData() { getData() {
this.$post(`${this.api.queryAnnouncementByCompetitionId}?pageNum=${this.pageNo}&pageSize=${this.pageSize}&competitionId=${this.id}`).then(({ data }) => { this.$post(`${this.api.listActivityAnnouncement}?pageNum=${this.pageNo}&pageSize=${this.pageSize}&competitionId=${this.id}`).then(({ data }) => {
this.listData = data.records this.listData = data.records
this.totals = data.total this.totals = data.total
this.$refs.table.clearSelection() this.$refs.table.clearSelection()
@ -94,7 +93,7 @@ export default {
type: "warning" type: "warning"
}) })
.then(() => { .then(() => {
this.$post(`${this.api.deleteAnnouncement}?id=${row.id}`).then(res => { this.$post(`${this.api.delActivityAnnouncement}?id=${row.id}`).then(res => {
util.successMsg("删除成功"); util.successMsg("删除成功");
this.getData(); this.getData();
}).catch(res => { }).catch(res => {
@ -105,13 +104,13 @@ export default {
}, },
switchOff(val, row, index) { switchOff(val, row, index) {
if (val) { if (val) {
this.$put(`${this.api.disableAnnouncement}?id=${row.id}&isDisable=${val}`).then(res => {}).catch(err => {}) this.$put(`${this.api.disableActivityAnnouncement}?id=${row.id}&isDisable=${val}`).then(res => {}).catch(err => {})
} else if (!row.status) { } else if (!row.status) {
this.$confirm('是否发布该公告?', '提示', { this.$confirm('是否发布该公告?', '提示', {
type: 'success' type: 'success'
}).then(() => { }).then(() => {
this.$put(`${this.api.disableAnnouncement}?id=${row.id}&isDisable=${val}`).then(res => { this.$put(`${this.api.disableActivityAnnouncement}?id=${row.id}&isDisable=${val}`).then(res => {
this.$post(this.api.amendmentAnnouncement, { this.$post(this.api.updateActivityAnnouncement, {
id: row.id, id: row.id,
status: 1 status: 1
}).then(res => { }).then(res => {
@ -122,14 +121,14 @@ export default {
row.isOpen = 1 row.isOpen = 1
}) })
} else { } else {
this.$put(`${this.api.disableAnnouncement}?id=${row.id}&isDisable=${val}`).then(res => {}).catch(err => {}) this.$put(`${this.api.disableActivityAnnouncement}?id=${row.id}&isDisable=${val}`).then(res => {}).catch(err => {})
} }
}, },
add() { add() {
this.$router.push(`noticeDetail?competitionId=${this.id}`) this.$router.push(`noticeDetail?activityId=${this.id}`)
}, },
edit(row) { edit(row) {
this.$router.push(`noticeDetail?id=${row.id}&competitionId=${this.id}`) this.$router.push(`noticeDetail?id=${row.id}&activityId=${this.id}`)
} }
} }
}; };

@ -38,8 +38,8 @@
</el-upload> </el-upload>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button v-if="!form.id" @click="save(0)" v-auth="'/activity/list:管理:公告通知:草稿'">草稿</el-button> <el-button v-if="!form.id" @click="save(0)">草稿</el-button>
<el-button type="primary" @click="save(1)" v-auth="'/activity/list:管理:公告通知:发布'">发布</el-button> <el-button type="primary" @click="save(1)">发布</el-button>
<el-button @click="back">取消</el-button> <el-button @click="back">取消</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -61,7 +61,7 @@ export default {
}, },
form: { form: {
id: this.$route.query.id, id: this.$route.query.id,
competitionId: this.$route.query.competitionId, activityId: this.$route.query.activityId,
announcementText: '', announcementText: '',
announcementTitle: '', announcementTitle: '',
announcementAnnexList: [], announcementAnnexList: [],
@ -80,7 +80,6 @@ export default {
form: { form: {
handler(){ handler(){
this.updateTime++ this.updateTime++
if(this.updateTime > 1) this.$store.commit('activity/setWait', 0)
}, },
deep:true deep:true
}, },
@ -90,7 +89,7 @@ export default {
}, },
methods: { methods: {
getData() { getData() {
this.$post(`${this.api.queryAnnouncementDetails}?id=${this.form.id}`).then(({ data }) => { this.$post(`${this.api.findActivityAnnouncement}?id=${this.form.id}`).then(({ data }) => {
this.form = data this.form = data
// //
const fileList = data.announcementAnnexList const fileList = data.announcementAnnexList
@ -117,13 +116,13 @@ export default {
if (form.id) { if (form.id) {
form.isOpen = 0 form.isOpen = 0
delete form.announcementAnnexList delete form.announcementAnnexList
this.$post(this.api.amendmentAnnouncement, form).then(res => { this.$post(this.api.updateActivityAnnouncement, form).then(res => {
util.successMsg("修改成功") util.successMsg("修改成功")
this.$router.back() this.$router.back()
}).catch(err => {}) }).catch(err => {})
} else { } else {
form.isOpen = status ? 0 : 1 form.isOpen = status ? 0 : 1
this.$post(this.api.addAnnouncement, form).then(res => { this.$post(this.api.addActivityAnnouncement, form).then(res => {
util.successMsg("创建成功") util.successMsg("创建成功")
this.$router.back() this.$router.back()
}).catch(err => {}) }).catch(err => {})
@ -143,7 +142,7 @@ export default {
} }
this.form.announcementAnnexList.push(data) this.form.announcementAnnexList.push(data)
// //
id && this.$post(this.api.saveAnnouncementAnnex, data).then(res => {}).catch(res => {}) id && this.$post(this.api.saveActivityAnnouncementAnnex, data).then(res => {}).catch(res => {})
}, },
// //
beforeUpload(file) { beforeUpload(file) {
@ -163,7 +162,7 @@ export default {
if (file.url) { if (file.url) {
this.$del(`${this.api.fileDeletion}?keys=${file.url}`).then(res => {}).catch(res => {}) this.$del(`${this.api.fileDeletion}?keys=${file.url}`).then(res => {}).catch(res => {})
const id = this.form.announcementAnnexList.find(e => e.fileName === file.name).id const id = this.form.announcementAnnexList.find(e => e.fileName === file.name).id
this.$post(`${this.api.delAnnex}?id=${id}`).then(res => {}).catch(res => {}) this.$post(`${this.api.delActivityAnnouncementAnnex}?id=${id}`).then(res => {}).catch(res => {})
} }
}, },
back() { back() {

@ -1,465 +1,436 @@
<template> <template>
<div class="activity"> <div class="wrap index">
<div class="banner" :style="{backgroundImage: 'url(' + (form.carouselUrl || 'https://huoran.oss-cn-shenzhen.aliyuncs.com/20220613/png/1536269450851409920.png') + ')'}"></div> <div class="banner" :style="{backgroundImage: 'url(' + (form.carouselUrl || 'https://huoran.oss-cn-shenzhen.aliyuncs.com/20220613/png/1536269450851409920.png') + ')'}"></div>
<div class="center"> <div class="center-con">
<breadcrumb ref="breadcrumb" :data="'全部赛事/' + form.name" route="matchPreview"></breadcrumb> <div class="center-wrap">
<div class="activity-inner"> <breadcrumb ref="breadcrumb" :data="'全部项目/' + form.projectName"></breadcrumb>
<div class="flex-between"> <div class="content">
<el-tabs v-model="curType" @tab-click="typeChange"> <div class="tool flex-between">
<el-tab-pane v-for="(item, index) in typeList" :key="index" :label="item.name" :name="item.id"></el-tab-pane> <el-tabs v-model="curType" @tab-click="typeChange">
</el-tabs> <el-tab-pane v-for="(item, index) in typeList" :key="index" :label="item.name" :name="item.id"></el-tab-pane>
<div class="status wait">等待报名</div> </el-tabs>
</div> <div class="status wait">等待报名</div>
<div class="info">
<h6 class="title">{{ form.name }}</h6>
<div class="meta">最近编辑时间{{ form.updateTime }}</div>
</div>
<div class="l-title" id="part1"><img src="@/assets/img/label.png" alt=""> 竞赛信息</div>
<div v-if="form.description" class="texts ql-editor" v-html="form.description"></div>
<template v-if="form.competitionAnnexList && form.competitionAnnexList.length">
<h6 class="p-title">附件下载</h6>
<ul class="files">
<li v-for="(item, i) in form.competitionAnnexList" :key="i">
<el-link v-if="item.canPreview" class="m-r-10" type="primary" @click="previewFile(item)">{{ item.fileName }}</el-link>
<span v-else class="file-name">{{ item.fileName }}</span>
<el-link type="primary" :underline="false" @click="download(item)">下载</el-link>
</li>
</ul>
</template>
<template v-if="!form.description && (!form.competitionAnnexList || !form.competitionAnnexList.length )">
<div class="empty">
<div>
<img src="@/assets/img/none.png" alt="">
<p>暂无数据</p>
</div> </div>
</div> <div class="info">
</template> <h6 class="title">{{ form.projectName }}</h6>
<div class="meta">最近编辑时间{{ form.updateTime }}</div>
<template v-if="form.releaseType && form.competitionStage.length">
<div class="l-title"><img src="@/assets/img/label.png" alt=""> 赛程规则与内容</div>
<h6 class="rule-title">{{ form.competitionStage.length }}个竞赛阶段同一个团队每个成员只能参加一个阶段赛项</h6>
<div v-for="(rule, i) in form.competitionStage" :key="i" class="rule">
<p style="font-size: 16px;color: #333;">{{ rule.stageName }}</p>
<p>比赛时间{{ rule.startTime && rule.startTime + ' ~ ' + rule.endTime }}</p>
<p>比赛方式{{ methods.find(e => e.id == rule.method) && methods.find(e => e.id == rule.method).name }}</p>
<p v-if="!rule.method">课程系统{{ rule.systemName }}</p>
<p v-if="rule.onlineButton">线上地点{{ rule.onlineAddress }}</p>
<p v-if="rule.offlineButton">线下地点{{ rule.offlineAddress }}</p>
<template v-if="rule.method === 2">
<p>线下地点{{ rule.offlineAddress }}</p>
<p>比赛内容{{ rule.contentDescription }}</p>
<p>评分规则{{ rule.scoreRule }}</p>
</template>
<template v-if="form.completeCompetitionSetup.competitionType">
<p>团队参赛人数限制{{ rule.teamNumLimit || '不限制' }}</p>
<p>团队成绩计算方式{{ teamCalculationMethods.find(e => e.id == rule.teamCalculationMethod) && teamCalculationMethods.find(e => e.id == rule.teamCalculationMethod).name }}</p>
</template>
<p>阶段比赛结束后{{ rule.resultAnnouncementTime }}小时公布阶段比赛成绩</p>
<div v-if="form.rule === 1" class="flex">
<p>晋级规则</p>
<div>
<p v-if="rule.peopleLimit">本阶段成绩排名前{{ rule.peopleLimit }}可晋级下一阶段比赛</p>
<p v-if="rule.percentageLimit">本阶段成绩排名前{{ rule.percentageLimit }}%可晋级下一阶段比赛</p>
<p v-if="rule.scoreLimit">本阶段成绩{{ rule.scoreLimit }}可晋级下一阶段比赛</p>
</div>
</div>
</div>
</template>
<!-- 进展 -->
<div class="l-title" id="part2"><img src="@/assets/img/label.png" alt=""> 竞赛进展</div>
<ul class="progress" v-if="progress.length">
<li v-for="(item,index) in progress" :key="index" :class="item.status == 0 ? 'not' : (item.status == 1 ? 'ing' : 'done')">
<i class="dot"></i>
<p class="name">{{item.title}}</p>
<p class="desc">{{item.description}}</p>
</li>
<img class="rocket" src="@/assets/img/rocket.png" alt="">
</ul>
<template v-else>
<div class="empty">
<div>
<img src="@/assets/img/none.png" alt="">
<p>暂无数据</p>
</div> </div>
</div>
</template> <div v-show="curType < 4">
<div class="l-title" id="part1"><img src="@/assets/img/label.png" alt=""> 项目信息</div>
<!-- 公告 --> <div v-if="form.projectDescribe" class="texts ql-editor" v-html="form.projectDescribe"></div>
<div class="l-title" id="part3"><img src="@/assets/img/label.png" alt=""> 通知公告</div> <template v-if="form.activityFileList">
<ul class="notice-list" v-if="notices.length"> <h6 class="p-title">附件下载</h6>
<li v-for="(item, i) in notices" :key="i" @click="toNotice(item)"> <ul class="files">
<h6>{{ item.announcementTitle }}</h6> <li v-for="(item, i) in form.activityFileList" :key="i">
<p class="meta">{{ item.updateTime }}</p> <el-link v-if="item.canPreview" class="m-r-10" type="primary" @click="preview(item)">{{ item.fileName }}</el-link>
<div class="des" v-html="item.announcementText"></div> <span v-else class="fileName">{{ item.fileName }}</span>
</li> <el-link type="primary" :underline="false" @click="download(item)">下载</el-link>
</ul> </li>
<template v-else> </ul>
<div class="empty"> </template>
<div>
<img src="@/assets/img/none.png" alt=""> <!-- 进展 -->
<p>暂无通知公告</p> <div class="l-title" id="part2"><img src="@/assets/img/label.png" alt=""> 项目进展</div>
<ul class="progress" v-if="progress.length">
<li v-for="(item,index) in progress" :key="index" :class="item.status == 0 ? 'not' : (item.status == 1 ? 'ing' : 'done')">
<i class="dot"></i>
<p class="name">{{item.title}}</p>
<p class="desc">{{item.description}}</p>
</li>
<img class="rocket" src="@/assets/img/rocket.png" alt="">
</ul>
<template v-else>
<div class="empty">
<div>
<img src="@/assets/img/none.png" alt="">
<p>暂无数据</p>
</div>
</div>
</template>
<!-- 公告 -->
<div class="l-title" id="part3"><img src="@/assets/img/label.png" alt=""> 通知公告</div>
<ul class="notice-list" v-if="notices.length">
<li v-for="(item, i) in notices" :key="i" @click="toNotice(item)">
<h6>{{ item.announcementTitle }}</h6>
<p class="meta">{{ item.updateTime }}</p>
<div class="des" v-html="item.announcementText"></div>
</li>
</ul>
<template v-else>
<div class="empty">
<div>
<img src="@/assets/img/none.png" alt="">
<p>暂无通知公告</p>
</div>
</div>
</template>
</div> </div>
</div> </div>
</template> </div>
</div> </div>
</div>
</div> </div>
</template> </template>
<script> <script>
import util from "@/libs/util";
import breadcrumb from '@/components/breadcrumb' import breadcrumb from '@/components/breadcrumb'
import Const from '@/const/activity' import util from '@/libs/util'
import Setting from "@/setting"
export default { export default {
data() { data() {
return { return {
rules: Const.rules, form: util.local.get('activity'),
methods: Const.methods, curType: '1',
teamCalculationMethods: Const.teamCalculationMethods, typeList: [
curType: '1', {
typeList: [ id: '1',
{ name: '项目信息'
id: '1', },
name: '竞赛信息' {
}, id: '2',
{ name: '项目进展'
id: '2', },
name: '竞赛进展' {
}, id: '3',
{ name: '通知公告'
id: '3', },
name: '通知公告' ],
} progress: [],
], timer: null,
form: util.local.get('activity'), notices: [],
progress: [],
notices: [],
}; };
}, },
components: { components: {
breadcrumb breadcrumb
}, },
mounted() { mounted() {
this.handleAnnex()
if (this.form.id) { if (this.form.id) {
this.getProgress() this.getProgress()
this.getNotice() this.getNotice()
} }
}, },
methods: { methods: {
// getProgress() { //
handleAnnex() { this.$get(this.api.listActivityProgress, {
const list = this.form.competitionAnnexList activityId: this.form.id
if (list) { }).then(res => {
list.map(e => { this.progress = res.activityProgressList.reverse()
const { filePath } = e }).catch(err => {});
e.canPreview = util.canPreview(filePath.substr(filePath.lastIndexOf('.') + 1)) // },
}) //
this.$forceUpdate() getNotice() {
} this.$post(`${this.api.listActivityAnnouncement}?pageNum=1&pageSize=1000&competitionId=${this.form.id}`).then(({ data }) => {
}, const records = data.records.filter(e => e.status) // status 0稿 1
getProgress() { // records.map(e => {
this.$get(this.api.getCompetitionProgress, { e.announcementText = e.announcementText.replace(/<img.*?(?:>|\/>)/gi, '')
competitionId: this.form.id })
}).then(res => { this.notices = records
this.progress = res.competitionProgressList.reverse() }).catch(res => {})
}).catch(err => {}); },
}, //
// preview(item) {
getNotice() { const { filePath } = item
this.$post(`${this.api.queryAnnouncementByCompetitionId}?pageNum=1&pageSize=1000&competitionId=${this.form.id}`).then(({ data }) => { const suffix = filePath.substr(filePath.lastIndexOf('.') + 1)
const records = data.records.filter(e => e.status) // status 0稿 1 window.open((util.isDoc(suffix) ? 'https://view.officeapps.live.com/op/view.aspx?src=' : '') + item.filePath)
records.map(e => { },
e.announcementText = e.announcementText.replace(/<img.*?(?:>|\/>)/gi, '') //
}) download(item) {
this.notices = records util.downloadFile(item.fileName, item.filePath)
}).catch(res => {}) },
}, // tab
// typeChange() {
previewFile(item) { document.querySelector(`#part${type}`).scrollIntoView()
const { filePath } = item },
const suffix = filePath.substr(filePath.lastIndexOf('.') + 1)
window.open((util.isDoc(suffix) || suffix === 'pdf' ? 'https://view.officeapps.live.com/op/view.aspx?src=' : '') + item.filePath)
},
//
download(item) {
util.downloadFile(item.fileName, item.filePath)
},
// tab
typeChange() {
document.querySelector(`#part${this.curType}`).scrollIntoView()
},
} }
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.activity { .wrap {
padding-bottom: 20px; margin: -24px;
background-color: #F3F6FA; }
.banner{ .banner{
width: 100%; width: 100%;
height: 350px; height: 350px;
padding: 120px 0 0 20%;
color: #fff; color: #fff;
background-size: 100% 350px; background-size: 100% 350px;
background-repeat: no-repeat; background-repeat: no-repeat;
box-sizing: border-box; }
} .l-title {
.center { font-size: 18px;
}
.main .center-con {
width: 1000px; width: 1000px;
margin: 40px auto 0; margin: 40px auto 0;
background: url(../../../assets/img/match-bg1.png) (0px 95px)/auto auto no-repeat,
url(../../../assets/img/match-bg2.png) (98% 300px)/auto auto no-repeat;
}
.main .center-wrap {
margin-top: 30px;
}
.rule-title {
margin-bottom: 10px;
font-size: 16px;
}
.rule {
padding: 15px;
margin-bottom: 15px;
border: 1px solid #dfdfdf;
p {
font-size: 14px;
line-height: 30px;
color: #6e6e6e;
} }
.activity-inner { }
min-height: calc(100vh - 465px); /deep/.el-tabs__item {
padding: 30px 40px 20px; box-shadow: none !important;
}
.content{
position: relative;
padding: 20px 40px;
margin-top: 30px;
background-color: #fff; background-color: #fff;
box-sizing: border-box; .title{
} width: 67%;
/deep/.el-tabs { margin: 0 auto;
.el-tabs__item.is-active, .el-tabs__item:hover { font-size: 28px;
color: #007EFF; text-align: center;
color: #0B1D30;
} }
.el-tabs__active-bar { .tool {
background-color: #007EFF; z-index: 100;
position: sticky;
top: 64px;
margin-bottom: 20px;
background-color: #fff;
} }
} .info .meta{
.p-title { padding: 16px 0;
border-left-color: #007EFF; font-size: 12px;
} color: #999;
.l-title{ text-align: center;
display: flex;
align-items: center;
margin-bottom: 12px;
font-size: 18px;
color: #333;
img{
margin-right: 5px;
}
}
.status {
padding: 0 16px;
margin-left: 20px;
line-height: 34px;
font-size: 14px;
color: #fff;
background-color: #52C41A;
border-radius: 4px;
cursor: pointer;
&.wait {
background-color: #FAAD14;
}
&.signing {
background-color: #007EFF;
}
&.signed {
background-color: #52C41A;
}
&.finish {
background-color: #ccc;
}
}
.title{
width: 67%;
margin: 0 auto;
font-size: 28px;
text-align: center;
color: #0B1D30;
}
.info .meta{
padding: 16px 0;
font-size: 12px;
color: #999;
text-align: center;
}
.texts {
margin-bottom: 30px;
font-size: 14px;
line-height: 1.6;
text-indent: 2em;
overflow: hidden;
/deep/img{
max-width: 100%;
}
}
.files {
margin-bottom: 30px;
li {
display: flex;
align-items: center;
margin: 10px 0;
} }
.file-name { .action {
margin-right: 10px; display: inline-flex;
font-size: 12px; align-items: center;
} }
} .status {
.el-link.el-link--primary { max-width: 120px;
color: #007EFF !important; padding: 0 16px;
&:after { margin-left: 20px;
border-color: #007EFF; line-height: 34px;
} font-size: 14px;
} color: #fff;
} background-color: #52C41A;
.progress{ border-radius: 4px;
position: relative; cursor: pointer;
width: 95%; @include ellipsis();
padding: 50px 0; &.wait {
margin: 40px auto 80px; background-color: #FAAD14;
text-align: left; }
&:before{ &.signing {
content: ''; background-color: $main-color;
position: absolute; }
top: 0; &.signed {
left: 50%; background-color: #52C41A;
width: 2px; }
height: 100%; &.playing {
background-color: #E1E6F2; background-color: #f96d6d;
}
&.finish {
background-color: #ccc;
}
} }
&:after { .end-text {
content: ''; font-size: 12px;
position: absolute; color: #666;
top: -10px; em {
left: 430px; font-style: normal;
border: 8px solid transparent; color: #f00;
border-bottom-color: #E1E6F2; }
} }
.rocket { .texts{
position: absolute; margin: 20px 0 50px;
bottom: -50px; font-size: 14px;
left: 425px; line-height: 1.6;
text-indent: 2em;
overflow: hidden;
/deep/img{
max-width: 100%;
}
} }
li{ .progress{
position: relative; position: relative;
width: 400px; width: 95%;
margin-bottom: 42px; padding: 50px 0;
.dot{ margin: 40px auto 80px;
text-align: left;
&:before{
content: '';
position: absolute;
top: 0;
left: 50%;
width: 2px;
height: 100%;
background-color: #E1E6F2;
}
&:after {
content: '';
position: absolute; position: absolute;
top: 12px; top: -10px;
left: 431px; left: 430px;
width: 15px; border: 8px solid transparent;
height: 15px; border-bottom-color: #E1E6F2;
background-color: #DCDCDC;
border-radius: 50%;
} }
.name{ .rocket {
display: inline-block; position: absolute;
padding: 0 19px; bottom: -50px;
margin-bottom: 16px; left: 425px;
line-height: 40px;
text-align: center;
font-size: 16px;
color: #fff;
border-radius: 20px;
background-color: #C4C4C4;
} }
.desc{ li{
position: relative; position: relative;
color: #333; width: 400px;
font-size: 14px; margin-bottom: 42px;
} .dot{
&.ing, &.done { position: absolute;
.dot { top: 12px;
top: 8px; left: 431px;
background-color: #007EFF; width: 15px;
height: 15px;
background-color: #DCDCDC;
border-radius: 50%;
} }
.name { .name{
background-color: #007EFF; display: inline-block;
padding: 0 19px;
margin-bottom: 16px;
line-height: 40px;
text-align: center;
font-size: 16px;
color: #fff;
border-radius: 20px;
background-color: #C4C4C4;
} }
} .desc{
&.ing { position: relative;
.dot { color: #333;
width: 27px; font-size: 14px;
height: 27px;
border: 6px solid #E2F1FB;
} }
} &.ing, &.done {
&:nth-child(odd) {
text-align: right;
&.ing {
.dot { .dot {
left: auto; top: 8px;
right: -58px; background-color: #007EFF;
}
.name {
background-color: #007EFF;
} }
} }
.name { &.ing {
&:before { .dot {
content: ''; width: 27px;
z-index: 2; height: 27px;
position: absolute; border: 6px solid #E2F1FB;
top: 14px;
right: -35px;
border: 18px solid transparent;
border-top-width: 6px;
border-bottom-width: 6px;
border-left-color: #C4C4C4;
} }
} }
.desc { &:nth-child(odd) {
text-align: right; text-align: right;
} &.ing {
&.ing, &.done { .dot {
left: auto;
right: -51px;
}
}
.name { .name {
&:before { &:before {
border-left-color: #007EFF; content: '';
z-index: 2;
position: absolute;
top: 14px;
right: -35px;
border: 18px solid transparent;
border-top-width: 6px;
border-bottom-width: 6px;
border-left-color: #C4C4C4;
} }
} }
} .desc {
} text-align: right;
&:nth-child(even) {
margin-left: 482px;
.dot {
left: -51px;
}
&.ing {
.dot {
left: -57px;
} }
} &.ing, &.done {
.name { .name {
text-align: left; &:before {
&:after { border-left-color: #007EFF;
content: ''; }
z-index: 2; }
position: absolute;
top: 14px;
left: -35px;
border: 18px solid transparent;
border-top-width: 6px;
border-bottom-width: 6px;
border-right-color: #C4C4C4;
} }
} }
.desc { &:nth-child(even) {
&:before { margin-left: 482px;
left: auto; .dot {
right: -16px; left: -51px;
border: 8px solid transparent;
border-left-color: #fff;
} }
&:after { &.ing {
left: auto; .dot {
right: -18px; left: -57px;
border: 9px solid transparent; }
border-left-color: #E6E6E6;
} }
}
&.ing, &.done {
.name { .name {
text-align: left;
&:after {
content: '';
z-index: 2;
position: absolute;
top: 14px;
left: -35px;
border: 18px solid transparent;
border-top-width: 6px;
border-bottom-width: 6px;
border-right-color: #C4C4C4;
}
}
.desc {
&:before {
left: auto;
right: -16px;
border: 8px solid transparent;
border-left-color: #fff;
}
&:after { &:after {
border-right-color: #007EFF; left: auto;
right: -18px;
border: 9px solid transparent;
border-left-color: #E6E6E6;
}
}
&.ing, &.done {
.name {
&:after {
border-right-color: #007EFF;
}
} }
} }
} }
} &:last-child{
&:last-child{ margin-bottom: 0;
margin-bottom: 0; }
} }
} }
} }
.files {
margin-bottom: 30px;
li {
display: flex;
align-items: center;
margin: 10px 0;
}
.fileName {
margin-right: 10px;
font-size: 12px;
}
}
.notice-list { .notice-list {
text-align: left; text-align: left;
li { li {
@ -501,33 +472,56 @@ export default {
text-overflow: ellipsis; text-overflow: ellipsis;
} }
} }
.empty{ .table {
display: flex; width: 100%;
justify-content: center; border-collapse: collapse;
align-items: center; th, td {
padding: 50px 0; padding: 12px;
text-align: center; border: 1px solid #ebeef5;
img{
width: 471px;
} }
p{ &.tc {
margin-top: 40px; text-align: center;
font-size: 18px; }
color: rgba(0, 0, 0, 0.25); th {
text-align: center;
background-color: #f8faff;
}
.icon {
margin-right: 10px;
font-size: 16px;
color: #7a7a7a;
cursor: pointer;
&:hover {
color: #007EFF;
}
}
.plus {
margin-bottom: 10px;
text-align: right;
}
.line {
display: flex;
align-items: center;
margin-bottom: 10px;
.el-input {
margin-right: 15px;
}
} }
} }
.rule-title { .flex-center {
margin-bottom: 10px; display: flex;
font-size: 16px; justify-content: space-between;
} align-items: center;
.rule {
padding: 15px;
margin-bottom: 15px; margin-bottom: 15px;
border: 1px solid #dfdfdf; }
p { /deep/.dia-form {
font-size: 14px; .w-100 {
line-height: 30px; width: 100%;
color: #6e6e6e; }
.tips {
display: flex;
justify-content: center;
align-items: center;
} }
} }
</style> </style>

@ -62,15 +62,20 @@ export default {
Setting.dynamicRoute && this.initTabs() Setting.dynamicRoute && this.initTabs()
}, },
beforeRouteLeave(to, from, next) { beforeRouteLeave(to, from, next) {
const detail = this.$refs.detail const { detail } = this.$refs
if (detail.step < 4 && detail.$refs['step' + detail.step].updateTime) { if (detail) {
this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示.......', { const step = detail.$refs['step' + detail.step]
type: 'warning' if (detail.step < 4 && step && step.updateTime) {
}).then(() => { this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示.......', {
detail.save(1,to.path,next) type: 'warning'
}).catch(() => { }).then(() => {
detail.save(1,to.path,next)
}).catch(() => {
next()
})
} else {
next() next()
}) }
} else { } else {
next() next()
} }
@ -105,16 +110,21 @@ export default {
handleSave(i) { handleSave(i) {
// //
if (this.active === 'tab1') { if (this.active === 'tab1') {
const detail = this.$refs.detail const { detail } = this.$refs
if (detail.step < 4 && detail.$refs['step' + detail.step].updateTime) { if (detail) {
this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示', { const step = detail.$refs['step' + detail.step]
type: 'warning' if (detail.step < 4 && step && step.updateTime) {
}).then(() => { this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示', {
detail.save(1, 1) type: 'warning'
this.backOrTab(i) }).then(() => {
}).catch(() => { detail.save(1, 1)
this.backOrTab(i)
}).catch(() => {
this.backOrTab(i)
})
} else {
this.backOrTab(i) this.backOrTab(i)
}) }
} else { } else {
this.backOrTab(i) this.backOrTab(i)
} }

@ -1,10 +1,10 @@
<template> <template>
<div class="wrap"> <div class="wrap">
<el-carousel :interval="6000"> <el-carousel :interval="6000" :height="carouselHeight">
<template v-for="(item, i) in banners"> <template v-for="(item, i) in banners">
<el-carousel-item :key="i"> <el-carousel-item :key="i">
<div :class="['banner-item', {'cursor-pointer': item.url}]" @click="openLink(item)"> <div :class="['banner-item', {'cursor-pointer': item.url}]" @click="openLink(item)">
<img :src="item.banner" alt=""> <img :src="item.banner" alt="" :style="{height: carouselHeight}">
<p class="banner-name">{{ item.title }}</p> <p class="banner-name">{{ item.title }}</p>
</div> </div>
</el-carousel-item> </el-carousel-item>
@ -26,26 +26,40 @@
</div> </div>
</div> </div>
<div class="filter"> <div class="filter">
<dl> <dl v-if="curTab == 1">
<dt>学科专业</dt> <dt>学科专业</dt>
<dd>学科类别</dd>
<el-select v-model="form.categoryId" clearable @change="getProfessionalClass()" @clear="clearClass()"> <el-select v-model="form.categoryId" clearable @change="getProfessionalClass()" @clear="clearClass()">
<el-option label="不限" value=""></el-option>
<el-option v-for="(item,index) in subjectList" :key="index" :label="item.disciplineName" :value="item.disciplineId"></el-option> <el-option v-for="(item,index) in subjectList" :key="index" :label="item.disciplineName" :value="item.disciplineId"></el-option>
</el-select> </el-select>
<dt style="margin: 0 10px 0 50px">专业类</dt> <dd style="margin: 0 0 0 50px">专业类</dd>
<el-select v-model="form.professionalCategoryId" clearable :disabled="form.categoryId ? false : true" @change="getProfessional" @clear="clearProfess()"> <el-select v-model="form.professionalCategoryId" clearable :disabled="form.categoryId ? false : true" @change="getProfessional" @clear="clearProfess()">
<el-option label="不限" value=""></el-option>
<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-select>
<dt style="margin: 0 10px 0 50px">专业</dt> <dd style="margin: 0 0 0 50px">专业</dd>
<el-select v-model="form.professionalId" clearable :disabled="form.professionalCategoryId ? false : true" @change="initData"> <el-select v-model="form.professionalId" clearable :disabled="form.professionalCategoryId ? false : true" @change="initData">
<el-option label="不限" value=""></el-option>
<el-option v-for="(item,index) in professionalList" :key="index" :label="item.professionalName" :value="item.professionalId"></el-option> <el-option v-for="(item,index) in professionalList" :key="index" :label="item.professionalName" :value="item.professionalId"></el-option>
</el-select> </el-select>
</dl> </dl>
<dl v-if="curTab == 3">
<dt>产品标签</dt>
<div class="vals">
<dd :class="{active: form.tagId === ''}" @click="filterChange('', 'tagId')">全部</dd>
<dd v-for="(item, i) in labels" :key="i" :class="{active: form.tagId === item.tagsId}" @click="filterChange(item.tagsId, 'tagId')">{{ item.tagsName }}</dd>
</div>
</dl>
<dl> <dl>
<dt>产品类型</dt> <dt>产品类型</dt>
<dd :class="{active: form.productClassification === ''}" @click="filterChange('', 'productClassification')">全部</dd> <div class="vals">
<dd v-for="(item, i) in classifications" :key="i" :class="{active: form.productClassification === item.typeId}" @click="filterChange(item.typeId, 'productClassification')">{{ item.typeName }}</dd> <dd :class="{active: form.productClassification === ''}" @click="filterChange('', 'productClassification')">全部</dd>
<dd v-for="(item, i) in classifications" :key="i" :class="{active: form.productClassification === item.typeId}" @click="filterChange(item.typeId, 'productClassification')">{{ item.typeName }}</dd>
</div>
</dl> </dl>
<dl> <dl>
<dt>购买状态</dt> <dt>购买状态</dt>
@ -56,6 +70,11 @@
<div class="filter m-t-20"> <div class="filter m-t-20">
<dl> <dl>
<dd v-for="(item, i) in sorts" :key="i" :class="{active: form.sort === item.id}" @click="filterChange(item.id, 'sort')">{{ item.name }}</dd> <dd v-for="(item, i) in sorts" :key="i" :class="{active: form.sort === item.id}" @click="filterChange(item.id, 'sort')">{{ item.name }}</dd>
<dd :class="{active: form.sort === 2 || form.sort === 5}" @click="sort">发布时间</dd>
<span class="caret" @click="sort">
<i :class="['asc', {active: form.sort === 2}]"></i>
<i :class="['desc', {active: form.sort === 5}]"></i>
</span>
</dl> </dl>
</div> </div>
@ -66,37 +85,31 @@
<img :src="item.coverDrawing" alt="" /> <img :src="item.coverDrawing" alt="" />
<img v-if="item.logoOfOurSchool" class="my-school" src="@/assets/img/my-school.png" alt=""> <img v-if="item.logoOfOurSchool" class="my-school" src="@/assets/img/my-school.png" alt="">
<div class="texts"> <div class="texts">
<div class="title">{{ item.productName }}</div> <el-tooltip effect="dark" :visible-arrow="false" :content="item.productName" placement="bottom">
<div class="title">{{ item.productName }}</div>
</el-tooltip>
<div class="desc" v-html="item.productIntroduction"></div> <div class="desc" v-html="item.productIntroduction"></div>
<div class="metas"> <div class="tags">
<template v-if="curTab === 2"> <el-tooltip v-if="item.tagsName" class="item" effect="dark" :visible-arrow="false" :content="item.tagsName" placement="bottom">
<el-tag <div>
type="danger"
effect="dark">
官方精选
</el-tag>
<div class="meta">{{ item.learningCount }}学过</div>
</template>
<div v-if="curTab === 3 && item.tagsName">
<el-tag v-for="(tag, i) in item.tagsName.split(',')" :key="i" class="tag">{{ tag }}</el-tag> <el-tag v-for="(tag, i) in item.tagsName.split(',')" :key="i" class="tag">{{ tag }}</el-tag>
</div> </div>
<template v-if="!curTab || curTab === 1"> </el-tooltip>
<div class="meta"> </div>
<img class="icon" src="@/assets/img/eye.png" alt=""> <div :class="['metas', {'not-selected': !item.selected}]">
{{ item.learningCount }} <el-tag
</div> v-if="item.selected"
<div v-if="item.isAssociatedProduct === 0" class="meta"> type="danger"
<img class="icon" src="@/assets/img/platform.png" alt=""> effect="dark">
平台官方 官方精选
</div> </el-tag>
<!-- <span class="type">{{ item.courseType == 1 ? '付费' : '免费'}}</span> --> <div v-if="item.isCourse" class="meta">{{ item.learningCount }}人学过</div>
</template>
</div> </div>
</div> </div>
</li> </li>
</ul> </ul>
<div class="pagination"> <div class="pagination">
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="page"></el-pagination> <el-pagination background layout="total, prev, pager, next" :page-size="pageSize" :total="total" @current-change="handleCurrentChange" :current-page="page"></el-pagination>
</div> </div>
</template> </template>
</div> </div>
@ -110,6 +123,7 @@ import Setting from "@/setting";
export default { export default {
data() { data() {
return { return {
carouselHeight: '336px',
banners: [], banners: [],
timer: null, timer: null,
curTab: '', curTab: '',
@ -133,6 +147,7 @@ export default {
], ],
form: { form: {
categoryId: '', categoryId: '',
isShelves: 0,
hotTag: 1, hotTag: 1,
professionalCategoryId: '', professionalCategoryId: '',
professionalId: '', professionalId: '',
@ -140,7 +155,9 @@ export default {
productName: '', productName: '',
purchaseStatus: '', purchaseStatus: '',
sort: 0, sort: 0,
tagId: ''
}, },
labels: [],
subjectList: [], // subjectList: [], //
professionalClassList: [], // professionalClassList: [], //
professionalList: [], // professionalList: [], //
@ -168,10 +185,6 @@ export default {
id: 1, id: 1,
name: '热销排行' name: '热销排行'
}, },
{
id: 2,
name: '发布时间'
},
], ],
list: [ list: [
{ {
@ -190,7 +203,7 @@ export default {
keyword: '', keyword: '',
total: 0, total: 0,
page: 1, page: 1,
pageSize: 10, pageSize: 12,
searchTimer: null, searchTimer: null,
loadIns: null loadIns: null
}; };
@ -204,8 +217,11 @@ export default {
} }
}, },
mounted() { mounted() {
console.log(11, parseInt(window.innerWidth / 5.7))
this.carouselHeight = parseInt(window.innerWidth / 5.7) + 'px'
this.getBanner() this.getBanner()
this.getSubject() this.getSubject()
this.getLabel()
this.getClass() this.getClass()
this.initData() this.initData()
}, },
@ -214,7 +230,8 @@ export default {
getBanner() { getBanner() {
this.$post(this.api.listMarketing, { this.$post(this.api.listMarketing, {
pageNum: 1, pageNum: 1,
pageSize: 1000 pageSize: 1000,
isOpen: 0
}).then(({ page }) => { }).then(({ page }) => {
this.banners = page.records this.banners = page.records
}).catch(res => {}) }).catch(res => {})
@ -227,7 +244,16 @@ export default {
pageNum: this.page, pageNum: this.page,
pageSize: this.pageSize, pageSize: this.pageSize,
}).then(({ page }) => { }).then(({ page }) => {
this.list = page.records const list = page.records
list.forEach(e => {
//
const el = document.createElement('div')
el.innerHTML = e.productIntroduction
e.productIntroduction = el.innerText
const cid = e.classificationId
e.isCourse = (cid === 1 || cid === 2) && !e.isAssociatedProduct
})
this.list = list
this.total = page.total this.total = page.total
this.loadIns.close() this.loadIns.close()
}).catch(res => { }).catch(res => {
@ -239,6 +265,12 @@ export default {
this.getData(); this.getData();
}, },
//
getLabel() {
this.$get(this.api.tagsList).then(res => {
this.labels = res.tagsList
}).catch(err => {})
},
// //
getSubject() { getSubject() {
this.$get(this.api.courseDiscipline).then(res => { this.$get(this.api.courseDiscipline).then(res => {
@ -318,6 +350,11 @@ export default {
this.form[prop] = id this.form[prop] = id
this.initData() this.initData()
}, },
//
sort() {
this.form.sort = this.form.sort === 2 ? 5 : 2
this.initData()
},
handleCurrentChange(val) { handleCurrentChange(val) {
this.page = val; this.page = val;
this.getData(); this.getData();
@ -337,7 +374,7 @@ export default {
position: relative; position: relative;
img { img {
width: 100%; width: 100%;
height: 336px; height: 100%;
} }
.banner-name { .banner-name {
position: absolute; position: absolute;
@ -405,11 +442,13 @@ export default {
background-color: #fff; background-color: #fff;
border-radius: 10px; border-radius: 10px;
dl { dl {
position: relative;
display: flex; display: flex;
align-items: center; flex-wrap: wrap;
margin: 20px 0; margin: 20px 0;
dt { dt {
min-width: 60px; min-width: 60px;
padding: 5px 0;
margin-right: 30px; margin-right: 30px;
color: #666; color: #666;
font-size: 14px; font-size: 14px;
@ -428,6 +467,39 @@ export default {
} }
} }
} }
.vals {
display: inline-flex;
flex-wrap: wrap;
width: 920px;
}
.caret {
position: absolute;
top: 4px;
left: 250px;
width: 20px;
height: 20px;
cursor: pointer;
i {
position: absolute;
width: 0;
height: 0;
border: 5px solid transparent;
}
.asc {
top: 0;
border-bottom-color: #c0c4cc;
&.active {
border-bottom-color: #409eff;
}
}
.desc {
top: 12px;
border-top-color: #c0c4cc;
&.active {
border-top-color: #409eff;
}
}
}
} }
.courses { .courses {
position: relative; position: relative;
@ -484,11 +556,11 @@ export default {
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
overflow: hidden; overflow: hidden;
&.ie { }
height: 80px; .tags {
text-overflow: ellipsis; height: 24px;
white-space: nowrap; margin-top: 10px;
} overflow: hidden;
} }
.tag { .tag {
margin-right: 8px; margin-right: 8px;
@ -509,6 +581,9 @@ export default {
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-top: 10px; margin-top: 10px;
&.not-selected {
justify-content: flex-end;
}
} }
.meta { .meta {
display: inline-flex; display: inline-flex;

@ -7,19 +7,20 @@
</div> </div>
<div class="right"> <div class="right">
<h6>{{ form.mall.productName }}</h6> <h6>{{ form.mall.productName }}</h6>
<div class="meta"> <div v-if="isCourse" class="meta">
<span class="val">48</span> 个实验项目&emsp;&emsp;已有 <span class="val">{{ form.goodsRes.learningCount }}</span>人学过 <span class="val">{{ form.numberOfExperimentalItems }}</span> 个实验项目&emsp;&emsp;
已有 <span class="val">{{ form.goodsRes.learningCount }}</span>人学过
</div> </div>
<div class="des" v-html="form.mall.productIntroduction"></div> <div class="des" v-html="form.mall.productIntroduction"></div>
<div class="field">适用专业{{ form.goodsRes.disciplineName }}</div> <div class="field">适用专业{{ form.goodsRes.professionalName }}</div>
<div class="fields"> <div class="fields">
<div v-if="form.mall.applicationScenario" class="field"><span class="label">适用场景</span>{{ form.mall.applicationScenario }}</div> <div v-if="form.mall.applicationScenario" class="field"><span class="label">适用场景</span>{{ form.mall.applicationScenario }}</div>
<div v-if="form.mall.matchingCourse" class="field"><span class="label">匹配课程</span>{{ form.mall.matchingCourse }}</div> <div v-if="form.mall.matchingCourse" class="field"><span class="label">匹配课程</span>{{ form.mall.matchingCourse }}</div>
<div v-if="form.mall.courseHours" class="field"><span class="label">预计课时</span>{{ form.mall.courseHours }}</div> <div v-if="form.mall.courseHours" class="field"><span class="label">预计课时</span>{{ form.mall.courseHours }}</div>
<div v-if="form.goodsRes.typeName" class="field"><span class="label">产品类型</span>{{ form.goodsRes.typeName }}</div> <div v-if="form.goodsRes.typeName" class="field"><span class="label">产品类型</span>{{ form.goodsRes.typeName }}</div>
</div> </div>
<button v-if="form.goodsRes.logoOfOurSchool" class="btn" @click="toTrail">试用体验</button> <button v-if="!form.goodsRes.logoOfOurSchool" class="btn" @click="toTrail">试用体验</button>
<button v-else class="btn entry" @click="toStation">进入实验</button> <button v-else-if="isCourse || withLink" class="btn entry" @click="toStation">进入实验</button>
</div> </div>
</div> </div>
<div class="course"> <div class="course">
@ -29,26 +30,27 @@
</ul> </ul>
<div class="courses"> <div class="courses">
<template v-if="!curTab"> <template v-if="!curTab">
<h6>课程介绍</h6>
<div class="des" v-html="form.mall.detailedIntroduction"></div> <div class="des" v-html="form.mall.detailedIntroduction"></div>
</template> </template>
<template v-else> <template v-else>
<div v-for="(item, i) in chapterList" :key="i"> <div class="chapter" v-for="(item, i) in chapterList" :key="i">
<h6>{{ item.name }}</h6> <div class="chapterName">{{ item.name }}</div>
<ul v-if="item.subsectionList.length" class="list"> <div class="section" v-if="item.subsectionList.length">
<li v-for="(section, i) in item.subsectionList" :key="i" @click="toPreview(item, section)"> <div v-for="(section, j) in item.subsectionList" :key="j" @click="toPreview(i, j)">
<p class="name"> <div class="sectionName" :title="section.name" :class="{active: curLink === `${item.name}${section.name}`}">
<img v-if="section.fileType === 'pptx'" src="@/assets/img/exts/ppt.png" alt=""> <div class="val">
<img v-else-if="section.fileType === 'mp4'" src="@/assets/img/exts/video.png" alt=""> <img v-if="section.fileType === 'pptx'" src="@/assets/img/exts/ppt.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 === 'mp4'" src="@/assets/img/exts/video.png" alt="">
<img v-else-if="section.fileType === 'txt'" src="@/assets/img/exts/txt.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 === 'pdf'" src="@/assets/img/exts/pdf.png" alt=""> <img v-else-if="section.fileType === 'txt'" src="@/assets/img/exts/txt.png" alt="">
<img v-else src="@/assets/img/exts/pic.png" alt=""> <img v-else-if="section.fileType === 'pdf'" src="@/assets/img/exts/pdf.png" alt="">
{{ section.projectName }} <img v-else src="@/assets/img/exts/pic.png" alt="">
</p> {{ section.name }}
<i :class="['status', section.whetherToStudyOrNot ? 'el-icon-success' : 'circle']" @click.stop="studySection(item, section)"></i> </div>
</li> <i v-if="!form.goodsRes.logoOfOurSchool" class="icon el-icon-lock"></i>
</ul> </div>
</div>
</div>
</div> </div>
</template> </template>
</div> </div>
@ -61,28 +63,18 @@
<img v-if="item.logoOfOurSchool" class="my-school" src="@/assets/img/my-school.png" alt=""> <img v-if="item.logoOfOurSchool" class="my-school" src="@/assets/img/my-school.png" alt="">
<div class="texts"> <div class="texts">
<div class="title">{{ item.productName }}</div> <div class="title">{{ item.productName }}</div>
<div class="desc" v-html="item.productIntroduction"></div> <div :class="['desc', {'not-tag': !item.tagsName}]" v-html="item.productIntroduction"></div>
<div v-if="item.tagsName" class="tags">
<el-tag v-for="(tag, i) in item.tagsName.split(',')" :key="i" class="tag">{{ tag }}</el-tag>
</div>
<div class="metas"> <div class="metas">
<template v-if="item.selected"> <el-tag
<el-tag v-if="item.selected"
type="danger" type="danger"
effect="dark"> effect="dark">
官方精选 官方精选
</el-tag> </el-tag>
<div class="meta">{{ item.learningCount }}学过</div> <div v-if="item.isCourse" class="meta">{{ item.learningCount }}人学过</div>
</template>
<template v-else>
<div class="meta">
<img class="icon" src="@/assets/img/eye.png" alt="">
{{ item.learningCount }}
</div>
<div v-if="item.isAssociatedProduct === 0" class="meta">
<img class="icon" src="@/assets/img/platform.png" alt="">
平台官方
</div>
<span class="type">{{ item.courseType == 1 ? '付费' : '免费'}}</span>
</template>
</div> </div>
</div> </div>
</li> </li>
@ -90,6 +82,16 @@
</div> </div>
</div> </div>
</div> </div>
<!-- 选择链接 -->
<el-dialog title="请选择链接" :visible.sync="linkVisible" width="420px" center :close-on-click-modal="false">
<div v-if="withLink" class="buy">
<div v-for="(link, i) in form.mallNonAssociatedLinks" :key="i" class="link-line">
{{ link.urlName }}
<a class="url" :href="link.url" target="_blank">{{ link.url }}</a>
</div>
</div>
</el-dialog>
</div> </div>
</template> </template>
@ -106,19 +108,44 @@ export default {
id: 0, id: 0,
name: '详情介绍' name: '详情介绍'
}, },
{
id: 1,
name: '课程目录'
},
], ],
form: { form: {
classificationIds: [],
mall: {}, mall: {},
goodsRes: {} goodsRes: {}
}, },
chapterList: [], chapterList: [],
hots: [] hots: [],
linkVisible: false
}; };
}, },
computed: {
//
withLink() {
const links = this.form.mallNonAssociatedLinks
return this.form.mall.isAssociatedProduct && links && links.length
},
//
isCourse() {
let id = this.form.classificationIds
if (id) {
id = id[0]
const isCourse = (id == 1 || id == 2) && this.form.mall.isAssociatedProduct === 0
this.tabs = [
{
id: 0,
name: '详情介绍'
},
]
isCourse && this.tabs.push({
id: 1,
name: '课程目录'
})
return isCourse
}
return false
}
},
mounted() { mounted() {
this.getData() this.getData()
this.getHot() this.getHot()
@ -128,37 +155,40 @@ export default {
getData() { getData() {
this.$get(`${this.api.detailsOfGoods}?mallId=${this.id}`).then(res => { this.$get(`${this.api.detailsOfGoods}?mallId=${this.id}`).then(res => {
const e = res.orderDetails const e = res.orderDetails
if (e.mall.interfaceDiagram) e.interfaceDiagrams = e.mall.interfaceDiagram.split(',') // +
e.interfaceDiagrams = [e.mall.coverDrawing]
if (e.mall.interfaceDiagram) e.interfaceDiagrams.push(...e.mall.interfaceDiagram.split(',').slice(0, 3))
this.form = e this.form = e
this.getChapter() this.chapterList = ''
e.mall.associatedProduct && this.getChapter()
}).catch(err => {}) }).catch(err => {})
}, },
// //
async getChapter() { async getChapter() {
let res = await this.$post(`${this.api.courseLearningProgress}?courseId=${this.form.mall.associatedProduct}`) let res = await this.$get(this.api.curriculumChapter + '/' + this.form.mall.associatedProduct)
this.chapterList = res.list this.chapterList = res.chapterList
}, },
// tab // tab
tabChange({ id }) { tabChange({ id }) {
this.curTab = id this.curTab = id
}, },
// //
toPreview(item, section) { toPreview(i, j) {
this.form.goodsRes.logoOfOurSchool ? this.form.goodsRes.logoOfOurSchool ?
this.$router.push('/station/preview?courseId=' + this.form.mall.associatedProduct + '&curriculumName=' + this.form.mall.associatedProductName) : this.$router.push(`/station/preview?courseId=${this.form.mall.associatedProduct}&curriculumName=${this.form.mall.associatedProductName}&mallId=${this.id}&chapter=${i}&section=${j}`) :
this.toTrail() this.toTrail()
}, },
// / // /
studySection(item) { studySection(item) {
item.whetherToStudyOrNot ? item.whetherToStudyOrNot ?
this.$post(`${this.api.deleteLearningProgress}?id=${item.learningProgressId}`).then(res => { this.$post(`${this.api.deleteLearningProgress}?id=${item.learningProgressId}`).then(res => {
this.getProgress() this.getChapter()
}).catch(res => {}) : }).catch(res => {}) :
this.$post(this.api.saveLearningProgress, { this.$post(this.api.saveLearningProgress, {
cid: this.courseId, cid: this.form.mall.associatedProduct,
projectId: item.projectId, projectId: item.projectId,
}).then(res => { }).then(res => {
this.getProgress() this.getChapter()
}).catch(res => {}) }).catch(res => {})
}, },
// //
@ -167,9 +197,13 @@ export default {
}, },
// //
toStation() { toStation() {
this.$post(`${this.api.addLearningRecord}?mallId=${this.id}`).then(res => { if (this.isCourse) { //
this.$router.push('/station/preview?courseId=' + this.form.mall.associatedProduct + '&curriculumName=' + this.form.mall.associatedProductName) this.$post(`${this.api.addLearningRecord}?mallId=${this.id}`).then(res => {
}).catch(res => {}) this.$router.push('/station/preview?courseId=' + this.form.mall.associatedProduct + '&curriculumName=' + this.form.mall.associatedProductName + '&mallId=' + this.id)
}).catch(res => {})
} else if (this.withLink) { //
this.linkVisible = true
}
}, },
// //
getHot() { getHot() {
@ -179,12 +213,23 @@ export default {
pageNum: 1, pageNum: 1,
pageSize: 2, pageSize: 2,
}).then(({ page }) => { }).then(({ page }) => {
this.hots = page.records const list = page.records
list.forEach(e => {
//
const el = document.createElement('div')
el.innerHTML = e.productIntroduction
e.productIntroduction = el.innerText
const cid = e.classificationId
e.isCourse = (cid === 1 || cid === 2) && !e.isAssociatedProduct
})
this.hots = list
}).catch(res => {}) }).catch(res => {})
}, },
// //
toDetail(id) { toDetail(id) {
this.$router.push(`show?id=${id}`); this.$router.push(`show?id=${id}`)
this.id = id
this.getData()
}, },
} }
}; };
@ -222,6 +267,7 @@ export default {
} }
.right { .right {
width: 646px; width: 646px;
overflow: hidden;
} }
h6 { h6 {
font-size: 24px; font-size: 24px;
@ -251,12 +297,11 @@ export default {
} }
.fields { .fields {
display: flex; display: flex;
margin: 10px 0 20px; justify-content: space-between;
flex-wrap: wrap;
margin: 10px 0 10px;
.field { .field {
margin-right: 50px; margin-bottom: 10px;
&:last-child {
margin-right: 0;
}
} }
} }
.btn { .btn {
@ -280,6 +325,7 @@ export default {
} }
.tab { .tab {
display: inline-flex; display: inline-flex;
margin-left: 10px;
li { li {
position: relative; position: relative;
margin-right: 20px; margin-right: 20px;
@ -306,7 +352,7 @@ export default {
margin-top: 20px; margin-top: 20px;
.detail { .detail {
width: 835px; width: 835px;
padding: 20px 36px; padding: 20px 24px;
background-color: #fff; background-color: #fff;
border-radius: 10px; border-radius: 10px;
@ -314,48 +360,49 @@ export default {
} }
.courses { .courses {
margin-top: 40px; margin-top: 40px;
h6 { .chapters{
margin-bottom: 20px; margin-top: 16px;
font-size: 14px; max-height: calc(100% - 53px);
color: #333; overflow: auto;
}
.chapter{
margin-bottom: 20px;
} }
.list { .chapterName{
height: calc(100vh - 530px); padding: 0 12px;
padding-right: 15px; margin-bottom: 15px;
overflow: auto; color: #333;
li { font-size: 14px;
}
.sectionName{
position: relative;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; padding: 12px;
height: 46px; font-size: 14px;
color: #666;
cursor: pointer;
border-radius: 8px; border-radius: 8px;
@include ellipsis;
img {
margin-right: 8px;
}
&:hover { &:hover {
color: #007EFF;
background: #F6FBFF; background: #F6FBFF;
} }
} .val {
.name { display: inline-flex;
display: inline-flex; align-items: center;
align-items: center; }
font-size: 14px; .icon {
color: #333; font-size: 18px;
img { color: #666;
margin-right: 8px;
} }
}
.status {
font-size: 18px;
color: #00c935;
}
.circle {
width: 18px;
height: 18px;
border-radius: 50%;
border: 1px solid #ccc;
}
} }
} }
.products { .products {
width: 270px; width: 295px;
margin-left: 24px; margin-left: 24px;
&>h6 { &>h6 {
font-size: 14px; font-size: 14px;
@ -406,12 +453,13 @@ export default {
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
overflow: hidden; overflow: hidden;
&.ie { &.not-tag {
height: 80px; -webkit-line-clamp: 3;
text-overflow: ellipsis;
white-space: nowrap;
} }
} }
.tags {
margin-top: 10px;
}
.tag { .tag {
margin-right: 8px; margin-right: 8px;
color: #007EFF; color: #007EFF;
@ -452,4 +500,11 @@ export default {
} }
} }
} }
.link-line {
margin: 5px 0;
.url {
color: #007EFF;
text-decoration: underline;
}
}
</style> </style>

@ -711,10 +711,10 @@ export default {
}).then(() => { }).then(() => {
this.save(this.projectManage.state) this.save(this.projectManage.state)
}).catch(() => { }).catch(() => {
this.$router.push('/project/list') this.$router.back()
}) })
} else { } else {
this.$router.push('/project/list') this.$router.back()
} }
} }
} }

@ -724,7 +724,7 @@ export default {
}) })
const courseData = {} const courseData = {}
courseList.map(e => { courseList.map(e => {
e.curriculumName = e.curriculumName.substring(0, 10) // e.curriculumName = e.curriculumName.substring(0, 10)
courseData[e.curriculumName] = [] courseData[e.curriculumName] = []
}) })
this.$post(this.api.studentAssessSchievement, times).then(({ data }) => { this.$post(this.api.studentAssessSchievement, times).then(({ data }) => {
@ -809,7 +809,7 @@ export default {
], ],
grid: { grid: {
left: '30', left: '30',
top: '32%', top: '45%',
right: '10', right: '10',
bottom: '5%', bottom: '5%',
containLabel: true containLabel: true

@ -76,7 +76,7 @@ export default {
}); });
}, },
goPreview(item) { goPreview(item) {
this.$router.push(`/station/preview?courseId=${item.cid}&curriculumName=${item.curriculumName}`); this.$router.push(`/station/preview?courseId=${item.cid}&curriculumName=${item.curriculumName}&mallId=${item.mallId || ''}`);
}, },
// tab // tab
tabChange(item) { tabChange(item) {

@ -56,8 +56,8 @@
<div class="list"> <div class="list">
<h4 class="title">{{ courseName }}</h4> <h4 class="title">{{ courseName }}</h4>
<div> <div>
<h6 class="pro-title">我的学习进度</h6> <h6 class="pro-title">当前教学进度</h6>
<el-progress :stroke-width="12" :percentage="schedule" :text-color="'#fff'"></el-progress> <el-progress :stroke-width="12" :percentage="schedule" :format="percentFormat" :text-color="'#fff'"></el-progress>
</div> </div>
<div class="types"> <div class="types">
<div :class="['item', { active: type === 1 }]" @click="typeChange(1)"> <div :class="['item', { active: type === 1 }]" @click="typeChange(1)">
@ -102,11 +102,11 @@
<template v-if="active === 1"> <template v-if="active === 1">
<el-card shadow="hover" class="m-t-20 m-b-20"> <el-card shadow="hover" class="m-t-20 m-b-20">
<h4 style="margin-bottom: 10px;font-size: 16px;">课程简介</h4> <h4 style="margin-bottom: 10px;font-size: 16px;">课程简介</h4>
<p>{{ briefIntroduction }}</p> <div v-html="briefIntroduction"></div>
</el-card> </el-card>
<el-card shadow="hover" class="m-b-20"> <el-card shadow="hover" class="m-b-20">
<h4 style="margin-bottom: 10px;font-size: 16px;">课程目标</h4> <h4 style="margin-bottom: 10px;font-size: 16px;">课程目标</h4>
<p>{{ teachingObjectives }}</p> <div v-html="teachingObjectives"></div>
</el-card> </el-card>
</template> </template>
<template v-if="active === 2"> <template v-if="active === 2">
@ -252,7 +252,10 @@ export default {
return { return {
editorConfig, editorConfig,
courseId: this.$route.query.courseId, courseId: this.$route.query.courseId,
mallId: this.$route.query.mallId,
curriculumName: this.$route.query.curriculumName, curriculumName: this.$route.query.curriculumName,
chapter: this.$route.query.chapter,
section: this.$route.query.section,
type: 1, type: 1,
video: "http://liuwanr.oss-cn-shenzhen.aliyuncs.com/mp4/20200519/1589871025648.mp4", video: "http://liuwanr.oss-cn-shenzhen.aliyuncs.com/mp4/20200519/1589871025648.mp4",
chapterList: [], // chapterList: [], //
@ -309,6 +312,7 @@ export default {
} }
], ],
schedule: 0, schedule: 0,
plan: '',
noteKeyword: '', noteKeyword: '',
searchTimer: null, searchTimer: null,
notes: [], notes: [],
@ -358,22 +362,22 @@ export default {
mounted() { mounted() {
this.insertScript(); this.insertScript();
this.getData(); this.getData();
this.getStatus()
this.addRecord() this.addRecord()
this.getNote() this.getNote()
}, },
methods: { methods: {
goBack() { goBack() {
this.$router.push('/station') this.$router.back()
}, },
async getData() { async getData() {
let { data } = await this.$post(`${this.api.curriculumDetail}?cid=${this.courseId}`); let { data } = await this.$post(`${this.api.curriculumDetail}?cid=${this.courseId}&mallId=${this.mallId}`);
this.courseName = data.curriculumName; this.courseName = data.curriculumName;
// this.coverUrl = data.coverUrl; // this.coverUrl = data.coverUrl;
this.briefIntroduction = data.briefIntroduction; this.briefIntroduction = data.briefIntroduction;
this.teachingObjectives = data.teachingObjectives; this.teachingObjectives = data.teachingObjectives;
this.assessmentList = data.assessmentConfig; this.assessmentList = data.assessmentConfig;
this.systemIds = data.systemIds this.systemIds = data.systemIds
this.getStatus()
}, },
// 使 // 使
addRecord() { addRecord() {
@ -394,16 +398,25 @@ export default {
async getChapter() { async getChapter() {
let res = await this.$get(`${this.api.curriculumChapter}/${this.courseId}`); let res = await this.$get(`${this.api.curriculumChapter}/${this.courseId}`);
this.chapterList = res.chapterList; this.chapterList = res.chapterList;
if (this.chapterList.length && this.chapterList[0].subsectionList && this.chapterList[0].subsectionList.length) { console.log(11, this.chapter)
this.preview(this.chapterList[0].subsectionList[0], this.chapterList[0].name, 1); const chapter = this.chapter === undefined ? 0 : +this.chapter
const section = this.section === undefined ? 0 : +this.section
const clist = this.chapterList[chapter]
if (this.chapterList.length && clist.subsectionList && clist.subsectionList.length) {
this.preview(clist.subsectionList[section], clist.name, 1);
} }
}, },
// //
async getProgress() { async getProgress() {
let res = await this.$post(`${this.api.courseLearningProgress}?courseId=${this.courseId}`); let res = await this.$post(`${this.api.courseLearningProgress}?courseId=${this.courseId}&systemId=${this.systemIds}`);
this.progressList = res.list this.progressList = res.list
this.plan = res.plan
this.schedule = +(res.schedule.replace('%', '')) this.schedule = +(res.schedule.replace('%', ''))
}, },
//
percentFormat(val) {
return this.plan
},
// //
typeChange(id) { typeChange(id) {
this.getChapter() this.getChapter()
@ -791,11 +804,10 @@ $height: 700px;
} }
.pro-title { .pro-title {
margin-bottom: 5px; margin-bottom: 5px;
color: #fff; font-size: 14px;
font-size: 12px;
} }
/deep/.el-progress-bar { /deep/.el-progress-bar {
width: 92%; width: 86%;
} }
.desc-wrap{ .desc-wrap{
position: relative; position: relative;
@ -866,7 +878,7 @@ $height: 700px;
.icon { .icon {
position: absolute; position: absolute;
right: 0; right: 0;
font-size: 14px; font-size: 16px;
color: #00c935; color: #00c935;
} }
.circle { .circle {

@ -6,32 +6,31 @@ const pre = "activity-";
export default { export default {
path: "/activity", path: "/activity",
name: "activity",
redirect: { redirect: {
name: `${pre}list` path: `/activity/list`
}, },
meta, meta,
component: BasicLayout, component: BasicLayout,
children: [ children: [
{ {
name: `${pre}list`,
path: `list`, path: `list`,
component: () => import("@/pages/activity/list"), component: () => import("@/pages/activity/list"),
}, },
{ {
name: `${pre}add`,
path: `add`, path: `add`,
component: () => import("@/pages/activity/add"), component: () => import("@/pages/activity/add"),
}, },
{ {
name: `${pre}manage`,
path: `manage`, path: `manage`,
component: () => import("@/pages/activity/manage"), component: () => import("@/pages/activity/manage"),
}, },
{ {
name: `${pre}noticeDetail`,
path: `noticeDetail`, path: `noticeDetail`,
component: () => import("@/pages/activity/manage/noticeDetail"), component: () => import("@/pages/activity/manage/noticeDetail"),
}, },
{
path: `preview`,
component: () => import("@/pages/activity/preview"),
},
] ]
}; };

@ -26,7 +26,7 @@ if (isPro) {
uploadURL = `http://121.37.12.51/` uploadURL = `http://121.37.12.51/`
host = "http://121.37.12.51/"; // 中台测试服 host = "http://121.37.12.51/"; // 中台测试服
// host = 'https://www.occupationlab.com/' // 正式服 // host = 'https://www.occupationlab.com/' // 正式服
host = "http://192.168.31.151:9000/"; // 榕 // host = "http://192.168.31.151:9000/"; // 榕
// host = 'http://192.168.31.52:9000/'; // 赓 // host = 'http://192.168.31.52:9000/'; // 赓
} }
@ -87,7 +87,7 @@ const Setting = {
// 相同路由,不同参数间进行切换,是否强力更新 // 相同路由,不同参数间进行切换,是否强力更新
sameRouteForceUpdate: false, sameRouteForceUpdate: false,
// 是否使用动态路由(即角色权限,开启了的话就会取后端返回的权限树来显示头部导肮和页面按钮) // 是否使用动态路由(即角色权限,开启了的话就会取后端返回的权限树来显示头部导肮和页面按钮)
dynamicRoute: false, dynamicRoute: true,
// 文件上传 // 文件上传
upload: { upload: {
apiURL: uploadURL, apiURL: uploadURL,

@ -342,10 +342,6 @@
} }
} }
.el-tooltip__popper {
width: 300px;
}
@media(max-width: 1600px) { @media(max-width: 1600px) {
.el-table { .el-table {
.el-switch__label--right.is-active { .el-switch__label--right.is-active {
@ -362,13 +358,13 @@
font-size: 12px; font-size: 12px;
} }
.el-tooltip__popper.is-dark { .el-tooltip__popper.is-dark {
padding: 18px 20px; padding: 10px;
color: #606266; color: #606266;
line-height: 1.8; line-height: 1.8;
background-color: #fff; background-color: #fff;
border: .0625rem solid #ebeef5; border: .0625rem solid #ebeef5;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.2);
border-radius: 4px; border-radius: 8px;
} }
.el-tooltip__popper[x-placement^="top"] { .el-tooltip__popper[x-placement^="top"] {
.popper__arrow { .popper__arrow {

Loading…
Cancel
Save