提交 9bcd159b authored 作者: 王鹏飞's avatar 王鹏飞

2.0第一版提测

上级 48d63988
差异被折叠。
...@@ -69,19 +69,19 @@ ...@@ -69,19 +69,19 @@
"vconsole-webpack-plugin": "^1.5.2" "vconsole-webpack-plugin": "^1.5.2"
}, },
"dependencies": { "dependencies": {
"axios": "^0.20.0", "axios": "^0.21.1",
"cross-env": "^7.0.2", "cross-env": "^7.0.3",
"element-ui": "^2.14.0", "element-ui": "^2.15.0",
"js-cookie": "^2.2.1", "js-cookie": "^2.2.1",
"lodash": "^4.17.15", "lodash": "^4.17.20",
"vue": "^2.6.12", "vue": "^2.6.12",
"vue-i18n": "^8.16.0", "vue-i18n": "^8.22.4",
"vue-loader": "^15.9.3", "vue-loader": "^15.9.6",
"vue-meta-info": "^0.1.7", "vue-meta-info": "^0.1.7",
"vue-router": "^3.4.3", "vue-router": "^3.4.9",
"vue-template-compiler": "^2.6.12", "vue-template-compiler": "^2.6.12",
"vuex": "^3.5.1", "vuex": "^3.6.0",
"core-js": "^3.6.5" "core-js": "^3.8.3"
}, },
"engines": { "engines": {
"node": ">=8.9" "node": ">=8.9"
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
<div class="app-container"> <div class="app-container">
<div class="app-container-hd" v-if="title"> <div class="app-container-hd" v-if="title">
<div class="app-container-hd__title">{{ title }}</div> <div class="app-container-hd__title">{{ title }}</div>
<div class="app-container-hd__right">
<slot name="header-right"></slot>
</div>
</div> </div>
<div class="app-container-bd"> <div class="app-container-bd">
<slot></slot> <slot></slot>
...@@ -28,6 +31,9 @@ export default { ...@@ -28,6 +31,9 @@ export default {
box-sizing: border-box; box-sizing: border-box;
} }
.app-container-hd { .app-container-hd {
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 8px; padding-bottom: 8px;
margin-bottom: 20px; margin-bottom: 20px;
border-bottom: 1px solid #ccc; border-bottom: 1px solid #ccc;
......
<template> <template>
<div class="course-list" element-loading-text="加载中..." v-loading="!loaded"> <div class="course-list" element-loading-text="加载中..." v-loading="!loaded">
<template v-if="list.length"> <template v-if="currentList.length">
<course-list-item v-for="item in list" :data="item" :key="item.id" v-bind="$attrs" v-on="$listeners" /> <course-list-item v-for="item in currentList" :data="item" :key="item.id" v-bind="$attrs" v-on="$listeners" />
</template> </template>
<template v-else> <template v-else>
<slot name="empty"> <slot name="empty">
...@@ -19,7 +19,8 @@ export default { ...@@ -19,7 +19,8 @@ export default {
name: 'CourseList', name: 'CourseList',
components: { CourseListItem }, components: { CourseListItem },
props: { props: {
requestCallback: Function requestCallback: Function,
searchValue: String
}, },
data() { data() {
return { return {
...@@ -27,10 +28,20 @@ export default { ...@@ -27,10 +28,20 @@ export default {
list: [] list: []
} }
}, },
computed: {
currentList() {
if (!this.searchValue) {
return this.list
}
return this.list.filter(item => {
return item.course_name.includes(this.searchValue)
})
}
},
methods: { methods: {
getCourseList() { getCourseList() {
api api
.getCourseModule() .getCourseList()
.then(response => { .then(response => {
this.list = this.requestCallback ? this.requestCallback(response) : response this.list = this.requestCallback ? this.requestCallback(response) : response
this.$emit('request-success', response) this.$emit('request-success', response)
......
<template> <template>
<div class="course-item"> <div class="course-item">
<div class="course-item-top"> <img class="course-item-pic" :src="data.curriculum.curriculum_picture" @click="$emit('on-click', data)" />
<img class="course-item-pic" :src="data.photo" v-if="data.photo" /> <div class="course-item-content">
<div class="course-item-content"> <div class="course-item__title">{{ data.course_name }}</div>
<div class="course-item__title">{{ data.title }}</div> <div class="course-item__tools">
<div class="course-item__tools"> <div class="course-item__progress">
<div class="course-item__text course-item__text__course">{{ data.course_num }}节课</div> <span>视频观看进度</span>
<div class="course-item__text course-item__text__video">{{ data.video_num }}节视频课</div> <el-progress :percentage="data.video_progress"></el-progress>
<div class="course-item__text course-item__text__freevideo">{{ data.free_video_num }}个免费视频</div> </div>
<div class="course-item__buttons">
<el-button type="primary" size="small" round @click="$emit('on-click', data)">查看课程</el-button>
</div> </div>
</div>
</div>
<div class="course-item-bottom">
<div class="course-child" v-for="item in data.child" :key="item.id" @click="$emit('on-click', item)">
<div class="name">{{ item.course_name }}</div>
<div class="progress" v-if="showProgress">{{ item.video_progress | progressText }}</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -47,13 +43,11 @@ export default { ...@@ -47,13 +43,11 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.course-item { .course-item {
background: #ffffff;
border-radius: 8px;
padding: 30px;
margin-bottom: 20px;
}
.course-item-top {
display: flex; display: flex;
padding: 14px 0;
}
.course-item + .course-item {
border-top: 1px solid #ccc;
} }
.course-item-pic { .course-item-pic {
width: 160px; width: 160px;
...@@ -61,6 +55,7 @@ export default { ...@@ -61,6 +55,7 @@ export default {
margin-right: 20px; margin-right: 20px;
border-radius: 2px; border-radius: 2px;
overflow: hidden; overflow: hidden;
cursor: pointer;
} }
.course-item-content { .course-item-content {
flex: 1; flex: 1;
...@@ -78,40 +73,16 @@ export default { ...@@ -78,40 +73,16 @@ export default {
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
overflow: hidden; overflow: hidden;
} }
.course-item__text { .course-item__tools {
display: inline-block;
font-size: 14px;
}
.course-item__text + .course-item__text {
margin-left: 0.1rem;
}
.course-item__text__course {
color: #88bbff;
}
.course-item__text__video {
color: #5ad0b2;
}
.course-item__text__freevideo {
color: #d05a5a;
}
.course-child {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 20px 0; }
border-bottom: 1px solid #eee; .course-item__progress {
cursor: pointer; display: flex;
&:hover { flex: 1;
color: #c01540; .el-progress {
} margin: 0 10px;
.name { width: 50%;
flex: 1;
font-size: 18px;
}
.progress {
margin-left: 20px;
font-size: 12px;
color: #999;
} }
} }
</style> </style>
...@@ -8,14 +8,24 @@ ...@@ -8,14 +8,24 @@
<span @click="logout">退出登录</span> <span @click="logout">退出登录</span>
</div> </div>
</div> </div>
<ul class="nav"> <el-menu class="nav" :unique-opened="true" :router="true" :default-active="activeLink">
<li v-for="(item, index) in datalist" :key="index" :class="genClasses(item)"> <template v-for="item in datalist">
<router-link :to="item.path"> <el-submenu :index="item.title" :key="item.title" v-if="item.children">
<i class="iconfont" :class="item.icon" v-if="item.icon"></i> <template slot="title">
<span>{{ item.title }}</span> <i class="iconfont" :class="item.icon"></i>
</router-link> <span>{{ item.title }}</span>
</li> </template>
</ul> <el-menu-item :index="item.path" :key="item.title" v-for="item in item.children">
<span slot="title">{{ item.title }}</span>
</el-menu-item>
</el-submenu>
<el-menu-item :index="item.path" :key="item.title" v-else>
<i class="iconfont" :class="item.icon"></i>
<span slot="title">{{ item.title }}</span>
</el-menu-item>
</template>
</el-menu>
</div> </div>
</div> </div>
</template> </template>
...@@ -27,19 +37,49 @@ export default { ...@@ -27,19 +37,49 @@ export default {
name: 'AppAside', name: 'AppAside',
props: { props: {
menus: { type: Array, default: () => [] }, menus: { type: Array, default: () => [] },
showUser: { type: Boolean, default: true } showUser: { type: Boolean, default: false }
}, },
data() { data() {
return { return {
activeLink: '/course/learn',
defaultMenus: [ defaultMenus: [
{ title: '课程学习', icon: 'icon-bianzu6-hong', path: '/course/learn' }, {
{ title: '考前摸底', icon: 'icon-bianzuhong', path: '/testExam' }, title: '我的课程',
// { title: '真题实战', icon: 'icon-kaoshihong', path: '/mock' }, icon: 'icon-bianzu6-hong',
{ title: '错题集合', icon: 'icon-guanlizhongxinbeifen-hong', path: '/my/questions/wrong' }, children: [{ title: '课程学习', path: '/course/learn' }]
{ title: '收藏试题', icon: 'icon-shoucang-hong', path: '/my/questions/collection' }, },
// { title: '必考考点', icon: 'icon-kaozheng-hong', path: '/course/test' }, {
{ title: '意见反馈', icon: 'icon-fankui-hong', path: '/feedback' }, title: '我的考试',
{ title: '联系客服', icon: 'icon-bianzu8-hong', path: '/contact' } icon: 'icon-bianzuhong',
children: [
{ title: '考前摸底', path: '/testExam' },
{ title: '错题集合', path: '/my/questions/wrong' },
{ title: '收藏试题', path: '/my/questions/collection' }
]
},
{
title: '实训练习',
icon: 'icon-kaoshihong',
children: [{ title: '实训案例练习', path: '/xxxx' }]
},
{
title: '个人中心',
icon: 'icon-guanlizhongxinbeifen-hong',
children: [
{ title: '个人信息', path: '/account' },
{ title: '修改密码', path: '/account/password' },
{ title: '安全设置', path: '/account/safe' }
]
},
{
title: '帮助与反馈',
icon: 'icon-bianzu8-hong',
children: [
{ title: '服务专区', path: '/contact' },
{ title: '系统说明', path: '/doc' },
{ title: '常见问题', path: '/help' }
]
}
] ]
} }
}, },
...@@ -57,6 +97,14 @@ export default { ...@@ -57,6 +97,14 @@ export default {
return this.user.avatar || defaultAvatar return this.user.avatar || defaultAvatar
} }
}, },
watch: {
$route: {
immediate: true,
handler(to, from) {
this.activeLink = to.path
}
}
},
methods: { methods: {
genClasses(data) { genClasses(data) {
const isActive = this.$route.fullPath.includes(data.path) const isActive = this.$route.fullPath.includes(data.path)
...@@ -110,28 +158,27 @@ export default { ...@@ -110,28 +158,27 @@ export default {
} }
.nav { .nav {
border: 0;
padding: 30px 0; padding: 30px 0;
li { color: #ccc;
text-align: center; .iconfont {
font-size: 16px; font-size: 16px;
font-weight: 600; color: currentColor;
color: #666; }
a { .el-submenu__title:hover {
display: block; color: #c01540;
padding: 16px 0; }
} .is-active {
&:hover, color: #c01540;
&.is-active { }
color: #c01540; .is-active .el-submenu__title {
background-color: #fff4f7; background: #fff4f7;
.iconfont { color: #c01540;
color: #c01540; }
} .el-menu-item:hover,
} .el-menu-item:focus {
.iconfont { color: #c01540;
margin-right: 4px; background: transparent;
color: #ccc;
}
} }
} }
} }
......
...@@ -5,17 +5,28 @@ ...@@ -5,17 +5,28 @@
</div> </div>
<div class="tool"> <div class="tool">
<!-- <app-search-bar :value="$route.query.keywords" @search="handleSearch" /> --> <!-- <app-search-bar :value="$route.query.keywords" @search="handleSearch" /> -->
<nav class="nav"> <!-- <nav class="nav">
<router-link to="/">首页</router-link> <router-link to="/">首页</router-link>
<router-link to="/my">我的</router-link> <router-link to="/my">我的</router-link>
<!-- <router-link to="/messages">通知</router-link> --> <router-link to="/messages">通知</router-link>
</nav> </nav> -->
<el-dropdown>
<div class="user">
<img :src="avatar" class="user-avatar" />
<span class="user-name">{{ user.realname }}</span>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item icon="el-icon-user" @click.native="$router.push('/account')">个人中心</el-dropdown-item>
<el-dropdown-item icon="el-icon-switch-button" @click.native="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import AppSearchBar from '@/components/AppSearchBar' import AppSearchBar from '@/components/AppSearchBar'
import defaultAvatar from '@/assets/images/avatar.png'
export default { export default {
name: 'AppHeader', name: 'AppHeader',
components: { AppSearchBar }, components: { AppSearchBar },
...@@ -24,15 +35,29 @@ export default { ...@@ -24,15 +35,29 @@ export default {
title: '金融产品数字化营销职业技能等级证书' title: '金融产品数字化营销职业技能等级证书'
} }
}, },
computed: {
user() {
return this.$store.state.user
},
avatar() {
return this.user.avatar || defaultAvatar
}
},
methods: { methods: {
handleSearch(value) { handleSearch(value) {
this.$router.replace({ path: '/search', query: { keywords: value } }) this.$router.replace({ path: '/search', query: { keywords: value } })
},
// 退出登录
logout() {
this.$store.dispatch('logout').then(() => {
window.location.href = webConf.others.loginUrl
})
} }
} }
} }
</script> </script>
<style lang="scss" > <style lang="scss">
.app-header { .app-header {
display: flex; display: flex;
align-items: center; align-items: center;
...@@ -60,5 +85,30 @@ export default { ...@@ -60,5 +85,30 @@ export default {
padding: 0 20px; padding: 0 20px;
} }
} }
.user {
height: 80px;
padding: 0 10px;
display: flex;
align-items: center;
cursor: pointer;
&:hover {
background-color: #fff4f7;
}
}
.user-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.user-name {
padding: 0 10px;
}
} }
</style> </style>
...@@ -13,11 +13,11 @@ ...@@ -13,11 +13,11 @@
id="viewport" id="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, shrink-to-fit=no, viewport-fit=cover" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, shrink-to-fit=no, viewport-fit=cover"
/> />
<link rel="stylesheet" href="https://g.alicdn.com/de/prismplayer/2.9.1/skins/default/aliplayer-min.css" /> <link rel="stylesheet" href="https://g.alicdn.com/de/prismplayer/2.9.3/skins/default/aliplayer-min.css" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2173492_ctgt96uojqw.css" /> <link rel="stylesheet" href="//at.alicdn.com/t/font_2173492_ctgt96uojqw.css" />
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
<script src="https://g.alicdn.com/de/prismplayer/2.9.1/aliplayer-min.js"></script> <script src="https://g.alicdn.com/de/prismplayer/2.9.3/aliplayer-min.js"></script>
</body> </body>
</html> </html>
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<aside-chapter :data="data" :chapters="chapters" :active="active"></aside-chapter> <aside-chapter :data="data" :chapters="chapters" :active="active"></aside-chapter>
</div> </div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="学习资料" name="1" v-if="active && active.type === 2"> <el-tab-pane label="讲义" name="1" v-if="active && active.type === 2">
<div class="tab-pane"> <div class="tab-pane">
<aside-lecture :ppts="ppts" :pptIndex="pptIndex" v-on="$listeners"></aside-lecture> <aside-lecture :ppts="ppts" :pptIndex="pptIndex" v-on="$listeners"></aside-lecture>
</div> </div>
......
<template>
<app-container title="个人信息"> </app-container>
</template>
<script>
import AppContainer from '@/components/AppContainer'
export default {
components: { AppContainer }
}
</script>
...@@ -10,10 +10,12 @@ ...@@ -10,10 +10,12 @@
<el-form-item label="重复新密码" prop="passwordR"> <el-form-item label="重复新密码" prop="passwordR">
<el-input type="password" v-model="ruleForm.passwordR" placeholder="请重复新密码"></el-input> <el-input type="password" v-model="ruleForm.passwordR" placeholder="请重复新密码"></el-input>
</el-form-item> </el-form-item>
<el-form-item>
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">保存</el-button>
</el-form-item>
</el-form> </el-form>
<template #footer>
<div class="app-container-ft">
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">保存</el-button>
</div>
</template>
</app-container> </app-container>
</template> </template>
......
<template>
<app-container title="安全设置">
<el-form :model="ruleForm" :rules="rules" label-width="100px" ref="ruleForm" class="form">
<el-form-item label="手机号码" prop="phone">
<el-input type="password" v-model="ruleForm.phone"></el-input>
</el-form-item>
</el-form>
<template #footer>
<div class="app-container-ft">
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">保存</el-button>
</div>
</template>
</app-container>
</template>
<script>
import AppContainer from '@/components/AppContainer'
import * as api from '@/api/account'
export default {
components: { AppContainer },
data() {
return {
ruleForm: {
phone: ''
},
rules: {
phone: [{ required: true, message: '请输入手机号码', trigger: 'blur' }]
},
submitLoading: false
}
},
methods: {
handleSubmit() {
this.$refs.ruleForm.validate().then(this.handleSubmitRequest)
},
handleSubmitRequest() {
this.submitLoading = true
api
.updatePassword(this.ruleForm)
.then(response => {
this.$message({ message: '密码修改成功', type: 'success' })
// 重置表单
this.$refs.ruleForm.resetFields()
})
.finally(() => {
this.submitLoading = false
})
}
}
}
</script>
<style lang="scss" scoped>
.form {
max-width: 340px;
}
</style>
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
<ul> <ul>
<li v-for="subItem in item.children" :key="subItem.id" @click="handleClick(subItem)"> <li v-for="subItem in item.children" :key="subItem.id" @click="handleClick(subItem)">
<div class="name">{{ subItem.name }}</div> <div class="name">{{ subItem.name }}</div>
<div class="duration">{{ subItem.duration }}</div>
<div class="progress" v-if="showProgress">{{ progressText(subItem.video_progress) }}</div> <div class="progress" v-if="showProgress">{{ progressText(subItem.video_progress) }}</div>
</li> </li>
</ul> </ul>
......
<template>
<div class="teacher">
<div class="teacher-item" v-for="item in data" :key="item.id">
<img :src="item.lecturer_avatar" class="teacher-item-pic" />
<div class="teacher-item-content">
<p class="t1">{{ item.lecturer_name }}</p>
<p class="t2">{{ item.lecturer_education }}</p>
<p class="t2">{{ item.lecturer_title }}</p>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
data: { type: Array, default: () => [] }
}
}
</script>
<style lang="scss" scoped>
.teacher-item {
display: flex;
margin-bottom: 10px;
}
.teacher-item-pic {
width: 90px;
height: 110px;
object-fit: cover;
margin-right: 10px;
}
.teacher-item-content {
flex: 1;
.t1 {
font-weight: bold;
}
.t2 {
margin-top: 5px;
color: #707070;
}
}
</style>
<template> <template>
<course-list @on-click="handleClick" /> <app-container title="课程学习">
<template #header-right>
<div class="search">
<el-input prefix-icon="el-icon-search" clearable v-model="searchValue" @keyup.enter.native="handleSearch" />
<el-button type="text" @click="handleSearch">搜索</el-button>
</div>
</template>
<course-list @on-click="handleClick" :searchValue="searchValue" />
</app-container>
</template> </template>
<script> <script>
import AppContainer from '@/components/AppContainer'
import CourseList from '@/components/CourseList.vue' import CourseList from '@/components/CourseList.vue'
export default { export default {
components: { CourseList }, components: { AppContainer, CourseList },
data() {
return {
searchValue: ''
}
},
methods: { methods: {
handleClick(data) { handleClick(data) {
this.$router.push({ name: 'courseLearnItem', params: { id: data.id } }) this.$router.push({ name: 'courseLearnItem', params: { id: data.course_id } })
} },
// 搜索
handleSearch() {}
} }
} }
</script> </script>
<style lang="scss" scoped>
.search {
display: flex;
width: 300px;
.el-button {
margin-left: 10px;
}
}
</style>
<template> <template>
<div class="main-container" element-loading-text="加载中..." v-loading="!loaded"> <app-container title="课程详情" element-loading-text="加载中..." v-loading="!loaded">
<div class="course-top" v-if="detail.curriculum"> <div class="course-top" v-if="loaded">
<div class="course-top-hd"> <div class="course-top-hd">
<div class="course-top__title">{{ detail.curriculum.curriculum_name }}</div> <div class="course-top-hd-left">
<div class="course-top__title">{{ detail.curriculum.curriculum_name }}</div>
<div class="course-top__progress">
视频观看进度 <el-progress :percentage="detail.video_progress"></el-progress>
</div>
</div>
<div class="course-top-hd-right">
<el-button type="primary" size="small" @click="onChapterClick(latestVideo)" v-if="latestVideo">
{{ buttonText }}
</el-button>
</div>
</div> </div>
<div class="course-top-bd"> <div class="course-top-bd">
<div class="course-top__pic"><img :src="detail.curriculum.curriculum_picture" /></div> <div class="course-top__pic"><img :src="detail.curriculum.curriculum_picture" /></div>
<div class="course-top__content" v-html="detail.curriculum.curriculum_represent"></div> <div class="course-top__content" v-html="detail.curriculum.curriculum_represent"></div>
</div> </div>
</div> </div>
<el-tabs v-model="tabActive"> <div class="course-bottom">
<el-tab-pane lazy label="按章节学习"> <div class="course-bottom-left">
<course-chapter :courseId="courseId" :data="detail.chapters"></course-chapter> <el-tabs v-model="tabActive">
</el-tab-pane> <el-tab-pane lazy label="课程内容">
<!-- <el-tab-pane lazy label="按考点学习"> <course-chapter :courseId="courseId" :showProgress="true" :data="detail.chapters"></course-chapter>
</el-tab-pane>
<!-- <el-tab-pane lazy label="按考点学习">
<course-tag :courseId="courseId" @on-click="onTagClick"></course-tag> <course-tag :courseId="courseId" @on-click="onTagClick"></course-tag>
</el-tab-pane> --> </el-tab-pane> -->
</el-tabs> </el-tabs>
</div> </div>
<div class="course-bottom-right">
<el-tabs>
<el-tab-pane label="课程讲师">
<course-teacher :data="detail.lecturers"></course-teacher>
</el-tab-pane>
</el-tabs>
</div>
</div>
</app-container>
</template> </template>
<script> <script>
import AppContainer from '@/components/AppContainer'
import CourseChapter from './components/CourseChapter' import CourseChapter from './components/CourseChapter'
import CourseTeacher from './components/CourseTeacher'
import CourseTag from '@/components/CourseTag' import CourseTag from '@/components/CourseTag'
import * as api from '@/api/course.js' import * as api from '@/api/course.js'
export default { export default {
components: { CourseChapter, CourseTag }, components: { AppContainer, CourseChapter, CourseTag, CourseTeacher },
metaInfo() { metaInfo() {
return { return {
title: this.detail.course_name || '' title: this.detail.course_name || ''
...@@ -41,6 +64,23 @@ export default { ...@@ -41,6 +64,23 @@ export default {
computed: { computed: {
courseId() { courseId() {
return this.$route.params.id return this.$route.params.id
},
buttonText() {
return this.detail.latest_play ? '继续学习' : '开始学习'
},
// 扁平化章节数据
flatChapters() {
return this.detail.chapters.reduce((result, item) => {
return result.concat(item.children)
}, [])
},
// 最新的视频
latestVideo() {
if (this.detail.latest_play && this.flatChapters.length) {
return this.flatChapters.find(item => item.resource_id === this.detail.latest_play)
} else {
return this.flatChapters.length ? this.flatChapters[0] : null
}
} }
}, },
methods: { methods: {
...@@ -59,6 +99,9 @@ export default { ...@@ -59,6 +99,9 @@ export default {
// 考点点击 // 考点点击
onTagClick(data) { onTagClick(data) {
this.$router.push({ name: 'courseTagItem', params: { courseId: this.courseId, id: data.id } }) this.$router.push({ name: 'courseTagItem', params: { courseId: this.courseId, id: data.id } })
},
onChapterClick(data) {
this.$router.push({ name: 'viewerCourseChapter', params: { cid: this.courseId, id: data.id } })
} }
}, },
beforeMount() { beforeMount() {
...@@ -79,15 +122,27 @@ export default { ...@@ -79,15 +122,27 @@ export default {
padding-bottom: 20px; padding-bottom: 20px;
} }
.course-top-hd { .course-top-hd {
padding-bottom: 8px; display: flex;
margin-bottom: 10px; justify-content: space-between;
border-bottom: 1px solid #ccc; padding-bottom: 10px;
}
.course-top-hd-left {
flex: 1;
} }
.course-top__title { .course-top__title {
font-size: 18px; font-size: 18px;
font-weight: bold; font-weight: bold;
line-height: 1; line-height: 1;
} }
.course-top__progress {
margin-top: 10px;
display: flex;
align-items: center;
.el-progress {
width: 50%;
margin: 0 10px;
}
}
.course-top-bd { .course-top-bd {
display: flex; display: flex;
} }
...@@ -108,4 +163,14 @@ export default { ...@@ -108,4 +163,14 @@ export default {
line-height: 24px; line-height: 24px;
overflow: hidden; overflow: hidden;
} }
.course-bottom {
display: flex;
}
.course-bottom-left {
flex: 1;
}
.course-bottom-right {
margin-left: 20px;
width: 300px;
}
</style> </style>
<template>
<app-container title="系统说明"> </app-container>
</template>
<script>
import AppContainer from '@/components/AppContainer'
export default {
components: { AppContainer }
}
</script>
<template>
<app-container title="常见问题">
<dl v-for="(item, index) in list" :key="index">
<dt>{{ item.title }}</dt>
<dd>{{ item.content }}</dd>
</dl>
</app-container>
</template>
<script>
import AppContainer from '@/components/AppContainer'
export default {
components: { AppContainer },
data() {
return {
list: [
{
title: '给组件绑定的事件为什么无法触发?',
content: '在 Vue 2.0 中,为自定义组件绑定原生事件必须使用 .native 修饰符'
},
{
title: '给组件绑定的事件为什么无法触发?',
content: '在 Vue 2.0 中,为自定义组件绑定原生事件必须使用 .native 修饰符'
},
{
title: '给组件绑定的事件为什么无法触发?',
content: '在 Vue 2.0 中,为自定义组件绑定原生事件必须使用 .native 修饰符'
}
]
}
}
}
</script>
<style lang="scss" scoped>
dl {
padding: 10px 0;
}
dt {
font-weight: bold;
color: #262626;
}
dd {
padding-top: 10px;
color: #666;
}
dl + dl {
border-top: 1px solid #eee;
}
</style>
...@@ -69,11 +69,23 @@ export default [ ...@@ -69,11 +69,23 @@ export default [
{ path: '/contact', component: () => import(/* webpackChunkName: "contact" */ '@/pages/contact') }, { path: '/contact', component: () => import(/* webpackChunkName: "contact" */ '@/pages/contact') },
/* 通知 */ /* 通知 */
{ path: '/messages', component: () => import(/* webpackChunkName: "messages" */ '@/pages/messages') }, { path: '/messages', component: () => import(/* webpackChunkName: "messages" */ '@/pages/messages') },
/* 通知 */
{ path: '/doc', component: () => import(/* webpackChunkName: "help" */ '@/pages/doc') },
/* 通知 */
{ path: '/help', component: () => import(/* webpackChunkName: "help" */ '@/pages/help') },
{
path: '/account',
component: () => import(/* webpackChunkName: "account" */ '@/pages/account/index')
},
/* 修改密码 */ /* 修改密码 */
{ {
path: '/account/password', path: '/account/password',
component: () => import(/* webpackChunkName: "account" */ '@/pages/account/password') component: () => import(/* webpackChunkName: "account" */ '@/pages/account/password')
}, },
{
path: '/account/safe',
component: () => import(/* webpackChunkName: "account" */ '@/pages/account/safe')
},
{ {
path: '/my/questions/wrong', path: '/my/questions/wrong',
component: () => import(/* webpackChunkName: "course-learn" */ '@/pages/my/questions/questionWrong') component: () => import(/* webpackChunkName: "course-learn" */ '@/pages/my/questions/questionWrong')
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论