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. 326
      src/pages/activity/preview/index.vue
  15. 18
      src/pages/match/manage/index.vue
  16. 149
      src/pages/product/list/index.vue
  17. 223
      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`,
excelExportApplicant: `${host}occupationlab/occupationlab/activity/applicant/excelExport`,
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`,

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

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

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

@ -27,7 +27,6 @@ import notice from "./notice";
import MatchSignup from "./matchSignup";
import { mapState } from "vuex";
export default {
name: "matchManage",
data() {
return {
name: this.$route.query.name,
@ -54,29 +53,24 @@ export default {
'btns'
])
},
mounted() {
Setting.dynamicRoute && this.initTabs()
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()
}
},
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:管理:报名人员')
mounted() {
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')
},
methods: {
back() {
this.handleSave(0) && this.backPage()
},
@ -85,11 +79,11 @@ export default {
//
if (this.active === 'tab1') {
const detail = this.$refs.detail
if (detail.step < 4 && detail.$refs['step' + detail.step].updateTime) {
if (detail && detail.updateTime) {
this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示', {
type: 'warning'
}).then(() => {
detail.save(1, 1)
detail.save(detail.form.publishStatus)
this.backOrTab(i)
}).catch(() => {
this.backOrTab(i)

@ -26,13 +26,13 @@
</el-table-column>
<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)" 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 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>
</el-table-column>
</el-table>
<div class="plus" @click="addData" v-auth="'/activity/list:管理:竞赛进展:新增'">
<div class="plus" @click="addData">
<i class="el-icon-circle-plus-outline"></i>
</div>
</div>
@ -77,10 +77,10 @@ export default {
row.operate = true
},
getData() {
this.$get(this.api.getCompetitionProgress, {
competitionId: this.id
this.$get(this.api.listActivityProgress, {
activityId: this.id
}).then(res => {
this.listData = res.competitionProgressList;
this.listData = res.activityProgressList;
for(let index=0; index<this.listData.length; index++) {
//
this.$set(this.listData, index, { operate: false, ...this.listData[index]})
@ -93,14 +93,14 @@ export default {
let data = row;
if (data.title.length) {
if (row.id) {
this.$put(this.api.editCompetitionProgress, data).then(res => {
this.$post(this.api.updateActivityProgress, data).then(res => {
this.touchTime = this.touchTime-1
util.successMsg("修改成功");
this.getData();
}).catch(res => {
});
} else {
this.$post(this.api.addCompetitionProgress, data).then(res => {
this.$post(this.api.addActivityProgress, data).then(res => {
this.touchTime = this.touchTime-1
util.successMsg("创建成功");
this.getData();
@ -114,10 +114,6 @@ export default {
handleSelectionChange(val) {
this.multipleSelection = val;
},
onSearch() {
this.pageNo = 1;
this.getData();
},
handleCurrentChange(val) {
this.pageNo = val;
this.getData();
@ -131,7 +127,7 @@ export default {
util.successMsg("删除成功");
}else {
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("删除成功");
this.getData();
}).catch(res => {
@ -147,7 +143,7 @@ export default {
if (this.listData.length) {
if (this.listData[this.listData.length - 1].id) {
this.listData.push({
competitionId: this.id,
activityId: this.id,
id: "",
title: "",
description: "",
@ -160,7 +156,7 @@ export default {
}
} else {
this.listData.push({
competitionId: this.id,
activityId: this.id,
id: "",
title: "",
description: "",

@ -8,14 +8,14 @@
<el-input placeholder="请输入姓名/手机号/学号" prefix-icon="el-icon-search" v-model="keyword" clearable size="mini" style="width: 250px"></el-input>
</li>
<li>
<label>参赛人员状态</label>
<label>报名人员状态</label>
<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-select>
</li>
</ul>
<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>
@ -37,7 +37,6 @@
<el-table-column label="操作" align="center" width="320">
<template slot-scope="scope">
<el-switch
v-auth="'/activity/list:管理:报名人员:禁用'"
v-model="scope.row.isDisable"
:active-text="scope.row.isDisable ? '关' : '开'"
:active-value="0"

@ -2,7 +2,7 @@
<!-- 报名人员 -->
<div class="page-content" style="padding: 24px">
<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>
<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 label="操作" align="center" width="250">
<template slot-scope="scope">
<el-button type="text" @click="edit(scope.row)" v-auth="'/activity/list:管理:公告通知:编辑'">编辑</el-button>
<el-button type="text" @click="del(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)">删除</el-button>
<el-switch
v-auth="'/activity/list:管理:公告通知:启用'"
v-model="scope.row.isOpen"
:active-text="scope.row.isOpen ? '关' : '开'"
:active-value="0"
@ -76,7 +75,7 @@ export default {
},
methods: {
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.totals = data.total
this.$refs.table.clearSelection()
@ -94,7 +93,7 @@ export default {
type: "warning"
})
.then(() => {
this.$post(`${this.api.deleteAnnouncement}?id=${row.id}`).then(res => {
this.$post(`${this.api.delActivityAnnouncement}?id=${row.id}`).then(res => {
util.successMsg("删除成功");
this.getData();
}).catch(res => {
@ -105,13 +104,13 @@ export default {
},
switchOff(val, row, index) {
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) {
this.$confirm('是否发布该公告?', '提示', {
type: 'success'
}).then(() => {
this.$put(`${this.api.disableAnnouncement}?id=${row.id}&isDisable=${val}`).then(res => {
this.$post(this.api.amendmentAnnouncement, {
this.$put(`${this.api.disableActivityAnnouncement}?id=${row.id}&isDisable=${val}`).then(res => {
this.$post(this.api.updateActivityAnnouncement, {
id: row.id,
status: 1
}).then(res => {
@ -122,14 +121,14 @@ export default {
row.isOpen = 1
})
} 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() {
this.$router.push(`noticeDetail?competitionId=${this.id}`)
this.$router.push(`noticeDetail?activityId=${this.id}`)
},
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-form-item>
<el-form-item>
<el-button v-if="!form.id" @click="save(0)" v-auth="'/activity/list:管理:公告通知:草稿'">草稿</el-button>
<el-button type="primary" @click="save(1)" v-auth="'/activity/list:管理:公告通知:发布'">发布</el-button>
<el-button v-if="!form.id" @click="save(0)">草稿</el-button>
<el-button type="primary" @click="save(1)">发布</el-button>
<el-button @click="back">取消</el-button>
</el-form-item>
</el-form>
@ -61,7 +61,7 @@ export default {
},
form: {
id: this.$route.query.id,
competitionId: this.$route.query.competitionId,
activityId: this.$route.query.activityId,
announcementText: '',
announcementTitle: '',
announcementAnnexList: [],
@ -80,7 +80,6 @@ export default {
form: {
handler(){
this.updateTime++
if(this.updateTime > 1) this.$store.commit('activity/setWait', 0)
},
deep:true
},
@ -90,7 +89,7 @@ export default {
},
methods: {
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
//
const fileList = data.announcementAnnexList
@ -117,13 +116,13 @@ export default {
if (form.id) {
form.isOpen = 0
delete form.announcementAnnexList
this.$post(this.api.amendmentAnnouncement, form).then(res => {
this.$post(this.api.updateActivityAnnouncement, form).then(res => {
util.successMsg("修改成功")
this.$router.back()
}).catch(err => {})
} else {
form.isOpen = status ? 0 : 1
this.$post(this.api.addAnnouncement, form).then(res => {
this.$post(this.api.addActivityAnnouncement, form).then(res => {
util.successMsg("创建成功")
this.$router.back()
}).catch(err => {})
@ -143,7 +142,7 @@ export default {
}
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) {
@ -163,7 +162,7 @@ export default {
if (file.url) {
this.$del(`${this.api.fileDeletion}?keys=${file.url}`).then(res => {}).catch(res => {})
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() {

@ -1,75 +1,37 @@
<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="center">
<breadcrumb ref="breadcrumb" :data="'全部赛事/' + form.name" route="matchPreview"></breadcrumb>
<div class="activity-inner">
<div class="flex-between">
<div class="center-con">
<div class="center-wrap">
<breadcrumb ref="breadcrumb" :data="'全部项目/' + form.projectName"></breadcrumb>
<div class="content">
<div class="tool flex-between">
<el-tabs v-model="curType" @tab-click="typeChange">
<el-tab-pane v-for="(item, index) in typeList" :key="index" :label="item.name" :name="item.id"></el-tab-pane>
</el-tabs>
<div class="status wait">等待报名</div>
</div>
<div class="info">
<h6 class="title">{{ form.name }}</h6>
<h6 class="title">{{ form.projectName }}</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">
<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>
<template v-if="form.activityFileList">
<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>
<li v-for="(item, i) in form.activityFileList" :key="i">
<el-link v-if="item.canPreview" class="m-r-10" type="primary" @click="preview(item)">{{ item.fileName }}</el-link>
<span v-else class="fileName">{{ 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>
</template>
<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>
<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>
@ -107,35 +69,35 @@
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import util from "@/libs/util";
import breadcrumb from '@/components/breadcrumb'
import Const from '@/const/activity'
import util from '@/libs/util'
import Setting from "@/setting"
export default {
data() {
return {
rules: Const.rules,
methods: Const.methods,
teamCalculationMethods: Const.teamCalculationMethods,
form: util.local.get('activity'),
curType: '1',
typeList: [
{
id: '1',
name: '竞赛信息'
name: '项目信息'
},
{
id: '2',
name: '竞赛进展'
name: '项目进展'
},
{
id: '3',
name: '通知公告'
}
},
],
form: util.local.get('activity'),
progress: [],
timer: null,
notices: [],
};
},
@ -143,34 +105,22 @@ export default {
breadcrumb
},
mounted() {
this.handleAnnex()
if (this.form.id) {
this.getProgress()
this.getNotice()
}
},
methods: {
//
handleAnnex() {
const list = this.form.competitionAnnexList
if (list) {
list.map(e => {
const { filePath } = e
e.canPreview = util.canPreview(filePath.substr(filePath.lastIndexOf('.') + 1)) //
})
this.$forceUpdate()
}
},
getProgress() { //
this.$get(this.api.getCompetitionProgress, {
competitionId: this.form.id
getProgress() { //
this.$get(this.api.listActivityProgress, {
activityId: this.form.id
}).then(res => {
this.progress = res.competitionProgressList.reverse()
this.progress = res.activityProgressList.reverse()
}).catch(err => {});
},
//
getNotice() {
this.$post(`${this.api.queryAnnouncementByCompetitionId}?pageNum=1&pageSize=1000&competitionId=${this.form.id}`).then(({ data }) => {
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
records.map(e => {
e.announcementText = e.announcementText.replace(/<img.*?(?:>|\/>)/gi, '')
@ -179,10 +129,10 @@ export default {
}).catch(res => {})
},
//
previewFile(item) {
preview(item) {
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)
window.open((util.isDoc(suffix) ? 'https://view.officeapps.live.com/op/view.aspx?src=' : '') + item.filePath)
},
//
download(item) {
@ -190,56 +140,84 @@ export default {
},
// tab
typeChange() {
document.querySelector(`#part${this.curType}`).scrollIntoView()
document.querySelector(`#part${type}`).scrollIntoView()
},
}
};
</script>
<style lang="scss" scoped>
.activity {
padding-bottom: 20px;
background-color: #F3F6FA;
.banner{
.wrap {
margin: -24px;
}
.banner{
width: 100%;
height: 350px;
padding: 120px 0 0 20%;
color: #fff;
background-size: 100% 350px;
background-repeat: no-repeat;
box-sizing: border-box;
}
.center {
}
.l-title {
font-size: 18px;
}
.main .center-con {
width: 1000px;
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);
padding: 30px 40px 20px;
}
/deep/.el-tabs__item {
box-shadow: none !important;
}
.content{
position: relative;
padding: 20px 40px;
margin-top: 30px;
background-color: #fff;
box-sizing: border-box;
}
/deep/.el-tabs {
.el-tabs__item.is-active, .el-tabs__item:hover {
color: #007EFF;
}
.el-tabs__active-bar {
background-color: #007EFF;
.title{
width: 67%;
margin: 0 auto;
font-size: 28px;
text-align: center;
color: #0B1D30;
}
.tool {
z-index: 100;
position: sticky;
top: 64px;
margin-bottom: 20px;
background-color: #fff;
}
.p-title {
border-left-color: #007EFF;
.info .meta{
padding: 16px 0;
font-size: 12px;
color: #999;
text-align: center;
}
.l-title{
display: flex;
.action {
display: inline-flex;
align-items: center;
margin-bottom: 12px;
font-size: 18px;
color: #333;
img{
margin-right: 5px;
}
}
.status {
max-width: 120px;
padding: 0 16px;
margin-left: 20px;
line-height: 34px;
@ -248,34 +226,33 @@ export default {
background-color: #52C41A;
border-radius: 4px;
cursor: pointer;
@include ellipsis();
&.wait {
background-color: #FAAD14;
}
&.signing {
background-color: #007EFF;
background-color: $main-color;
}
&.signed {
background-color: #52C41A;
}
&.playing {
background-color: #f96d6d;
}
&.finish {
background-color: #ccc;
}
}
.title{
width: 67%;
margin: 0 auto;
font-size: 28px;
text-align: center;
color: #0B1D30;
}
.info .meta{
padding: 16px 0;
.end-text {
font-size: 12px;
color: #999;
text-align: center;
color: #666;
em {
font-style: normal;
color: #f00;
}
.texts {
margin-bottom: 30px;
}
.texts{
margin: 20px 0 50px;
font-size: 14px;
line-height: 1.6;
text-indent: 2em;
@ -284,26 +261,7 @@ export default {
max-width: 100%;
}
}
.files {
margin-bottom: 30px;
li {
display: flex;
align-items: center;
margin: 10px 0;
}
.file-name {
margin-right: 10px;
font-size: 12px;
}
}
.el-link.el-link--primary {
color: #007EFF !important;
&:after {
border-color: #007EFF;
}
}
}
.progress{
.progress{
position: relative;
width: 95%;
padding: 50px 0;
@ -381,7 +339,7 @@ export default {
&.ing {
.dot {
left: auto;
right: -58px;
right: -51px;
}
}
.name {
@ -459,6 +417,19 @@ export default {
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 {
text-align: left;
@ -501,33 +472,56 @@ export default {
text-overflow: ellipsis;
}
}
.empty{
display: flex;
justify-content: center;
align-items: center;
padding: 50px 0;
.table {
width: 100%;
border-collapse: collapse;
th, td {
padding: 12px;
border: 1px solid #ebeef5;
}
&.tc {
text-align: center;
img{
width: 471px;
}
p{
margin-top: 40px;
font-size: 18px;
color: rgba(0, 0, 0, 0.25);
th {
text-align: center;
background-color: #f8faff;
}
}
.rule-title {
margin-bottom: 10px;
.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 {
padding: 15px;
.flex-center {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
border: 1px solid #dfdfdf;
p {
font-size: 14px;
line-height: 30px;
color: #6e6e6e;
}
/deep/.dia-form {
.w-100 {
width: 100%;
}
.tips {
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

@ -62,8 +62,10 @@ export default {
Setting.dynamicRoute && this.initTabs()
},
beforeRouteLeave(to, from, next) {
const detail = this.$refs.detail
if (detail.step < 4 && detail.$refs['step' + detail.step].updateTime) {
const { detail } = this.$refs
if (detail) {
const step = detail.$refs['step' + detail.step]
if (detail.step < 4 && step && step.updateTime) {
this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示.......', {
type: 'warning'
}).then(() => {
@ -74,6 +76,9 @@ export default {
} else {
next()
}
} else {
next()
}
},
methods: {
initTabs() {
@ -105,8 +110,10 @@ export default {
handleSave(i) {
//
if (this.active === 'tab1') {
const detail = this.$refs.detail
if (detail.step < 4 && detail.$refs['step' + detail.step].updateTime) {
const { detail } = this.$refs
if (detail) {
const step = detail.$refs['step' + detail.step]
if (detail.step < 4 && step && step.updateTime) {
this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示', {
type: 'warning'
}).then(() => {
@ -118,6 +125,9 @@ export default {
} else {
this.backOrTab(i)
}
} else {
this.backOrTab(i)
}
return false
} else {
return true

@ -1,10 +1,10 @@
<template>
<div class="wrap">
<el-carousel :interval="6000">
<el-carousel :interval="6000" :height="carouselHeight">
<template v-for="(item, i) in banners">
<el-carousel-item :key="i">
<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>
</div>
</el-carousel-item>
@ -26,26 +26,40 @@
</div>
</div>
<div class="filter">
<dl>
<dl v-if="curTab == 1">
<dt>学科专业</dt>
<dd>学科类别</dd>
<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-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-option label="不限" value=""></el-option>
<el-option v-for="(item,index) in professionalClassList" :key="index" :label="item.professionalClassName" :value="item.professionalClassId"></el-option>
</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-option label="不限" value=""></el-option>
<el-option v-for="(item,index) in professionalList" :key="index" :label="item.professionalName" :value="item.professionalId"></el-option>
</el-select>
</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>
<dt>产品类型</dt>
<div class="vals">
<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>
<dt>购买状态</dt>
@ -56,6 +70,11 @@
<div class="filter m-t-20">
<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 :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>
</div>
@ -66,37 +85,31 @@
<img :src="item.coverDrawing" alt="" />
<img v-if="item.logoOfOurSchool" class="my-school" src="@/assets/img/my-school.png" alt="">
<div class="texts">
<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="metas">
<template v-if="curTab === 2">
<div class="tags">
<el-tooltip v-if="item.tagsName" class="item" effect="dark" :visible-arrow="false" :content="item.tagsName" placement="bottom">
<div>
<el-tag v-for="(tag, i) in item.tagsName.split(',')" :key="i" class="tag">{{ tag }}</el-tag>
</div>
</el-tooltip>
</div>
<div :class="['metas', {'not-selected': !item.selected}]">
<el-tag
v-if="item.selected"
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>
</div>
<template v-if="!curTab || curTab === 1">
<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 v-if="item.isCourse" class="meta">{{ item.learningCount }}人学过</div>
</div>
</div>
</li>
</ul>
<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>
</template>
</div>
@ -110,6 +123,7 @@ import Setting from "@/setting";
export default {
data() {
return {
carouselHeight: '336px',
banners: [],
timer: null,
curTab: '',
@ -133,6 +147,7 @@ export default {
],
form: {
categoryId: '',
isShelves: 0,
hotTag: 1,
professionalCategoryId: '',
professionalId: '',
@ -140,7 +155,9 @@ export default {
productName: '',
purchaseStatus: '',
sort: 0,
tagId: ''
},
labels: [],
subjectList: [], //
professionalClassList: [], //
professionalList: [], //
@ -168,10 +185,6 @@ export default {
id: 1,
name: '热销排行'
},
{
id: 2,
name: '发布时间'
},
],
list: [
{
@ -190,7 +203,7 @@ export default {
keyword: '',
total: 0,
page: 1,
pageSize: 10,
pageSize: 12,
searchTimer: null,
loadIns: null
};
@ -204,8 +217,11 @@ export default {
}
},
mounted() {
console.log(11, parseInt(window.innerWidth / 5.7))
this.carouselHeight = parseInt(window.innerWidth / 5.7) + 'px'
this.getBanner()
this.getSubject()
this.getLabel()
this.getClass()
this.initData()
},
@ -214,7 +230,8 @@ export default {
getBanner() {
this.$post(this.api.listMarketing, {
pageNum: 1,
pageSize: 1000
pageSize: 1000,
isOpen: 0
}).then(({ page }) => {
this.banners = page.records
}).catch(res => {})
@ -227,7 +244,16 @@ export default {
pageNum: this.page,
pageSize: this.pageSize,
}).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.loadIns.close()
}).catch(res => {
@ -239,6 +265,12 @@ export default {
this.getData();
},
//
getLabel() {
this.$get(this.api.tagsList).then(res => {
this.labels = res.tagsList
}).catch(err => {})
},
//
getSubject() {
this.$get(this.api.courseDiscipline).then(res => {
@ -318,6 +350,11 @@ export default {
this.form[prop] = id
this.initData()
},
//
sort() {
this.form.sort = this.form.sort === 2 ? 5 : 2
this.initData()
},
handleCurrentChange(val) {
this.page = val;
this.getData();
@ -337,7 +374,7 @@ export default {
position: relative;
img {
width: 100%;
height: 336px;
height: 100%;
}
.banner-name {
position: absolute;
@ -405,11 +442,13 @@ export default {
background-color: #fff;
border-radius: 10px;
dl {
position: relative;
display: flex;
align-items: center;
flex-wrap: wrap;
margin: 20px 0;
dt {
min-width: 60px;
padding: 5px 0;
margin-right: 30px;
color: #666;
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 {
position: relative;
@ -484,11 +556,11 @@ export default {
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
&.ie {
height: 80px;
text-overflow: ellipsis;
white-space: nowrap;
}
.tags {
height: 24px;
margin-top: 10px;
overflow: hidden;
}
.tag {
margin-right: 8px;
@ -509,6 +581,9 @@ export default {
justify-content: space-between;
align-items: center;
margin-top: 10px;
&.not-selected {
justify-content: flex-end;
}
}
.meta {
display: inline-flex;

@ -7,19 +7,20 @@
</div>
<div class="right">
<h6>{{ form.mall.productName }}</h6>
<div class="meta">
<span class="val">48</span> 个实验项目&emsp;&emsp;已有 <span class="val">{{ form.goodsRes.learningCount }}</span>人学过
<div v-if="isCourse" class="meta">
<span class="val">{{ form.numberOfExperimentalItems }}</span> 个实验项目&emsp;&emsp;
已有 <span class="val">{{ form.goodsRes.learningCount }}</span>人学过
</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 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.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>
<button v-if="form.goodsRes.logoOfOurSchool" class="btn" @click="toTrail">试用体验</button>
<button v-else class="btn entry" @click="toStation">进入实验</button>
<button v-if="!form.goodsRes.logoOfOurSchool" class="btn" @click="toTrail">试用体验</button>
<button v-else-if="isCourse || withLink" class="btn entry" @click="toStation">进入实验</button>
</div>
</div>
<div class="course">
@ -29,26 +30,27 @@
</ul>
<div class="courses">
<template v-if="!curTab">
<h6>课程介绍</h6>
<div class="des" v-html="form.mall.detailedIntroduction"></div>
</template>
<template v-else>
<div v-for="(item, i) in chapterList" :key="i">
<h6>{{ item.name }}</h6>
<ul v-if="item.subsectionList.length" class="list">
<li v-for="(section, i) in item.subsectionList" :key="i" @click="toPreview(item, section)">
<p class="name">
<div class="chapter" v-for="(item, i) in chapterList" :key="i">
<div class="chapterName">{{ item.name }}</div>
<div class="section" v-if="item.subsectionList.length">
<div v-for="(section, j) in item.subsectionList" :key="j" @click="toPreview(i, j)">
<div class="sectionName" :title="section.name" :class="{active: curLink === `${item.name}${section.name}`}">
<div class="val">
<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 === '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.projectName }}
</p>
<i :class="['status', section.whetherToStudyOrNot ? 'el-icon-success' : 'circle']" @click.stop="studySection(item, section)"></i>
</li>
</ul>
{{ section.name }}
</div>
<i v-if="!form.goodsRes.logoOfOurSchool" class="icon el-icon-lock"></i>
</div>
</div>
</div>
</div>
</template>
</div>
@ -61,28 +63,18 @@
<img v-if="item.logoOfOurSchool" class="my-school" src="@/assets/img/my-school.png" alt="">
<div class="texts">
<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">
<template v-if="item.selected">
<el-tag
v-if="item.selected"
type="danger"
effect="dark">
官方精选
</el-tag>
<div 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 v-if="item.isCourse" class="meta">{{ item.learningCount }}人学过</div>
</div>
</div>
</li>
@ -90,6 +82,16 @@
</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>
</template>
@ -106,19 +108,44 @@ export default {
id: 0,
name: '详情介绍'
},
{
id: 1,
name: '课程目录'
},
],
form: {
classificationIds: [],
mall: {},
goodsRes: {}
},
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() {
this.getData()
this.getHot()
@ -128,37 +155,40 @@ export default {
getData() {
this.$get(`${this.api.detailsOfGoods}?mallId=${this.id}`).then(res => {
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.getChapter()
this.chapterList = ''
e.mall.associatedProduct && this.getChapter()
}).catch(err => {})
},
//
async getChapter() {
let res = await this.$post(`${this.api.courseLearningProgress}?courseId=${this.form.mall.associatedProduct}`)
this.chapterList = res.list
let res = await this.$get(this.api.curriculumChapter + '/' + this.form.mall.associatedProduct)
this.chapterList = res.chapterList
},
// tab
tabChange({ id }) {
this.curTab = id
},
//
toPreview(item, section) {
toPreview(i, j) {
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()
},
// /
studySection(item) {
item.whetherToStudyOrNot ?
this.$post(`${this.api.deleteLearningProgress}?id=${item.learningProgressId}`).then(res => {
this.getProgress()
this.getChapter()
}).catch(res => {}) :
this.$post(this.api.saveLearningProgress, {
cid: this.courseId,
cid: this.form.mall.associatedProduct,
projectId: item.projectId,
}).then(res => {
this.getProgress()
this.getChapter()
}).catch(res => {})
},
//
@ -167,9 +197,13 @@ export default {
},
//
toStation() {
if (this.isCourse) { //
this.$post(`${this.api.addLearningRecord}?mallId=${this.id}`).then(res => {
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)
}).catch(res => {})
} else if (this.withLink) { //
this.linkVisible = true
}
},
//
getHot() {
@ -179,12 +213,23 @@ export default {
pageNum: 1,
pageSize: 2,
}).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 => {})
},
//
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 {
width: 646px;
overflow: hidden;
}
h6 {
font-size: 24px;
@ -251,12 +297,11 @@ export default {
}
.fields {
display: flex;
margin: 10px 0 20px;
justify-content: space-between;
flex-wrap: wrap;
margin: 10px 0 10px;
.field {
margin-right: 50px;
&:last-child {
margin-right: 0;
}
margin-bottom: 10px;
}
}
.btn {
@ -280,6 +325,7 @@ export default {
}
.tab {
display: inline-flex;
margin-left: 10px;
li {
position: relative;
margin-right: 20px;
@ -306,7 +352,7 @@ export default {
margin-top: 20px;
.detail {
width: 835px;
padding: 20px 36px;
padding: 20px 24px;
background-color: #fff;
border-radius: 10px;
@ -314,48 +360,49 @@ export default {
}
.courses {
margin-top: 40px;
h6 {
.chapters{
margin-top: 16px;
max-height: calc(100% - 53px);
overflow: auto;
}
.chapter{
margin-bottom: 20px;
font-size: 14px;
}
.chapterName{
padding: 0 12px;
margin-bottom: 15px;
color: #333;
font-size: 14px;
}
.list {
height: calc(100vh - 530px);
padding-right: 15px;
overflow: auto;
li {
.sectionName{
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
height: 46px;
padding: 12px;
font-size: 14px;
color: #666;
cursor: pointer;
border-radius: 8px;
@include ellipsis;
img {
margin-right: 8px;
}
&:hover {
color: #007EFF;
background: #F6FBFF;
}
}
.name {
.val {
display: inline-flex;
align-items: center;
font-size: 14px;
color: #333;
img {
margin-right: 8px;
}
}
.status {
.icon {
font-size: 18px;
color: #00c935;
}
.circle {
width: 18px;
height: 18px;
border-radius: 50%;
border: 1px solid #ccc;
color: #666;
}
}
}
.products {
width: 270px;
width: 295px;
margin-left: 24px;
&>h6 {
font-size: 14px;
@ -406,12 +453,13 @@ export default {
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
&.ie {
height: 80px;
text-overflow: ellipsis;
white-space: nowrap;
&.not-tag {
-webkit-line-clamp: 3;
}
}
.tags {
margin-top: 10px;
}
.tag {
margin-right: 8px;
color: #007EFF;
@ -452,4 +500,11 @@ export default {
}
}
}
.link-line {
margin: 5px 0;
.url {
color: #007EFF;
text-decoration: underline;
}
}
</style>

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

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

@ -76,7 +76,7 @@ export default {
});
},
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
tabChange(item) {

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

@ -6,32 +6,31 @@ const pre = "activity-";
export default {
path: "/activity",
name: "activity",
redirect: {
name: `${pre}list`
path: `/activity/list`
},
meta,
component: BasicLayout,
children: [
{
name: `${pre}list`,
path: `list`,
component: () => import("@/pages/activity/list"),
},
{
name: `${pre}add`,
path: `add`,
component: () => import("@/pages/activity/add"),
},
{
name: `${pre}manage`,
path: `manage`,
component: () => import("@/pages/activity/manage"),
},
{
name: `${pre}noticeDetail`,
path: `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/`
host = "http://121.37.12.51/"; // 中台测试服
// 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/'; // 赓
}
@ -87,7 +87,7 @@ const Setting = {
// 相同路由,不同参数间进行切换,是否强力更新
sameRouteForceUpdate: false,
// 是否使用动态路由(即角色权限,开启了的话就会取后端返回的权限树来显示头部导肮和页面按钮)
dynamicRoute: false,
dynamicRoute: true,
// 文件上传
upload: {
apiURL: uploadURL,

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

Loading…
Cancel
Save