parent
c228536503
commit
2d71c360e9
@ -0,0 +1,21 @@ |
||||
module.exports = { |
||||
root: true, |
||||
env: { |
||||
node: true, |
||||
es6: true, |
||||
browser: true |
||||
}, |
||||
extends: ['plugin:vue/essential', 'eslint:recommended', 'plugin:prettier/recommended'], |
||||
parserOptions: { |
||||
parser: 'babel-eslint' |
||||
}, |
||||
globals: { |
||||
envConfig: 'readable' |
||||
}, |
||||
rules: { |
||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', |
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', |
||||
'no-unused-vars': 0, |
||||
'vue/no-mutating-props': 0 |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
module.exports = { |
||||
printWidth: 120, // 一行最多 120 字符(默认80)
|
||||
tabWidth: 2, // 每个tab相当于多少个空格(默认2)
|
||||
useTabs: false, // 是否使用tab进行缩进(默认false)
|
||||
semi: false, // 行尾需要有分号(默认true)
|
||||
singleQuote: true, // 使用单引号(默认false)
|
||||
quoteProps: 'as-needed', // 对象的 key 仅在必要时用引号
|
||||
jsxSingleQuote: false, // jsx 不使用单引号,而使用双引号
|
||||
trailingComma: 'none', // 多行使用拖尾逗号(默认none)
|
||||
bracketSpacing: true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"(默认true)
|
||||
jsxBracketSameLine: false, // 多行JSX中的>放置在最后一行的结尾,而不是另起一行(默认false)
|
||||
htmlWhitespaceSensitivity: 'css', // 根据显示样式决定 html 要不要折行
|
||||
arrowParens: 'avoid', // 只有一个参数的箭头函数的参数是否带圆括号(默认avoid:添加括号)
|
||||
endOfLine: 'auto' // 行尾换行符
|
||||
} |
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 190 KiB |
Before Width: | Height: | Size: 869 KiB |
@ -0,0 +1,340 @@ |
||||
<template> |
||||
<div class="onLineWrap" v-show="courseCon.courseName"> |
||||
<div class="courseName">{{ courseCon.courseName }}</div> |
||||
<div class="line"></div> |
||||
<div class="courseTime">时间:{{ yyyDate(courseCon.courseTime) }}</div> |
||||
<div class="courseTime">讲师:{{ courseCon.instructor }}</div> |
||||
<div class="courseTime" v-show="courseCon.title">职称:{{ courseCon.title }}</div> |
||||
<div class="courseTime">授课内容:{{ courseCon.courseContent }}</div> |
||||
<div class="onLineBtnCoup"> |
||||
<div v-if="startLeran" class="payLearn" type="primary" @click="toLearn">开始学习</div> |
||||
<div v-if="!startLeran" @click="toPay" class="payLearn" type="primary">付费学习¥ {{ courseCon.amount }}</div> |
||||
<div v-if="!startLeran" @click="toInpWord" class="inpPass" type="text">输入口令学习</div> |
||||
</div> |
||||
<el-dialog :title="title" :visible.sync="dialogVisible" width="450px" class="onlineDialog" @close="closed"> |
||||
<el-divider></el-divider> |
||||
<el-dialog class="onlineDialog" @close="inClosed" width="30%" :title="'支付'" :visible.sync="innerVisible" |
||||
append-to-body> |
||||
<el-divider></el-divider> |
||||
<div style="text-align: center;margin-top: 30px;"> |
||||
<qrcode :value="codeUrl" :options="options"></qrcode> |
||||
<div style="margin-top: 5px">请使用{{ paymentType == 'A01' ? '支付宝' : '微信' }}扫描二维码</div> |
||||
</div> |
||||
</el-dialog> |
||||
<div v-if="current == 'pass'" class="verification-container"> |
||||
<input v-for="(code, index) in verificationCodes" :key="index" v-model="verificationCodes[index]" |
||||
@input="handleInput(index, $event)" @keydown="handleKeyDown(index, $event)" maxlength="1" |
||||
class="verification-input" /> |
||||
</div> |
||||
<div v-else-if="current == 'pay'"> |
||||
<el-form label-width="80px" class="payLabel"> |
||||
<el-form-item label="应付金额:" class="payLabel"> |
||||
<div style="color: rgb(253, 70, 26);font-size: 25px;">¥ {{ courseCon.amount }}</div> |
||||
</el-form-item> |
||||
<el-form-item label="支付方式:"> |
||||
<el-radio size="small" class="paytypebtn" v-model="paymentType" label="A01" border> |
||||
<img class="btnpayimg" src="/assets/home/zfb.png" alt="" />支付宝</el-radio> |
||||
<el-radio size="small" class="paytypebtn" v-model="paymentType" label="W01" border> |
||||
<img class="btnpayimg" src="/assets/home/wx.png" alt="" />微信</el-radio> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
<div v-else class="copyLearnLink"> |
||||
<div>学习链接</div> |
||||
<div style="margin: 1px">请使用腾讯会议打开</div> |
||||
<div>{{ courseCon.url }}</div> |
||||
</div> |
||||
<div slot="footer" style="text-align: center"> |
||||
<el-button type="primary" style="width: 250px;height: 44px;border-radius: 22px;" @click="submit">{{ |
||||
(current == 'copy') ? '复制链接' : '确定' }}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { getOnlineCourse, subPass, payForOnlineCourse } from '@/api/train'; |
||||
import { dateFormat } from '@/util/util'; |
||||
import copyText from '@/util/cpoyText'; |
||||
import { mapGetters } from 'vuex' |
||||
import VueQrcode from '@xkeshi/vue-qrcode' |
||||
import { searchOrderStatus } from '@/api/pay/index.js' |
||||
|
||||
|
||||
export default { |
||||
components: { |
||||
qrcode: VueQrcode, |
||||
}, |
||||
data() { |
||||
return { |
||||
title: '', |
||||
courseId: '', |
||||
options: { size: 150 }, |
||||
startLeran: false, |
||||
current: '', |
||||
courseCon: {}, |
||||
dialogVisible: false, |
||||
innerVisible: false, |
||||
orderSearch: null, |
||||
verificationCodes: ['', '', '', ''], |
||||
paymentType: 'A01', |
||||
codeUrl: '' |
||||
} |
||||
}, |
||||
created() { |
||||
this.courseId = this.$route.query.courseId |
||||
this.startLeran = this.$route.query.toLearn === 'true' |
||||
getOnlineCourse(this.courseId).then(res => { |
||||
this.courseCon = res.data |
||||
}) |
||||
|
||||
}, |
||||
computed: { |
||||
...mapGetters(['paytype', 'tooltypelist', 'token', 'userinform']), |
||||
yyyDate() { |
||||
return function (val) { |
||||
return dateFormat(new Date(val)) |
||||
} |
||||
} |
||||
}, |
||||
methods: { |
||||
closed() { |
||||
this.verificationCodes = ['', '', '', ''] |
||||
}, |
||||
inClosed() { |
||||
clearInterval(this.orderSearch) |
||||
this.orderSearch = null |
||||
}, |
||||
toInpWord() { |
||||
this.current = 'pass' |
||||
this.title = '请输入口令' |
||||
this.dialogVisible = true |
||||
}, |
||||
toPay() { |
||||
this.current = 'pay' |
||||
this.title = '付款' |
||||
this.dialogVisible = true |
||||
}, |
||||
toLearn() { |
||||
this.current = 'copy' |
||||
this.dialogVisible = true |
||||
this.title = '复制学习链接' |
||||
}, |
||||
async pay() { |
||||
const id = this.userinform.userId |
||||
const data = { |
||||
"price": this.courseCon.amount, |
||||
"payType": this.paymentType, |
||||
"userId": id, |
||||
// "recordName": this.courseItem.courseName, |
||||
// "toolId":this.courseItem.courseId |
||||
} |
||||
const res = await payForOnlineCourse(data) |
||||
if (res) { |
||||
console.log(res); |
||||
this.codeUrl = res.data.payinfo |
||||
this.innerVisible = true |
||||
this.orderSearch = setInterval(() => { |
||||
searchOrderStatus({ reqsn: res.data.reqsn }).then(res => { |
||||
if (res) { |
||||
clearInterval(this.orderSearch) |
||||
this.orderSearch = null |
||||
this.$message.success('支付成功') |
||||
} |
||||
}) |
||||
}, 5000); |
||||
} |
||||
this.innerVisible = true |
||||
}, |
||||
submit() { |
||||
if (this.current == 'copy') { |
||||
const res = copyText(this.courseCon.url) |
||||
if (res) { |
||||
this.$message.success("复制成功") |
||||
this.dialogVisible = false |
||||
} |
||||
} else if (this.current == 'pay') { |
||||
this.pay() |
||||
return |
||||
} |
||||
const code = this.verificationCodes.toString().replaceAll(",", "") |
||||
if (code.length != 4) { |
||||
return |
||||
} |
||||
subPass(this.courseId, code).then(res => { |
||||
if (res.code == 200) { |
||||
this.startLeran = true |
||||
} |
||||
this.verificationCodes = ['', '', '', ''] |
||||
this.dialogVisible = false |
||||
}) |
||||
|
||||
}, |
||||
handleInput(index, event) { |
||||
const value = event.target.value; |
||||
this.verificationCodes[index] = value; |
||||
// 自动跳到下一个输入框 |
||||
if (value && index < this.verificationCodes.length - 1) { |
||||
const nextInput = event.target.nextElementSibling; |
||||
if (nextInput) { |
||||
this.$nextTick(() => { |
||||
nextInput.focus() |
||||
}); |
||||
} |
||||
} |
||||
}, |
||||
handleKeyDown(index, event) { |
||||
// 处理删除操作 |
||||
if (event.key === 'Backspace' && !event.target.value && index > 0) { |
||||
const prevInput = event.target.previousElementSibling; |
||||
if (prevInput) { |
||||
this.$nextTick(() => { |
||||
prevInput.focus(); |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss"> |
||||
.paytypebtn { |
||||
|
||||
.el-radio__label { |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
|
||||
.el-radio__input { |
||||
display: none; |
||||
|
||||
} |
||||
} |
||||
|
||||
.payLabel { |
||||
.el-form-item__content { |
||||
font-weight: 500; |
||||
font-size: 19px; |
||||
color: grey; |
||||
} |
||||
} |
||||
|
||||
.verification-container { |
||||
display: flex; |
||||
justify-content: center; |
||||
margin-top: 40px; |
||||
} |
||||
|
||||
.verification-input { |
||||
width: 54px; |
||||
height: 54px; |
||||
background: #ECEFF3; |
||||
margin: 0 15px; |
||||
text-align: center; |
||||
font-size: 18px; |
||||
border-radius: 5px; |
||||
border: none; |
||||
} |
||||
|
||||
.verification-input:focus { |
||||
outline: none; |
||||
border-color: #007bff; |
||||
box-shadow: 0 0 5px #007bff; |
||||
} |
||||
|
||||
.onlineDialog { |
||||
.el-divider { |
||||
margin: -30px 0 10px 0; |
||||
} |
||||
|
||||
.el-dialog__title { |
||||
font-weight: bold !important; |
||||
} |
||||
} |
||||
|
||||
.btnpayimg { |
||||
width: 17px; |
||||
height: 17px; |
||||
margin-right: 5px; |
||||
} |
||||
|
||||
.onLineWrap { |
||||
padding: 10px 0 0 0; |
||||
font-family: PingFang SC; |
||||
|
||||
|
||||
|
||||
.courseName { |
||||
margin-left: 40px; |
||||
font-weight: bold; |
||||
font-size: 18px; |
||||
color: #1A1A1A; |
||||
} |
||||
|
||||
.line { |
||||
width: 1631px; |
||||
height: 1px; |
||||
background: #999999; |
||||
opacity: 0.15; |
||||
margin-top: 24px; |
||||
} |
||||
|
||||
.courseTime { |
||||
margin-top: 15px; |
||||
margin-left: 40px; |
||||
} |
||||
|
||||
|
||||
|
||||
.onLineBtnCoup { |
||||
position: absolute; |
||||
bottom: 20px; |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: center; |
||||
left: 50%; |
||||
transform: translate(-50%); |
||||
|
||||
.inpPass { |
||||
text-align: center; |
||||
height: 16px; |
||||
font-family: PingFang SC; |
||||
font-weight: 500; |
||||
font-size: 16px; |
||||
color: #2286FA; |
||||
line-height: 33px; |
||||
margin-bottom: 70px; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
.payLearn { |
||||
width: 160px; |
||||
height: 36px; |
||||
background: #2286FA; |
||||
border-radius: 18px; |
||||
font-family: PingFang SC; |
||||
font-weight: 500; |
||||
font-size: 16px; |
||||
color: #FFFFFF; |
||||
line-height: 36px; |
||||
text-align: center; |
||||
margin-bottom: 15px; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
.el-button { |
||||
margin: 10px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.copyLearnLink { |
||||
font-family: PingFang SC; |
||||
text-align: center; |
||||
font-weight: 500; |
||||
font-size: 16px; |
||||
color: #1A1A1A; |
||||
line-height: 30px; |
||||
} |
||||
</style> |
@ -1 +1,8 @@ |
||||
@import './variable.scss' |
||||
@import './reset.scss'; |
||||
@import './variable.scss'; |
||||
|
||||
.contactMissZhang { |
||||
.el-notification__content { |
||||
color: #f56c6c; |
||||
} |
||||
} |
||||
|
@ -1 +1,2 @@ |
||||
$bg-color: #0066eb |
||||
$bg-color: #0066eb; |
||||
$font-size:500; |
@ -0,0 +1,15 @@ |
||||
function downPdf(val) { |
||||
fetch(val).then(respose => { |
||||
return respose.blob() |
||||
}).then(blob => { |
||||
console.log(val); |
||||
const url = URL.createObjectURL(blob) |
||||
const a = document.createElement("a") |
||||
const name = val.substr(val.lastIndexOf('/') + 1, val.length) |
||||
a.href = url |
||||
a.download = name |
||||
a.click() |
||||
}) |
||||
} |
||||
|
||||
export default downPdf |
Loading…
Reference in new issue