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

feat: 增加课程学习提醒;

上级 caac2f82
......@@ -37,7 +37,8 @@ export default class API {
/* 具体执行请求失败后业务逻辑前,先执行该方法 */
const beforeFail = _config.beforeFail ? _config.beforeFail : this._reqFail
const headers = {
tenant: 'transport'
tenant: 'transport',
'Content-Type': 'application/x-www-form-urlencoded'
}
_config.headers = _.assignIn(_config.headers, headers)
/* 判别 传输方式 */
......
......@@ -6,7 +6,8 @@ export default class Before {
async update(to, from, next) {
if (to.meta.requiredLogin) {
const isLogin = await store.dispatch('checkLogin')
const isLogin =
store.state.isLogin || (await store.dispatch('checkLogin'))
if (isLogin) {
next()
} else {
......
......@@ -60,7 +60,7 @@ export default {
name: 'Index',
components: { SearchBar, Card, FreeCourseItem },
metaInfo: {
title: '道路运输安全知识线上课'
title: '道路安全考证宝典'
},
data() {
return {
......
import BaseAPI from '@/api/base_api'
const httpRequest = new BaseAPI(webConf)
/**
* 获取课程提醒列表
*/
export function getAlarmList() {
return httpRequest.get('/zy/v2/education/alarm/list')
}
/**
* 获取课程提醒详情
*/
export function getAlarm(id) {
return httpRequest.get(`/zy/v2/education/alarm/detail/${id}`)
}
/**
* 添加课程提醒
*/
export function addAlarm(data) {
return httpRequest.post('/zy/v2/education/alarm/add', data)
}
/**
* 更新课程提醒
*/
export function updateAlaram(data) {
return httpRequest.post('/zy/v2/education/alarm/edit', data)
}
/**
* 删除课程提醒
*/
export function deleteAlaram(id) {
return httpRequest.delete(`/zy/v2/education/alarm/delete/${id}`)
}
/**
* 检查是否关注微信公众号
*/
export function checkFollowWechat(id) {
return httpRequest.get('/zy/v2/education/hasguanzhu')
}
<template>
<div class="alarm-item">
<div class="alarm-item-left" @click="$emit('click-edit', data)">
<h4 class="alarm-item__title">{{data.time}}</h4>
<p class="alarm-item__text">{{showText}}</p>
</div>
<div class="alarm-item-right">
<van-switch
v-model="checked"
size="18px"
active-color="#2B7CE9"
:loading="switchLoading"
@change="onChange"
/>
<van-icon name="delete" @click="onRemove" />
</div>
</div>
</template>
<script>
import * as api from '../api'
export default {
name: 'AlarmItem',
props: {
data: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
checked: false,
switchLoading: false
}
},
watch: {
'data.status': {
immediate: true,
handler(value) {
this.checked = value === '1'
}
}
},
computed: {
showText() {
const type = parseInt(this.data.type)
if (type === 1) {
return '每天'
} else if (type === 3) {
return '工作日'
} else {
return this.selectedWeek.length
? '每周' + this.selectedWeek.join('、')
: '永不'
}
},
selectedWeek() {
const weeks = ['一', '二', '三', '四', '五', '六', '日']
const nums = this.data.week_json ? JSON.parse(this.data.week_json) : []
return nums.map(item => weeks[item - 1])
}
},
methods: {
onChange() {
this.switchLoading = true
const params = Object.assign({}, this.data)
params.status = this.checked ? 1 : 0
api.updateAlaram(params).finally(() => {
this.switchLoading = false
})
},
onRemove() {
this.$emit('remove', this.data)
api.deleteAlaram(this.data.id).then(response => {
this.$toast('删除成功')
this.$emit('update')
})
}
}
}
</script>
<style lang="scss" scoped>
.alarm-item {
display: flex;
align-items: center;
padding: 20px 0;
}
.alarm-item-left {
flex: 1;
}
.alarm-item__title {
font-size: 20px;
font-weight: bold;
line-height: 1;
}
.alarm-item__text {
margin-top: 5px;
font-size: 13px;
line-height: 1;
color: #666;
}
.alarm-item-right {
margin-left: 20px;
font-size: 0;
::v-deep .van-icon {
margin-left: 20px;
font-size: 20px;
color: #ccc;
}
}
</style>
<template>
<div class="alarm-update">
<div class="alarm-title">{{title}}</div>
<div class="alarm-form">
<div class="alarm-form-time">
<div class="alarm-form-time__lable">提醒时间</div>
<van-picker
v-model="ruleForm.time"
:columns="timeColumns"
:item-height="30"
:default-index="defaultIndex"
@change="onChangeTime"
/>
</div>
<div class="alarm-form-item">
<div class="alarm-form-item-hd">
<div class="alarm-form-item-hd__lable">重复</div>
<div class="alarm-form-item-hd__aside">{{selectedResultText}}</div>
</div>
<div class="alarm-form-item-content">
<van-checkbox-group v-model="ruleForm.week_json" direction="horizontal">
<van-checkbox v-for="(item, index) in weeks" :name="index + 1" :key="index">{{item}}</van-checkbox>
</van-checkbox-group>
</div>
</div>
<van-button type="primary" @click="onSubmit">确定</van-button>
</div>
</div>
</template>
<script>
import { isEqual } from 'lodash'
import * as api from '../api'
export default {
name: 'AlarmUpdate',
props: {
isUpdate: { type: Boolean, default: false },
data: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
ruleForm: {
time: '06:30',
week_json: [],
status: 1
},
weeks: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
defaultIndex: 13
}
},
watch: {
data: {
immediate: true,
handler(data) {
if (!data || !this.isUpdate) {
return
}
const weeks = data.week_json ? JSON.parse(data.week_json) : []
this.defaultIndex = this.timeColumns.findIndex(
item => item === data.time
)
this.ruleForm = Object.assign({}, this.ruleForm, data, {
week_json: weeks
})
}
}
},
computed: {
title() {
return this.isUpdate ? '修改提醒时间' : '新增提醒时间'
},
// 时间选择项
timeColumns() {
return this.genTimeColumns()
},
// 重复类型
selectedResultType() {
const weeks = this.ruleForm.week_json.sort()
if (isEqual(weeks, [1, 2, 3, 4, 5, 6, 7])) {
return 1
} else if (isEqual(weeks, [1, 2, 3, 4, 5])) {
return 3
} else {
return 2
}
},
// 重复类型显示文本
selectedResultText() {
if (this.selectedResultType === 1) {
return '每天'
} else if (this.selectedResultType === 3) {
return '工作日'
} else {
return this.selectedWeek.length
? '每周' + this.selectedWeek.join('、')
: '永不'
}
},
selectedWeek() {
const weeks = ['一', '二', '三', '四', '五', '六', '日']
const nums = this.ruleForm.week_json
return nums.map(item => weeks[item - 1])
}
},
methods: {
onSubmit() {
this.isUpdate ? this.handleUpdate() : this.handleAdd()
},
// 添加
handleAdd() {
const params = Object.assign({}, this.ruleForm)
params.type = this.selectedResultType
params.week_json = JSON.stringify(this.ruleForm.week_json.sort())
api.addAlarm(params).then(response => {
if (response.success) {
this.handleSuccess(response)
} else {
this.$toast(JSON.stringify(response.errors))
}
})
},
// 更新
handleUpdate() {
const params = Object.assign({}, this.ruleForm)
params.type = this.selectedResultType
params.week_json = JSON.stringify(this.ruleForm.week_json.sort())
api.updateAlaram(params).then(response => {
if (response.success) {
this.handleSuccess(response)
} else {
this.$toast(JSON.stringify(response.errors))
}
})
},
handleSuccess(response) {
this.$emit('success', response)
},
filter(type, options) {
if (type === 'minute') {
return options.filter(option => option % 30 === 0)
}
return options
},
// 生成提醒时间数据
genTimeColumns() {
const columns = []
for (let i = 0; i <= 23; i++) {
const temp = i < 10 ? `0${i}` : i
columns.push(`${temp}:00`)
columns.push(`${temp}:30`)
}
return columns
},
onChangeTime(picker, value, index) {
this.ruleForm.time = value
}
}
}
</script>
<style lang="scss" scoped>
.alarm-update {
padding: 20px;
}
.alarm-title {
margin-bottom: 20px;
font-size: 18px;
color: #222;
line-height: 1;
text-align: center;
}
.alarm-form {
}
.alarm-form-time {
position: relative;
margin-bottom: 20px;
}
.alarm-form-time__lable {
position: absolute;
top: 0;
left: 0;
bottom: 0;
z-index: 100;
display: flex;
align-items: center;
font-size: 15px;
line-height: 1;
}
.alarm-form-item {
margin-bottom: 20px;
}
.alarm-form-item-hd {
display: flex;
justify-content: space-between;
padding-bottom: 20px;
}
.alarm-form-item-hd__lable {
font-size: 15px;
}
.alarm-form-item-hd__aside {
font-size: 15px;
color: #a7a6a7;
}
::v-deep .van-picker__frame {
display: none;
}
::v-deep .van-checkbox {
width: 34px;
height: 34px;
justify-content: center;
font-size: 12px;
text-align: center;
border: 1px solid #eee;
border-radius: 50%;
box-sizing: border-box;
&:last-child {
margin-right: 0;
}
}
::v-deep .van-checkbox[aria-checked='true'] {
background-color: #2b7ce9;
border: 0;
.van-checkbox__label {
color: #fff;
}
}
::v-deep .van-checkbox__icon {
display: none;
}
::v-deep .van-checkbox__label {
margin: 0;
color: #a7a6a7;
}
::v-deep .van-button {
margin-top: 40px;
display: block;
width: 100%;
height: 40px;
background-color: #2b7ce9;
border: 0;
border-radius: 6px;
}
</style>
<template>
<div class="list">
<alarm-item
v-for="item in list"
:data="item"
:key="item.id"
@click-edit="onUpdate"
@update="refersh"
></alarm-item>
<div class="add-button">
<div class="inner" @click="popupVisible = true"></div>
</div>
<!-- 添加/修改 -->
<van-popup v-model="popupVisible" position="bottom" @closed="onClosed">
<alarm-update
:isUpdate="isUpdate"
:data="activeItem"
@success="onSuccess"
v-if="popupVisible"
></alarm-update>
</van-popup>
<van-popup v-model="followPopupVisible" style="border-radius:6px;">
<div class="qrcode">
<p>开启学习提醒功能,需先关注紫荆职教公众号。</p>
<img src="../../../assets/images/wechat_mp_qrcode.png" />
<h5>保存二维码图片,扫码关注</h5>
</div>
</van-popup>
</div>
</template>
<script>
import * as api from './api'
import AlarmItem from './components/alarmItem.vue'
import AlarmUpdate from './components/update.vue'
export default {
name: 'AlarmIndex',
components: { AlarmItem, AlarmUpdate },
metaInfo: {
title: '学习提醒'
},
data() {
return {
list: [],
popupVisible: false,
isUpdate: false,
activeItem: null,
followPopupVisible: false
}
},
methods: {
// 检查是否关注公众号
checkFollowWechat() {
api.checkFollowWechat().then(response => {
this.followPopupVisible = !response.flag
})
},
// 获取提醒列表
getAlarmList() {
api.getAlarmList().then(response => {
this.list = response
})
},
refersh() {
this.getAlarmList()
},
onUpdate(data) {
this.isUpdate = true
this.activeItem = data
this.popupVisible = true
},
onSuccess() {
this.popupVisible = false
this.refersh()
},
onClosed() {
this.isUpdate = false
this.activeItem = null
}
},
beforeMount() {
this.checkFollowWechat()
this.getAlarmList()
}
}
</script>
<style lang="scss" scoped>
.list {
padding: 20px 0;
margin: 0 20px;
}
.add-button {
height: 64px;
margin-bottom: 50px;
.inner {
position: fixed;
left: 50%;
bottom: 50px;
transform: translateX(-50%);
width: 64px;
height: 64px;
background: url('../../../assets/images/icon_remind_add.png') no-repeat;
background-size: 100%;
}
}
.qrcode {
width: 5.9rem;
padding: 0.4rem;
box-sizing: border-box;
img {
margin: 10px 0;
width: 100%;
}
p {
font-size: 15px;
color: #222;
}
h5 {
font-size: 15px;
color: #222;
font-weight: bold;
text-align: center;
}
}
</style>
import BaseAPI from '@/api/base_api'
const httpRequest = new BaseAPI(webConf)
/**
* 获取免费课程列表
*/
export function getFreeCourseList() {
return httpRequest.get('/zy/v2/education/freecourse')
}
<template>
<div class="learned"></div>
</template>
<script>
export default {
metaInfo: {
title: '已学课程'
},
data() {
return {}
},
methods: {}
}
</script>
<style lang="scss" scoped>
</style>
......@@ -133,11 +133,19 @@ export default [
{
path: '/pay',
name: 'pay',
component: () => import('../pages/pay/index.vue')
component: () => import('../pages/pay/index.vue'),
meta: { requiredLogin: true }
},
{
path: '/download',
name: 'download',
component: () => import('../pages/download/index.vue')
component: () => import('../pages/download/index.vue'),
meta: { requiredLogin: true }
},
{
path: '/my/alarm',
name: 'MyAlarm',
component: () => import('../pages/my/alarm/index.vue'),
meta: { requiredLogin: true }
}
]
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论