提交 6901d23d authored 作者: matian's avatar matian

updates

上级 6a77190b
差异被折叠。
...@@ -19,7 +19,11 @@ ...@@ -19,7 +19,11 @@
"axios": "^1.1.3", "axios": "^1.1.3",
"element-plus": "^2.2.19", "element-plus": "^2.2.19",
"pinia": "^2.0.23", "pinia": "^2.0.23",
"qrcode.vue": "^3.3.3",
"query-string": "^7.1.1",
"querystring": "^0.2.1",
"swiper": "^8.4.4", "swiper": "^8.4.4",
"vant": "^3.6.5",
"vue": "^3.2.41", "vue": "^3.2.41",
"vue-router": "^4.1.6" "vue-router": "^4.1.6"
}, },
......
...@@ -58,3 +58,11 @@ export function postNes(data: any) { ...@@ -58,3 +58,11 @@ export function postNes(data: any) {
headers: { 'Content-Type': 'multipart/form-data' } headers: { 'Content-Type': 'multipart/form-data' }
}) })
} }
/**
* 获取用户OpenId
* */
export function getOpenId(data?: any) {
return httpRequest.post('https://shop-show-pc.ezijing.com/api/usercenter/v1/wechat/get-openid', data, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
}
\ No newline at end of file
...@@ -4,6 +4,7 @@ import TreeItem from './TreeItem.vue' ...@@ -4,6 +4,7 @@ import TreeItem from './TreeItem.vue'
const navList = [ const navList = [
{ name: '项目介绍', path: '/' }, { name: '项目介绍', path: '/' },
{ name: '课程体系', path: '/#product' }, { name: '课程体系', path: '/#product' },
{ name: '精品课程', path: '/shop' },
{ name: '师资介绍', path: '/#teacher' }, { name: '师资介绍', path: '/#teacher' },
{ name: '认证流程', path: '/#apply' } { name: '认证流程', path: '/#apply' }
] ]
...@@ -12,7 +13,11 @@ const navList = [ ...@@ -12,7 +13,11 @@ const navList = [
<template> <template>
<nav class="app-nav"> <nav class="app-nav">
<ul class="app-menu"> <ul class="app-menu">
<TreeItem :item="item" v-for="(item, index) in navList" :key="index"></TreeItem> <TreeItem
:item="item"
v-for="(item, index) in navList"
:key="index"
></TreeItem>
</ul> </ul>
</nav> </nav>
</template> </template>
......
...@@ -6,7 +6,9 @@ import router from './router' ...@@ -6,7 +6,9 @@ import router from './router'
import ElementPlus from 'element-plus' import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css' import 'element-plus/dist/index.css'
import { Overlay } from 'vant'
// 2. 引入组件样式
import 'vant/lib/index.css';
// 公共css // 公共css
import './assets/css/base.css' import './assets/css/base.css'
// 公共组件 // 公共组件
...@@ -23,6 +25,7 @@ app.component('AppCard', AppCard).component('AppContainer', AppContainer) ...@@ -23,6 +25,7 @@ app.component('AppCard', AppCard).component('AppContainer', AppContainer)
modules({ router }) modules({ router })
app.use(createPinia()) app.use(createPinia())
app.use(Overlay)
app.use(router) app.use(router)
app.use(ElementPlus) app.use(ElementPlus)
......
import httpRequest from '@/utils/axios'
/**
* 创建订单
* */
export function createOrder(data?: any) {
return httpRequest.post('https://shop-show-pc.ezijing.com/api/shop/order/add', data)
}
/**
* 获取订单
* */
export function getOrderList(data?: any) {
return httpRequest.post('https://shop-show-pc.ezijing.com/api/shop/order/search', data)
}
/**
* 获取用户OpenId
* */
export function getOpenId(data?: any) {
return httpRequest.post('https://shop-show-pc.ezijing.com/api/usercenter/v1/wechat/get-openid', data, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
}
差异被折叠。
<script setup lang="ts">
import { createOrder, getOrderList } from '../api'
import QrcodeVue from 'qrcode.vue'
import { useUserStore } from '@/stores/user'
const user = useUserStore()
const timer = ref()
const qrCodeUrl = ref('')
const payStatus = ref('')
const orderId = ref('')
const props = defineProps({
payMethod: {
type: Number
},
shopItem: {
type: Object
}
})
const emit = defineEmits<{
(e: 'update', params: object): void
}>()
onMounted(() => {
const params: any = {
shop_id: '6998523899570814976',
spu_id: '6998525810348916736',
sku_id: '6998525810365693952',
redirect_url: '',
buy_count: '1',
notify_url: `https://ep-lms-api.ezijing.com/v2/student/push?tenant=paa&sso_id=${user.user?.id}&class_id=${props.shopItem.class_id}&course_flag=1&course_id=${props.shopItem.course_id}`
}
// 支付宝扫码支付
if (props.payMethod === 1) {
params.payment_method = '11'
// 微信扫码支付
} else if (props.payMethod === 2) {
params.payment_method = '1'
}
createOrder(params).then((res: any) => {
console.log(res)
qrCodeUrl.value = res.payment_url
timer.value = setInterval(() => {
// 通过定时器每间隔一会去请求查询微信支付状态(具体参数根据项目需要而定)
handleGetOrderList(res.order_detail_id)
}, 2000)
})
})
const handleGetOrderList = (id: any) => {
getOrderList({ order_detail_id: id }).then((res) => {
payStatus.value = res.data[0].order_status
orderId.value = res.data[0].order_id
if (payStatus.value === '4') {
const params = {
orderId: res.data[0].order_id,
payPrice: res.data[0].payment_money,
status: 'success',
payStatus: res.data[0].order_status
}
clearInterval(timer.value)
emit('update', params)
}
})
}
</script>
<template>
<div class="main">
<div class="main_order">
<div class="order_id">
<div class="id_tit">商品订单:</div>
<div class="id_num">{{ orderId }}</div>
</div>
<div class="order_price">
<div class="price_tit">支付金额:</div>
<div class="price_con">
<div class="con_icon">¥</div>
<div class="con_num">{{ shopItem?.price }}</div>
</div>
</div>
<div class="line"></div>
<div class="order_mode">
<div class="mode_tit">支付方式:</div>
<div class="mode_con">
<img
:src="
payMethod === 1
? 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/pay_ali.png'
: 'https://webapp-pub.ezijing.com/project_online/fi/pay_wechat.png'
"
class="con_style"
/>
<span class="radio_tit">{{
payMethod === 1 ? '支付宝支付' : '微信支付'
}}</span>
<img
src="https://webapp-pub.ezijing.com/project_online/fi/icon_pay_checked.png"
class="checked_img"
/>
</div>
</div>
<div class="order_qaCode">
<div class="qaCode_left">
<div class="left_code">
<qrcode-vue :value="qrCodeUrl" :size="197" level="H"></qrcode-vue>
</div>
<div
class="left_desc"
:class="payMethod === 1 ? 'left_desc_ali' : 'left_desc_wechat'"
>
{{
payMethod === 1
? '请打开手机支付宝,扫一扫完成支付'
: '请打开手机微信,扫一扫完成支付'
}}
</div>
</div>
<img
:src="
payMethod === 1
? 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/icon_aliPay_img1.png'
: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/icon_wechat_img1.png'
"
class="right_img"
/>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.main {
width: 100%;
padding: 50px 0 46px 0;
.main_order {
width: 1200px;
background: #ffffff;
margin: auto;
padding: 59px 0 137px 40px;
.order_id {
display: flex;
font-size: 16px;
font-weight: 400;
line-height: 34px;
.id_tit {
color: #333333;
}
.id_num {
color: #999999;
}
}
.order_price {
display: flex;
font-size: 16px;
font-weight: 400;
line-height: 34px;
margin-top: 22px;
.price_tit {
color: #333333;
}
.price_con {
display: flex;
.con_icon {
font-size: 22px;
font-weight: 400;
line-height: 34px;
color: #aa1941;
}
.con_num {
font-size: 36px;
font-weight: normal;
line-height: 34px;
color: #aa1941;
}
}
}
.line {
margin-top: 26px;
border-bottom: 1px solid #e6e6e6;
}
.order_mode {
.mode_tit {
font-size: 16px;
font-weight: 500;
line-height: 34px;
color: #333333;
}
.mode_con {
margin-top: 29px;
width: 160px;
height: 66px;
border: 1px solid #4586d0;
display: flex;
justify-content: center;
align-items: center;
position: relative;
.con_style {
margin-right: 10px;
}
.checked_img {
position: absolute;
right: -1px;
bottom: -1px;
}
}
}
.order_qaCode {
display: flex;
margin-top: 39px;
.qaCode_left {
.left_code {
width: 197px;
}
.left_desc {
width: 197px;
height: 31px;
font-size: 12px;
font-weight: 400;
line-height: 31px;
color: #ffffff;
text-align: center;
}
.left_desc_ali {
background: #0f76fb;
}
.left_desc_wechat {
background: #01c71e;
}
}
.right_img {
margin: -11px 0 0 124px;
}
}
}
}
</style>
<script setup lang="ts">
import { useDevice } from '@/composables/useDevice'
const { mobile } = useDevice()
const router = useRouter()
const props = defineProps({
payInfo: {
type: Object
},
shopItem: {
type: Object
}
})
function getDateTime(dayNum: any) {
const dateDay = new Date()
dateDay.setDate(dateDay.getDate() + dayNum) //获取dayNum天后的日期
console.log(dateDay)
const y = dateDay.getFullYear()
const m =
dateDay.getMonth() + 1 < 10
? '0' + (dateDay.getMonth() + 1)
: dateDay.getMonth() + 1 //获取当前月份的日期,不足10补0
const d = dateDay.getDate() < 10 ? '0' + dateDay.getDate() : dateDay.getDate() //获取当前几号,不足10补0
return y + '-' + m + '-' + d
}
const start_time = getDateTime(0)
const end_time = getDateTime(90)
const handleStudy = () => {
window.open('https://paa-learning.ezijing.com')
}
const handlePrev = () => {
router.push({
path: `/shop/detail/${props.shopItem?.id}`,
query: {
payStatus: props.payInfo?.payStatus
}
})
}
</script>
<template>
<div class="main_pay" v-if="!mobile">
<div class="pay_con">
<div class="con_top">
<img
src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/icon_sucess.png"
alt=""
/>
<div class="top_tit">支付成功!</div>
</div>
<div class="con_info">
<div class="info_order">
<div class="order_tit">商品订单:</div>
<div class="order_id">{{ payInfo?.orderId }}</div>
</div>
<div class="info_price">
<div class="price_tit">支付金额:</div>
<div class="price_id">¥{{ payInfo?.payPrice }}</div>
</div>
<div class="info_tips">
若有疑问请与客服联系,我们将尽快为您提供服务
</div>
<div class="info_btn">
<div class="btn_prev" @click="handlePrev">返回</div>
<div class="btn_study" @click="handleStudy">开始学习</div>
</div>
</div>
</div>
</div>
<div class="main_pay_mobile" v-else>
<div class="con_nav">
<img
class="img1"
src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/prev_mini.png"
alt=""
srcset=""
@click="handlePrev"
/>
<div class="nav_title">
<img
class="img2"
src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/icon_sucess.png"
alt=""
/>
支付成功
</div>
</div>
<div class="course_con">
<img
src="https://img1.baidu.com/it/u=3009731526,373851691&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500"
@click="handlePrev"
/>
<div class="course_dec">
<div class="info_title">{{ shopItem?.title }}</div>
<div class="info_date">有效期:{{ start_time }}{{ end_time }}</div>
</div>
</div>
<div class="order_main">
<div class="order_num">
商品订单:<span>{{ payInfo?.orderId }}</span>
</div>
<div class="order_price">
支付金额:<span>{{ payInfo?.payPrice }}</span>
</div>
<div class="order_after_sales">
若有疑问请与客服联系,我们将尽快为您提供服务
</div>
</div>
<div class="start_study">
<div class="study_con" @click="handleStudy">开始学习</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.is-h5 {
.main_pay_mobile {
padding: 0 0.28rem;
.con_nav {
display: flex;
align-items: center;
justify-content: center;
position: relative;
.img1 {
position: absolute;
left: 0;
}
.nav_title {
height: 0.32rem;
font-size: 0.32rem;
font-weight: 500;
line-height: 0.34rem;
color: #333333;
.img2 {
width: 0.36rem;
height: 0.36rem;
}
}
}
.course_con {
margin: 0.3rem 0;
height: 1.97rem;
background: #ffffff;
opacity: 1;
border-radius: 0.12rem;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.28rem 0.2rem;
box-sizing: border-box;
gap: 0.2rem;
img {
width: 2.2rem;
height: 1.4rem;
}
.course_dec {
display: flex;
flex-direction: column;
gap: 0.2rem;
.info_title {
height: 0.64rem;
font-size: 0.28rem;
font-weight: 500;
line-height: 0.36rem;
color: #333333;
}
.info_date {
height: 0.22rem;
font-size: 0.22rem;
font-weight: 400;
line-height: 0.3rem;
color: #999999;
}
}
}
.order_main {
width: 100%;
background: #fff;
border-radius: 0.12rem;
margin-bottom: 1.91rem;
padding: 0.4rem;
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: 0.36rem;
font-weight: 400;
.order_num,
.order_price {
font-size: 0.24rem;
color: #333;
span {
color: #999;
}
}
.order_after_sales {
font-size: 0.22rem;
color: #999;
}
}
.start_study {
display: flex;
align-items: center;
justify-content: center;
.study_con {
width: 6.1rem;
height: 0.8rem;
background: linear-gradient(102deg, #f2ca8c 0%, #e69b1c 100%);
opacity: 1;
border-radius: 0.4rem;
text-align: center;
line-height: 0.8rem;
color: #fff;
font-size: 0.28rem;
}
}
}
}
.is-pc {
.main_pay {
width: 100%;
padding: 50px 0 60px 0;
.pay_con {
width: 1200px;
margin: auto;
background: #ffffff;
border-radius: 6px;
.con_top {
width: 1200px;
height: 106px;
background: #f4fff5;
border-radius: 6px 6px 0px 0px;
display: flex;
align-items: center;
padding: 40px 0 40px 67px;
box-sizing: border-box;
.top_tit {
margin-left: 14px;
}
}
.con_info {
padding: 0 0 82px 67px;
.info_order {
display: flex;
font-weight: 400;
margin-top: 43px;
.order_tit {
color: #333333;
}
.order_id {
color: #999999;
}
}
.info_price {
display: flex;
font-weight: 400;
margin-top: 29px;
.price_tit {
color: #333333;
}
.price_id {
color: #999999;
}
}
.info_tips {
font-size: 14px;
font-weight: 400;
color: #999999;
margin-top: 30px;
}
.info_btn {
margin-top: 46px;
display: flex;
.btn_prev {
width: 71px;
height: 32px;
border: 1px solid #999999;
border-radius: 16px;
line-height: 32px;
font-size: 16px;
font-weight: 400;
color: #666666;
text-align: center;
cursor: pointer;
}
.btn_study {
width: 96px;
height: 32px;
background: #edb24c;
border-radius: 24px;
font-size: 16px;
font-weight: 400;
line-height: 32px;
color: #ffffff;
text-align: center;
margin-left: 21px;
cursor: pointer;
}
}
}
}
}
}
</style>
import type { RouteRecordRaw } from 'vue-router'
import AppLayout from '@/components/layout/Index.vue'
export const routes: Array<RouteRecordRaw> = [
{
path: '/shop/pay',
component: AppLayout,
children: [{ path: '/shop/pay/:id', component: () => import('./views/Index.vue'), props: true }]
}
]
<script setup lang="ts">
import Confirm from '../components/Confirm.vue'
import Order from '../components/Order.vue'
import PaySucess from '../components/PaySucess.vue'
import { useShopStore } from '@/stores/shop'
import { useDevice } from '@/composables/useDevice'
const { mobile } = useDevice()
const { shopItem } = useShopStore()
const status = ref('confirm') // confirm | order | success
const payMethod = ref(0)
const payInfo = ref({})
const handleSuccess = (data: any) => {
payMethod.value = data.payMode
status.value = data.status
}
const handleOrder = (data: any) => {
payInfo.value = data
status.value = data.status
}
const handleSuccessH5 = (data: any) => {
payInfo.value = data
status.value = data.status
}
</script>
<template>
<div class="pay_main" v-if="!mobile">
<Confirm
:shopItem="shopItem"
@success="handleSuccess"
v-if="status === 'confirm'"
/>
<Order
:shopItem="shopItem"
:payMethod="payMethod"
@update="handleOrder"
v-if="status === 'order'"
/>
<PaySucess
:shopItem="shopItem"
:payInfo="payInfo"
v-if="status === 'success'"
/>
</div>
<div v-else>
<Confirm
:shopItem="shopItem"
@success="handleSuccessH5"
v-if="status === 'confirm'"
/>
<PaySucess
:shopItem="shopItem"
:payInfo="payInfo"
v-if="status === 'success'"
/>
</div>
</template>
<style lang="scss" scoped>
.pay_main {
background: #f7f8fa;
}
</style>
<script setup lang="ts">
defineProps({
// 是否弹框
buyDialogVisible: {
type: Boolean,
required: true
}
})
const emit = defineEmits<{
(e: 'update:buyDialogVisible', buyDialogVisible: false): void
}>()
// 关闭弹框
const handleCancel = () => {
emit('update:buyDialogVisible', false)
}
</script>
<template>
<div>
<el-dialog :model-value="buyDialogVisible" width="25%" top="16%" :modal="false" :before-close="handleCancel">
<div class="buy_alert">
<img src="https://webapp-pub.ezijing.com/project_online/fi/icon_contact.png" alt="" />
<div class="alert_con">
<div class="con_tit">请联系我们</div>
<div class="con_desc">PAA秘书处:13263110169(同微信)</div>
</div>
</div>
</el-dialog>
</div>
</template>
<style lang="scss" scoped>
.buy_alert {
display: flex;
align-items: center;
.alert_con {
margin-left: 10px;
.con_tit {
font-size: 16px;
font-weight: 400;
line-height: 34px;
color: #333333;
}
.con_desc {
font-size: 14px;
font-weight: 400;
line-height: 34px;
color: #666666;
}
}
}
:deep(.el-dialog) {
width: 315px;
box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.16);
border-radius: 10px;
margin-left: 50%;
.el-dialog__header {
padding-bottom: 0;
}
}
</style>
<script lang="ts" setup>
const router = useRouter()
defineProps({
shopItem: {
type: Object
}
})
const defaultProps = {
children: 'children',
label: 'label'
}
const handleDetail = (item: any) => {
router.push(`/shop/detail/${item.id}`)
}
</script>
<template>
<div class="course_info course_info1">
<div class="info_tit">课程目录</div>
<div class="info_line"></div>
<div class="info_con1" v-if="shopItem?.type === '课程包'">
<div
class="course_list"
v-for="(item, index) in shopItem?.course_list"
:key="index"
@click="handleDetail(item)"
>
<img :src="item.image_url" alt="" />
<div class="list_info">
<div class="tit">{{ item.title }}</div>
<div class="hour">{{ item.course_hour }}</div>
</div>
</div>
</div>
<div class="info_con1" v-else>
<el-tree
:data="shopItem?.content_list"
:props="defaultProps"
accordion
highlight-current
node-key="id"
:default-expanded-keys="[shopItem?.content_list[0].id]"
>
<template #default="{ node }">
<span class="custom-tree-node">
<span class="label">{{ node.label }}</span>
<span class="icon">
<img
src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/icon_jt.png"
alt=""
/>
</span>
</span>
</template>
</el-tree>
</div>
</div>
</template>
<style lang="scss" scoped>
.course_info {
margin-top: 0.3rem;
.info_tit {
font-size: 0.28rem;
font-weight: 500;
color: #333333;
}
.info_line {
display: none;
}
.info_con1 {
padding: 0.17rem 0.2rem;
border-top: 0.06rem solid #fff5e1 !important;
border: 1px solid #fff5e1;
border-radius: 15px;
margin-top: 0.2rem;
.custom-tree-node {
.label {
width: 5rem;
display: inline-block;
}
.icon {
img {
height: 0.09rem;
}
}
}
.course_list:last-child {
border: none;
}
.course_list {
display: flex;
border-bottom: 1px solid #e8e8e8;
padding: 0.2rem 0;
box-sizing: border-box;
cursor: pointer;
img {
width: 2.2rem;
height: 1.4rem;
border-radius: 0.12rem;
}
.list_info {
height: 1.4rem;
margin-left: 0.21rem;
padding: 0.13rem 0 0.15rem 0;
display: flex;
flex-direction: column;
justify-content: space-between;
box-sizing: border-box;
.tit {
font-size: 14px;
font-weight: 400;
line-height: 20px;
color: #666666;
}
.hour {
font-size: 14px;
font-weight: 400;
line-height: 22px;
color: #999999;
}
}
}
}
}
:deep(.el-tree-node__content) {
height: 0.6rem;
margin-bottom: 0.2rem;
border-radius: 10px;
background: #f5f8fb;
}
:deep(.el-icon svg) {
display: none;
}
:deep(.el-tree-node__label) {
font-size: 0.24rem;
font-weight: 400;
line-height: 0.32rem;
color: #333333;
}
:deep(.el-tree-node__children) {
.el-tree-node__content {
background: #ffffff !important;
border-bottom: 0.01rem solid #f4f4f4;
}
.el-tree-node__label {
font-size: 0.22rem;
font-weight: 400;
line-height: 0.32rem;
color: #666666;
display: inline !important;
}
.icon {
display: none;
}
}
</style>
\ No newline at end of file
<script lang="ts" setup>
const router = useRouter()
defineProps({
shopItem: {
type: Object
}
})
const defaultProps = {
children: 'children',
label: 'label'
}
const handleDetail = (item: any) => {
router.push(`/shop/detail/${item.id}`)
}
</script>
<template>
<div class="course_info course_info1">
<div class="info_tit">课程目录</div>
<div class="info_line"></div>
<div class="info_con1" v-if="shopItem?.type === '课程包'">
<div
class="course_list"
v-for="(item, index) in shopItem?.course_list"
:key="index"
@click="handleDetail(item)"
>
<img :src="item.image_url" alt="" />
<div class="list_info">
<div class="tit">{{ item.title }}</div>
<div class="hour">{{ item.course_hour }}</div>
</div>
</div>
</div>
<div class="info_con1" v-else>
<el-tree
:data="shopItem?.content_list"
:props="defaultProps"
accordion
highlight-current
node-key="id"
:default-expanded-keys="[shopItem?.content_list[0].id]"
>
<template #default="{ node }">
<span class="custom-tree-node">
<span class="label">{{ node.label }}</span>
<span style="margin-left: 205px" class="icon">
<img
src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/icon_jt.png"
alt=""
/>
</span>
</span>
</template>
</el-tree>
</div>
</div>
</template>
<style lang="scss" scoped>
.course_info1 {
margin-top: 40px;
}
.course_info {
.info_tit {
font-size: 18px;
font-weight: 500;
color: #333333;
}
.info_line {
width: 31px;
height: 2px;
background: #c1ab85;
margin: 9px 0 0 21px;
}
.info_con {
padding: 32px 22px 30px 28px;
background-color: #f5f8fb;
margin-top: 20px;
border-radius: 16px;
font-size: 16px;
font-weight: 400;
line-height: 32px;
color: #666666;
}
.info_con1 {
margin-top: 20px;
padding: 32px 19px;
border-top: 6px solid #fff5e1 !important;
border: 1px solid #fff5e1;
border-radius: 15px;
font-size: 16px;
font-weight: 400;
line-height: 32px;
color: #333333;
.custom-tree-node {
.label {
width: 403px;
display: inline-block;
}
}
.course_list:last-child {
border: none;
}
.course_list {
display: flex;
border-bottom: 1px solid #e8e8e8;
padding: 20px 0;
box-sizing: border-box;
cursor: pointer;
img {
width: 140px;
height: 80px;
border-radius: 6px;
}
.list_info {
height: 80px;
margin-left: 14px;
padding: 14px 0 6px 0;
.tit {
font-size: 14px;
font-weight: 400;
line-height: 20px;
color: #666666;
}
.hour {
font-size: 14px;
font-weight: 400;
line-height: 22px;
color: #999999;
margin-top: 22px;
}
}
}
}
}
:deep(.el-tree-node__content) {
height: 50px;
margin-bottom: 16px;
border-radius: 10px;
background: #f5f8fb;
}
:deep(.el-icon svg) {
display: none;
}
:deep(.el-tree-node__label) {
font-size: 16px;
font-weight: 400;
line-height: 32px;
color: #333333;
}
:deep(.el-tree-node__children) {
.el-tree-node__content {
background: #ffffff !important;
border-bottom: 1px solid #f4f4f4;
}
.el-tree-node__label {
font-size: 14px;
font-weight: 400;
line-height: 32px;
color: #666666;
display: inline !important;
}
.icon {
display: none;
}
}
.is-h5 {
.info_con1 {
.custom-tree-node {
}
}
}
</style>
\ No newline at end of file
<script lang="ts" setup>
import { useDevice } from '@/composables/useDevice'
import { useUserStore } from '@/stores/user'
const user = useUserStore()
const { mobile } = useDevice()
const router = useRouter()
const props = defineProps({
payStatus: {
type: String
},
shopItem: {
type: Object
}
})
const buyDialogVisible = ref(false)
const handleBuyCourse = () => {
console.log('999')
if (user.isLogin) {
if (props.payStatus === '4' || props.shopItem?.isBuy === true) {
window.open('https://paa-learning.ezijing.com')
} else {
if (props.shopItem?.type === '课程包') {
buyDialogVisible.value = true
} else {
router.push(`/shop/pay/${props.shopItem?.id}`)
}
}
} else {
window.location.href = `${
import.meta.env.VITE_LOGIN_URL
}?rd=${encodeURIComponent(location.href)}`
}
}
</script>
<template>
<div class="detail_footer">
<div
class="left_status"
v-if="payStatus === '4' || shopItem?.isBuy === true"
>
已购买
</div>
<template v-else>
<div class="footer_left">
<div class="left_tit">全部课程价格</div>
<div class="left_desc">根据课程价格累积计算</div>
</div>
<div class="footer_price" v-if="!mobile">
<div class="price_icon">¥</div>
<div class="price_price">{{ shopItem?.price }}</div>
</div>
</template>
<div v-if="!mobile">
<div class="footer_btn" @click="handleBuyCourse">
{{
payStatus === '4' || shopItem?.isBuy === true
? '立即学习'
: '立即购买'
}}
</div>
</div>
<div v-else>
<div
class="footer_btn"
@click="handleBuyCourse"
v-if="payStatus === '4' || shopItem?.isBuy === true"
>
<div class="btn_buy">立即学习</div>
</div>
<div class="footer_btn" @click="handleBuyCourse" v-else>
<div class="footer_price">
<div class="price_icon">¥</div>
<div class="price_price">{{ shopItem?.price }}</div>
</div>
<div class="btn_buy">立即购买</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.is-pc {
.detail_footer {
width: 1200px;
height: 100px;
background: #ffffff;
box-shadow: 0px 1px 18px rgba(0, 0, 0, 0.1);
border-radius: 15px;
margin: 30px auto;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 46px 0 60px;
box-sizing: border-box;
.left_status {
font-size: 24px;
font-weight: normal;
line-height: 34px;
color: #666666;
}
.footer_left {
.left_tit {
font-size: 16px;
font-weight: 400;
line-height: 34px;
color: #333333;
}
.left_desc {
font-size: 14px;
font-weight: 400;
line-height: 34px;
color: #999999;
}
}
.footer_price {
display: flex;
margin-left: 605px;
.price_icon {
font-size: 24px;
font-weight: 500;
line-height: 34px;
color: #aa1941;
}
.price_price {
font-size: 40px;
font-weight: normal;
line-height: 34px;
color: #aa1941;
}
}
.footer_btn {
width: 144px;
height: 48px;
line-height: 48px;
background: linear-gradient(180deg, #ffe9c6 0%, #e69b1c 100%);
border-radius: 24px;
font-size: 18px;
font-weight: bold;
color: #ffffff;
text-align: center;
margin-left: 43px;
cursor: pointer;
}
}
}
.is-h5 {
.detail_footer {
border-radius: 0.2rem 0.2rem 0 0;
background: #ffffff;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.3rem;
.left_status {
font-size: 0.24rem;
font-weight: normal;
color: #666666;
}
.footer_left {
.left_tit {
font-size: 0.24rem;
color: #333333;
}
.left_desc {
font-size: 0.22rem;
color: #999999;
}
.footer_price {
display: none;
}
}
.footer_btn {
width: 4.08rem;
height: 0.8rem;
background: linear-gradient(102deg, #f2ca8c 0%, #e69b1c 100%);
border-radius: 0.4rem;
text-align: center;
line-height: 0.8rem;
color: #ffffff;
display: flex;
justify-content: space-around;
cursor: pointer;
.footer_price {
display: flex;
padding-left: 0.48rem;
margin-right: 0.18rem;
.price_icon {
font-size: 0.24rem;
color: #ffffff;
margin-top: 0.05rem;
}
.price_price {
font-size: 0.4rem;
}
}
.btn_buy {
font-size: 0.28rem;
color: #ffffff;
cursor: pointer;
}
}
}
}
</style>
\ No newline at end of file
<script lang="ts" setup>
defineProps({
shopItem: {
type: Object
}
})
</script>
<template>
<div class="course_info">
<div class="course_info course_info1">
<div class="info_tit">适用人群</div>
<div class="info_line"></div>
<div class="info_con">{{ shopItem?.for_people }}</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.is-pc{
.course_info {
margin-top: 40px;
.info_tit {
font-size: 18px;
font-weight: 500;
color: #333333;
}
.info_line {
width: 31px;
height: 2px;
background: #c1ab85;
margin: 9px 0 0 21px;
}
.info_con {
padding: 32px 22px 30px 28px;
background-color: #f5f8fb;
margin-top: 20px;
border-radius: 16px;
font-size: 16px;
font-weight: 400;
line-height: 32px;
color: #666666;
}
}
}
.is-h5{
.course_info{
.info_tit{
font-size: 0.28rem;
font-weight: 500;
color: #333333;
}
.info_line{
display: none;
}
.info_con{
padding:0.2rem;
background: #F4F8FB;
font-size: 0.24rem;
font-weight: 400;
line-height: 0.4rem;
color: #666666;
margin-top:0.2rem;
border-radius: 0.16rem;
}
}
}
</style>
\ No newline at end of file
<script lang="ts" setup>
defineProps({
shopItem: {
type: Object
}
})
</script>
<template>
<div class="course_info">
<div class="info_tit">课程介绍</div>
<div class="info_line"></div>
<div class="info_con">
{{ shopItem?.desc }}
</div>
</div>
</template>
<style lang="scss" scoped>
.course_info {
.info_tit {
font-size: 18px;
font-weight: 500;
color: #333333;
}
.info_line {
width: 31px;
height: 2px;
background: #c1ab85;
margin: 9px 0 0 21px;
}
.info_con {
padding: 32px 22px 30px 28px;
background-color: #f5f8fb;
margin-top: 20px;
border-radius: 16px;
font-size: 16px;
font-weight: 400;
line-height: 32px;
color: #666666;
}
}
.is-h5{
.course_info{
.info_tit{
font-size: 0.28rem;
font-weight: 500;
color: #333333;
}
.info_line{
display: none;
}
.info_con{
padding:0.2rem;
background: #F4F8FB;
font-size: 0.24rem;
font-weight: 400;
line-height: 0.4rem;
color: #666666;
margin-top:0.2rem;
border-radius: 0.16rem;
}
}
}
</style>
\ No newline at end of file
<script setup lang="ts">
import CourseListItem from './CourseListItem.vue'
import { useDevice } from '@/composables/useDevice'
const { mobile } = useDevice()
const props = defineProps({
courseList: {
type: Array
},
type: {
type: String
}
})
const page = reactive({
size: 10,
currentPage: 1
})
const courseListAll = $computed<any>(() => {
if (props.type) {
return props.courseList?.filter((item: any) => item.category === props.type)
} else {
return props.courseList
}
})
watch(
() => courseListAll,
() => {
return queryByPage
}
)
const courseListAllNew = ref([])
const queryByPage = $computed<any>(() => {
// 起始位置 = (当前页 - 1) x 每页的大小
const start = (page.currentPage - 1) * page.size
// 结束位置 = 当前页 x 每页的大小
const end = page.currentPage * page.size
// 返回切割数组后的数据
return courseListAll.slice(start, end)
})
courseListAllNew.value = queryByPage
// 改变每页大小的方法
const handleSizeChange = (val: number) => {
page.size = val
// courseListAllNew.value = queryByPage
console.log(courseListAllNew)
courseListAllNew.value = queryByPage
}
// 改变当前页的方法
const handleCurrentChange = (val: number) => {
page.currentPage = val
// courseListAllNew.value = queryByPage
console.log(courseListAllNew)
courseListAllNew.value = queryByPage
}
</script>
<template>
<div class="course_list" v-for="(item, index) in courseListAllNew" :key="index">
<CourseListItem :courseItem="item" :key="type"></CourseListItem>
</div>
<el-pagination
class="pagination"
layout="total, sizes, prev, pager, next, jumper"
:page-sizes="[3, 5, 10, 15, 20]"
:page-size="page.size"
:total="courseListAll.length"
v-model:currentPage="page.currentPage"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
v-if="courseListAll.length > 10 && !mobile"
>
</el-pagination>
</template>
<style lang="scss" scoped>
.pagination {
margin: 46px 204px 40px 0;
display: flex;
justify-content: flex-end;
}
.is-h5 {
.course_list {
padding: 0 0.3rem;
margin-bottom: 0.45rem;
box-sizing: border-box;
}
}
</style>
<script setup lang="ts">
import ContactDialog from '../components/ContactDialog.vue'
import { useDevice } from '@/composables/useDevice'
import { useUserStore } from '@/stores/user'
const { mobile } = useDevice()
const user = useUserStore()
const router = useRouter()
const buyDialogVisible = ref(false)
defineProps({
courseItem: {
type: Object
}
})
// 查看详情
const handleDatail = (item: any) => {
router.push({
path: `/shop/detail/${item}`
})
}
const handleBuy = (courseItem: any) => {
if (user.isLogin) {
if (courseItem?.isBuy === true) {
window.open('https://paa-learning.ezijing.com')
} else {
if (courseItem.type === '课程包') {
buyDialogVisible.value = true
} else {
router.push(`/shop/pay/${courseItem.id}`)
}
}
} else {
window.location.href = `${
import.meta.env.VITE_LOGIN_URL
}?rd=${encodeURIComponent(location.href)}`
}
}
</script>
<template>
<div class="main_tab">
<div class="tab_con">
<div class="con_left" @click="handleDatail(courseItem?.id)">
<div class="left_img">
<img :src="courseItem?.image_url" class="left_img" />
</div>
<div class="left_type">{{ courseItem?.type }}</div>
</div>
<div class="con_right">
<div class="right_top" @click="handleDatail(courseItem?.id)">
<div class="top_use">
<div class="use_icon">适用人群</div>
<div class="use_tips">{{ courseItem?.for_people }}</div>
</div>
<div class="top_tit">{{ courseItem?.title }}</div>
<div class="top_desc">
{{ courseItem?.desc }}
</div>
</div>
<div class="right_bottom">
<div class="bottom_price" v-if="!mobile">
<div class="price_icon">¥</div>
<div class="price_num">{{ courseItem?.price }}</div>
</div>
<div class="bottom_btn">
<div
class="btn_detail"
v-if="!mobile"
@click="handleDatail(courseItem?.id)"
>
查看详情
</div>
<div class="btn_buy" @click="handleBuy(courseItem)">
{{ courseItem?.isBuy === true ? '立即学习' : '立即购买' }}
</div>
</div>
</div>
</div>
</div>
<ContactDialog v-model:buyDialogVisible="buyDialogVisible" />
</div>
</template>
<style lang="scss" scoped>
.is-pc {
.main_tab {
width: 1200px;
cursor: pointer;
.tab_con {
display: flex;
padding: 40px 45px;
background: #ffffff;
border-radius: 10px;
margin-top: 20px;
box-sizing: border-box;
.con_left {
position: relative;
border-radius: 5px;
box-sizing: border-box;
cursor: pointer;
.left_img {
width: 446px;
height: 250px;
object-fit: cover;
border-radius: 5px;
}
.left_type {
width: 59px;
height: 27px;
background: rgba(255, 255, 255, 0.32);
opacity: 1;
border-radius: 3px;
font-size: 16px;
font-weight: 400;
line-height: 27px;
color: #333333;
position: absolute;
top: 10px;
right: 10px;
}
}
.con_right {
margin-left: 32px;
width: 632px;
.right_top {
cursor: pointer;
.top_use {
display: flex;
align-items: center;
.use_icon {
width: 67px;
height: 21px;
background: #f4eadb;
border-radius: 2px;
font-size: 14px;
font-weight: 400;
line-height: 21px;
color: #886426;
}
.use_tips {
font-size: 14px;
font-weight: 400;
line-height: 30px;
color: #999999;
margin-left: 10px;
}
}
.top_tit {
font-size: 24px;
font-weight: 500;
line-height: 34px;
color: #333333;
margin-top: 18px;
text-align: left;
}
.top_desc {
font-size: 16px;
font-weight: 400;
line-height: 30px;
color: #666666;
text-align: left;
margin-top: 22px;
}
}
.right_bottom {
margin-top: 53px;
display: flex;
justify-content: space-between;
.bottom_price {
display: flex;
.price_icon {
font-size: 24px;
font-weight: 500;
line-height: 34px;
color: #aa1941;
}
.price_num {
font-size: 40px;
font-weight: normal;
line-height: 34px;
color: #aa1941;
margin-left: 3px;
}
}
.bottom_btn {
display: flex;
.btn_detail {
width: 96px;
height: 32px;
background: rgba(255, 255, 255, 0.39);
border: 1px solid #e79e23;
border-radius: 16px;
font-size: 16px;
font-weight: 400;
line-height: 32px;
color: #e2971d;
cursor: pointer;
}
.btn_buy {
width: 96px;
height: 32px;
background: linear-gradient(180deg, #ffe9c6 0%, #e69b1c 100%);
border-radius: 24px;
font-size: 16px;
font-weight: 400;
line-height: 32px;
color: #ffffff;
margin-left: 20px;
cursor: pointer;
}
}
}
}
}
}
}
.is-h5 {
padding: 0 0.25rem;
.main_tab {
cursor: pointer;
.tab_con {
background: #ffffff;
opacity: 1;
border-radius: 16px;
display: flex;
margin-bottom: 0.2rem;
padding: 0.2rem;
box-sizing: border-box;
.con_left {
width: 2.2rem;
height: 1.6rem;
position: relative;
.left_img {
width: 100%;
height: 1.6rem;
border-radius: 6px;
}
.left_type {
padding: 0.03rem;
background: rgba(255, 255, 255, 0.32);
border-radius: 3px;
font-size: 0.2rem;
font-weight: 400;
color: #333333;
position: absolute;
top: 10px;
right: 10px;
}
}
.con_right {
margin-left: 0.2rem;
width: 4.2rem;
.right_top {
display: flex;
flex-direction: column-reverse;
justify-content: space-between;
padding: 0.14rem 0 0.11rem 0;
box-sizing: border-box;
.top_tit {
font-size: 0.28rem;
font-family: Source Han Sans CN;
font-weight: 500;
color: #333333;
}
.top_desc {
display: none;
}
.top_use {
.use_icon {
width: 1.2rem;
font-size: 0.2rem;
font-weight: 400;
color: #e29a21;
background: #fff3e0;
border-radius: 3px;
text-align: center;
}
.use_tips {
font-size: 0.2rem;
font-weight: 400;
color: #999999;
}
}
}
.right_bottom {
display: flex;
justify-content: flex-end;
margin-top: 0.24rem;
.bottom_btn {
.btn_buy {
width: 1.3rem;
height: 0.46rem;
background: linear-gradient(102deg, #f2ca8c 0%, #e69b1c 100%);
border-radius: 40px;
font-size: 0.24rem;
font-weight: 400;
line-height: 0.46rem;
color: #ffffff;
text-align: center;
cursor: pointer;
}
}
}
}
}
}
}
</style>
<script setup lang="ts">
import ShareDialog from './ShareDialog.vue'
import ContactDialog from '../components/ContactDialog.vue'
import { useDevice } from '@/composables/useDevice'
import { useUserStore } from '@/stores/user'
const user = useUserStore()
const { mobile } = useDevice()
const props = defineProps({
shopItem: {
type: Object
},
payStatus: {
type: String
}
})
const router = useRouter()
const shareDialogVisible = ref(false)
const buyDialogVisible = ref(false)
const handleShare = () => {
shareDialogVisible.value = true
}
const handleBuyCourse = () => {
if (user.isLogin) {
if (props.payStatus === '4' || props.shopItem?.isBuy === true) {
window.open('https://paa-learning.ezijing.com')
} else {
if (props.shopItem?.type === '课程包') {
buyDialogVisible.value = true
} else {
router.push(`/shop/pay/${props.shopItem?.id}`)
}
}
} else {
window.location.href = `${
import.meta.env.VITE_LOGIN_URL
}?rd=${encodeURIComponent(location.href)}`
}
}
</script>
<template>
<div class="detail_banner">
<div class="banner_con">
<img
class="con_img"
src="https://img1.baidu.com/it/u=3009731526,373851691&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500"
/>
<template v-if="!mobile">
<div class="con_info">
<div class="info_tit">{{ shopItem?.title }}</div>
<div class="info_indentify">{{ shopItem?.course_card }}</div>
<div class="info_tips">
<div class="tips_card">{{ shopItem?.course_chapter }}节课程</div>
<div class="tips_card">{{ shopItem?.course_total_hour }}小时</div>
</div>
</div>
<div class="con_share">
<div class="share_btn" @click="handleShare">
<img
src="https://webapp-pub.ezijing.com/project_online/fi/icon_share.png"
alt=""
/>
分享
</div>
</div>
</template>
</div>
</div>
<div class="detail_buy">
<div class="buy_left">
<div
class="left_status"
v-if="payStatus === '4' || shopItem?.isBuy === true"
>
已购买
</div>
<div class="left_price" v-else>
<div class="price_icon">¥</div>
<div class="price_num">{{ shopItem?.price }}</div>
</div>
<div class="left_tip">
<div class="tip1 tip">支付安全</div>
<div class="tip2 tip">课程回放</div>
</div>
</div>
<div class="buy_right" @click="handleBuyCourse" v-if="!mobile">
{{
payStatus === '4' || shopItem?.isBuy === true ? '立即学习' : '立即购买'
}}
</div>
</div>
<div class="detail_info" v-if="mobile">
<div class="info_top">
<div class="top_icon">适用人群</div>
<div class="top_for">{{ shopItem?.for_people }}</div>
</div>
<div class="info_tit">{{ shopItem?.title }}</div>
<div class="info_tips">{{ shopItem?.course_card }}</div>
<div class="info_time">
<div class="time_left">
<div class="left_tit">课程节数</div>
<div class="left_con">
<span class="con_num">{{ shopItem?.course_chapter }}</span>
<span class="con_txt"></span>
</div>
</div>
<div class="time_line"></div>
<div class="time_left">
<div class="left_tit">总课时</div>
<div class="left_con">
<span class="con_num">{{ shopItem?.course_total_hour }}</span>
<span class="con_txt">小时</span>
</div>
</div>
</div>
</div>
<ShareDialog v-model:shareDialogVisible="shareDialogVisible" />
<ContactDialog v-model:buyDialogVisible="buyDialogVisible" />
</template>
<style lang="scss" scoped>
.is-pc {
.detail_banner {
width: 100%;
height: 370px;
background: url('https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/course_detail_banner.jpg')
no-repeat center / 100% 100%;
.banner_con {
width: 1200px;
margin: auto;
display: flex;
padding: 60px 0 85px 0;
.con_img {
width: 400px;
height: 225px;
border-radius: 6px;
}
.con_info {
margin-left: 41px;
width: 596px;
.info_tit {
padding-top: 29px;
font-size: 24px;
font-weight: 500;
color: #333333;
}
.info_indentify {
font-size: 16px;
font-weight: 400;
color: #666666;
margin-top: 23px;
}
.info_tips {
display: flex;
margin-top: 21px;
gap: 9px;
.tips_card {
padding: 6px 9px 6px 9px;
background: #f8d394;
border-radius: 4px;
font-size: 14px;
font-weight: 400;
color: #886426;
}
}
}
.con_share {
padding-top: 29px;
cursor: pointer;
.share_btn {
padding: 0 17px;
height: 30px;
background: #ffffff;
border-radius: 16px;
font-size: 14px;
font-weight: 400;
line-height: 30px;
color: #666666;
cursor: pointer;
}
}
}
}
.detail_buy {
width: 1200px;
height: 97px;
background: #ffffff;
box-shadow: 0px 1px 18px rgba(0, 0, 0, 0.11);
border-radius: 15px;
margin: -44px auto;
border-top: 5px solid #f4b242;
padding: 0 40px 0 90px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
.buy_left {
display: flex;
align-items: center;
.left_price {
display: flex;
.price_icon {
font-size: 24px;
font-weight: 500;
line-height: 34px;
color: #aa1941;
margin-top: 6px;
}
.price_num {
font-size: 40px;
font-weight: normal;
line-height: 34px;
color: #aa1941;
margin-left: 3px;
}
}
.left_status {
font-size: 24px;
font-weight: normal;
line-height: 34px;
color: #666666;
}
.left_tip {
display: flex;
}
.tip {
padding: 4px 6px 3px 7px;
background: #f4eadb;
border-radius: 2px;
font-size: 14px;
font-weight: 400;
color: #886426;
}
.tip1 {
margin-left: 23px;
}
.tip2 {
margin-left: 10px;
}
}
.buy_right {
width: 144px;
height: 48px;
background: linear-gradient(180deg, #ffe9c6 0%, #e69b1c 100%);
border-radius: 24px;
font-size: 18px;
font-weight: bold;
line-height: 48px;
text-align: center;
color: #ffffff;
cursor: pointer;
}
}
}
.is-h5 {
.detail_banner {
.banner_con {
background: none;
.con_img {
width: 100%;
height: 3.2rem;
}
}
}
.detail_buy {
height: 0.98rem;
background: linear-gradient(270deg, #efb046 0%, #f7cb78 100%);
display: flex;
padding: 0 0.45rem;
.buy_left {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
.left_tip {
display: flex;
.tip {
background: rgba(247, 203, 119, 0.39);
font-size: 0.2rem;
font-weight: 400;
color: #b97604;
padding: 0.04rem 0.06rem;
border-radius: 4px;
}
.tip1 {
margin-right: 0.07rem;
}
}
.left_status {
font-size: 0.3rem;
color: #ffffff;
}
.left_price {
display: flex;
align-items: center;
color: #ffffff;
.price_icon {
font-size: 0.24rem;
margin: 0.1rem 0.03rem 0 0;
}
.price_num {
font-size: 0.4rem;
}
}
}
}
.detail_info {
background: #ffffff;
margin: -0.2rem 0.3rem 0.3rem 0.3rem;
padding: 0.2rem;
position: relative;
z-index: 100;
border-radius: 0.12rem;
.info_top {
display: flex;
.top_icon {
width: 1rem;
background: #fff3e0;
font-size: 0.2rem;
font-weight: 400;
color: #e5a12f;
}
.top_for {
font-size: 0.2rem;
font-weight: 400;
color: #999999;
margin-left: 0.2rem;
}
}
.info_tit {
font-size: 0.28rem;
color: #333333;
margin-top: 0.12rem;
}
.info_tips {
font-size: 0.24rem;
font-weight: 400;
color: #666666;
margin-top: 0.2rem;
}
.info_time {
height: 1rem;
background: #f4f8fb;
margin-top: 0.2rem;
padding: 0.15rem 1.2rem;
display: flex;
align-items: center;
border-radius: 0.08rem;
.time_left {
display: flex;
flex-direction: column;
align-items: center;
width: 0.96rem;
.left_tit {
font-size: 0.24rem;
font-weight: 400;
line-height: 30px;
color: #898989;
}
.left_con {
.con_num {
font-size: 0.28rem;
color: #333333;
}
.con_txt {
font-size: 0.2rem;
color: #898989;
}
}
}
.time_line {
width: 0px;
height: 0.48rem;
border: 0.01rem solid #dddddd;
margin: 0 1.1rem;
}
}
}
}
</style>
<script setup lang="ts">
const router = useRouter()
defineProps({
courseItem: {
type: Object
}
})
</script>
<template>
<div>
<div class="include_course">
<div class="course_tit">包含该课程的系列课</div>
<div class="course_card">
<div
class="card_course"
v-for="(item, index) in courseItem"
:key="index"
@click="router.push(`/shop/detail/${item?.id}`)"
>
<img
:src="
item.image_url ||
'https://img1.baidu.com/it/u=3009731526,373851691&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500'
"
/>
<div class="course_info">
<div class="info_tit">{{ item.title }}</div>
<div class="info_price">
<div class="price_icon">¥</div>
<div class="price_price">{{ item.price }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.is-pc{
.include_course {
background: #ffffff;
box-shadow: 0px 1px 18px rgba(0, 0, 0, 0.1);
border-radius: 15px;
margin-bottom: 20px;
.course_tit {
padding: 20px 0 17px 20px;
font-size: 18px;
font-weight: 500;
line-height: 34px;
color: #333333;
}
.course_card {
background: #f7f8fa;
box-sizing: border-box;
border-radius: 15px;
padding: 36px 200px 36px 36px;
box-sizing: border-box;
border-radius: 0.12rem;
.card_course {
display: flex;
background: #ffffff;
padding: 19px;
box-sizing: border-box;
border-radius: 6px;
cursor: pointer;
img {
width: 160px;
height: 90px;
border-radius: 5px;
}
.course_info {
padding-top: 10px;
margin-left: 14px;
.info_tit {
font-size: 16px;
font-weight: 400;
// line-height: 20px;
color: #666666;
}
.info_price {
display: flex;
align-items: flex-end;
margin-top: 8px;
.price_icon {
font-size: 12px;
font-weight: 500;
line-height: 34px;
color: #c1ab85;
}
.price_price {
font-size: 20px;
font-weight: normal;
line-height: 34px;
color: #c1ab85;
margin-left: 1px;
}
}
}
}
}
}
}
.is-h5{
.include_course{
margin: 0 0.3rem;
box-sizing: border-box;
border: 1px solid #FFF5E1;
border-bottom: none;
border-radius:0.12rem ;
background: #FFF5E1;
.course_tit{
height:0.6rem;
padding-left: 0.2rem;
line-height: 0.6rem;;
}
.course_card{
border-radius: 0.08rem 0.08rem 0 0;
padding:0.44rem 0;
background: #ffffff;
border-radius:0.12rem ;
}
.card_course{
display: flex;
margin:0 0.29rem ;
padding:0.25rem 0.21rem ;
background: #F4F8FB;
img{
width:1.6rem;
height: 0.9rem;
}
.course_info{
margin-left: 0.14rem;
.info_tit{
font-size: 0.24rem;
color: #333333;
}
.info_price{
display: flex;
margin-top: 0.28rem;
.price_icon{
font-size: 0.12rem;
color: #E5A12F;
}
.price_price{
font-size: 0.2rem;
color: #E5A12F;
}
}
}
}
}
}
</style>
<script setup>
import { Swiper, SwiperSlide } from 'swiper/vue'
import { Grid, Navigation } from 'swiper'
import 'swiper/css'
import 'swiper/css/grid'
import 'swiper/css/navigation'
import { useDevice } from '@/composables/useDevice'
const { mobile } = useDevice()
const router = useRouter()
defineProps({
shopRelatedList: {
type: Array
}
})
const swiper1 = ref(null)
function prev(swiper) {
swiper?.slidePrev()
}
function next(swiper) {
swiper?.slideNext()
}
const handleDetail = (item) => {
router.push(`/shop/detail/${item.id}`)
}
</script>
<template>
<div class="teacher_list">
<div class="list_con">
<div class="con_tit">相关课程推荐</div>
<div class="con_line"></div>
<div class="con_course">
<div v-if="!mobile">
<Swiper
class="my-swiper"
:grid="{ rows: 3, fill: 'column' }"
:spaceBetween="20"
:slidePreview="1"
:modules="[Navigation, Grid]"
@swiper="(swiper) => (swiper1 = swiper)"
>
<SwiperSlide
v-for="(item, index) in shopRelatedList"
:key="index"
class="course-item"
@click="handleDetail(item)"
>
<img :src="item.image_url" class="img" />
<div class="item_right">
<div class="right_name">{{ item.title }}</div>
<div class="right_price">
<div class="price_icon">¥</div>
<div class="price_num">{{ item.price }}</div>
</div>
</div>
</SwiperSlide>
</Swiper>
<template v-if="shopRelatedList.length > 3">
<div class="swiper-button-prev" @click="prev(swiper1)"></div>
<div class="swiper-button-next" @click="next(swiper1)"></div>
</template>
</div>
<div v-else>
<div
class="course-item"
v-for="(item, index) in shopRelatedList"
:key="index"
@click="handleDetail(item)"
>
<img :src="item.image_url" class="img" />
<div class="item_right">
<div class="right_name">{{ item.title }}</div>
<div class="right_price">
<div class="price_icon">¥</div>
<div class="price_num">{{ item.price }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.is-pc {
.teacher_list {
margin-top: 20px;
.list_con {
width: 396px;
height: 433px;
background: #ffffff;
box-shadow: 0px 1px 18px rgba(0, 0, 0, 0.1);
border-radius: 15px;
border-top: 6px solid #fde6c1;
padding-top: 27px;
.con_tit {
font-size: 18px;
font-weight: 500;
line-height: 34px;
color: #333333;
text-align: center;
}
.con_line {
width: 31px;
height: 2px;
background: #c1ab85;
margin: 9px 0 0 183px;
}
.con_course {
padding: 0 33px;
position: relative;
margin-top: 35px;
.course-item {
padding: 29px 27px 23px 0;
box-sizing: border-box;
display: flex;
align-items: center;
cursor: pointer;
.img {
width: 140px;
height: 80px;
border-radius: 6px;
}
.item_right {
margin-left: 14px;
.right_name {
font-size: 14px;
font-weight: 400;
color: #666666;
width: 183px;
white-space: wrap;
}
.right_price {
display: flex;
.price_icon {
font-size: 12px;
font-weight: 500;
line-height: 34px;
color: #c1ab85;
margin-top: 2px;
}
.price_num {
font-size: 16px;
font-weight: normal;
line-height: 34px;
color: #c1ab85;
}
}
}
}
}
}
}
}
.is-h5 {
.teacher_list {
padding: 0.32rem 0.2rem;
margin: 0.3rem;
background: #ffffff;
border-radius: 0.12rem;
.list_con {
.con_tit {
font-size: 0.28rem;
color: #333333;
font-weight: 500;
}
.con_line {
display: none;
}
}
.con_course {
margin-top: 0.2rem;
background: #f4f8fb;
padding: 0.2rem 0.24rem;
border-radius: 0.16rem;
.course-item:last-child {
border: none;
}
.course-item {
box-sizing: border-box;
display: flex;
align-items: center;
cursor: pointer;
border-bottom: 0.01rem solid #e5e5e5;
padding: 0.2rem 0;
.img {
width: 2.2rem;
height: 1.4rem;
border-radius: 6px;
}
.item_right {
margin-left: 0.21rem;
flex-direction: column;
justify-content: space-between;
.right_name {
font-size: 0.28rem;
font-weight: 500;
color: #333333;
width: 3.69rem;
white-space: wrap;
}
.right_price {
display: flex;
margin-top: 0.22rem;
.price_icon {
font-size: 0.2rem;
font-weight: 500;
line-height: 0.34rem;
color: #e5a12f;
}
.price_num {
font-size: 0.24rem;
font-weight: normal;
line-height: 0.34rem;
color: #e5a12f;
}
}
}
}
}
}
}
.my-swiper {
--swiper-navigation-size: 14px;
--swiper-navigation-color: #333333;
position: relative;
height: 400px;
:deep(.swiper-slide) {
height: 25%;
}
}
:deep(.swiper-button-prev) {
left: 5px;
top: -15%;
color: #333333;
}
:deep(.swiper-button-next) {
right: 5px;
top: -15%;
color: #333333;
}
:deep(.swiper-button-next:after) {
font-size: 12px;
}
:deep(.swiper-button-prev:after) {
font-size: 12px;
}
</style>
<script setup lang="ts">
import QrcodeVue from 'qrcode.vue'
const qrCodeUrl = ref(window.location.href)
defineProps({
// 是否弹框
shareDialogVisible: {
type: Boolean,
required: true
}
})
const emit = defineEmits<{
(e: 'update:shareDialogVisible', shareDialogVisible: false): void
}>()
// 关闭弹框
const handleCancel = () => {
emit('update:shareDialogVisible', false)
}
</script>
<template>
<div>
<el-dialog :model-value="shareDialogVisible" width="15%" top="15%" :modal="false" :before-close="handleCancel">
<div class="share_alert">
<!-- <img src="https://webapp-pub.ezijing.com/project_online/fi/qa_code.png" alt="" /> -->
<qrcode-vue :value="qrCodeUrl" :size="214" level="H"></qrcode-vue>
<div class="alert_con">
<img
src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/icon_weixin.png"
class="con_icon"
/>
<span class="con_tit">微信扫一扫</span>
</div>
</div>
</el-dialog>
</div>
</template>
<style lang="scss" scoped>
:deep(.el-dialog) {
width: 315px;
box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.16);
border-radius: 10px;
margin-left: 57%;
.el-dialog__header {
padding-bottom: 0;
}
}
.share_alert {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
.alert_con {
margin-top: 5px;
.con_icon {
margin-right: 7px;
}
.con_tit {
font-size: 14px;
font-weight: 400;
line-height: 24px;
color: #666666;
}
}
}
</style>
<script setup>
import { Swiper, SwiperSlide } from 'swiper/vue'
import { Grid, Navigation } from 'swiper'
import { useDevice } from '@/composables/useDevice'
const { mobile } = useDevice()
import 'swiper/css'
import 'swiper/css/grid'
import 'swiper/css/navigation'
defineProps({
lecturerList: {
type: Array
}
})
const swiper1 = ref(null)
function prev(swiper) {
console.log(swiper, '111')
swiper?.slidePrev()
}
function next(swiper) {
swiper?.slideNext()
}
const list = [
{
avatar: 'https://webapp-pub.ezijing.com/project_online/fi/teacher_01.png',
name: '张伟张伟张伟张伟张伟张伟张伟张伟张伟张伟张伟张伟',
title_list: ['清华大学国家金融研究院副院长、副研究员']
},
{
avatar: 'https://webapp-pub.ezijing.com/project_online/fi/teacher_02.png',
name: '高皓',
title_list: ['清华大学五道口金融学院全球家族企业研究中心主任']
},
{
avatar: 'https://webapp-pub.ezijing.com/project_online/fi/teacher_03.png',
name: '肇越',
title_list: ['清华大学五道口金融学院硕士生导师首席经济学家']
},
{
avatar: 'https://webapp-pub.ezijing.com/project_online/fi/teacher_04.png',
name: '陈秉正',
title_list: ['清华大学经济管理学院金融系教授', '中国保险与风险管理研究中心主任']
}
]
</script>
<template>
<div class="teacher_list" v-if="!mobile">
<div class="list_con">
<div class="con_tit">讲师介绍</div>
<div class="con_line"></div>
<div class="con_teacher">
<div>
<Swiper
class="my-swiper"
:grid="{ rows: 2, fill: 'column' }"
:spaceBetween="20"
:slidePreview="1"
:modules="[Navigation, Grid]"
@swiper="swiper => (swiper1 = swiper)"
>
<SwiperSlide v-for="(item, index) in lecturerList" :key="index" class="teacher-item">
<div class="item_top">
<img
:src="item.avatar || 'https://webapp-pub.ezijing.com/project_online/fi/teacher_04.png'"
class="top_img"
/>
<div class="top_name">{{ item.name }}</div>
</div>
<ol v-if="item.title_list?.length">
<li v-for="it in item.title_list" :key="it">
<p>
{{ it }}
</p>
</li>
</ol>
</SwiperSlide>
</Swiper>
<template v-if="lecturerList.length > 2">
<div class="swiper-button-prev" @click="prev(swiper1)"></div>
<div class="swiper-button-next" @click="next(swiper1)"></div>
</template>
</div>
</div>
</div>
</div>
<div class="teacher_list" v-else >
<div class="con_tit">讲师介绍</div>
<div class="con_teacher">
<div v-for="(item, index) in lecturerList" :key="index" class="teacher-item">
<div class="item_top">
<img
:src="item.avatar || 'https://webapp-pub.ezijing.com/project_online/fi/teacher_04.png'"
class="top_img"
/>
<div class="top_name">{{ item.name }}</div>
</div>
<ol v-if="item.title_list?.length">
<li v-for="it in item.title_list" :key="it">
<p>
{{ it }}
</p>
</li>
</ol>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.is-pc{
.teacher_list {
.list_con {
width: 396px;
height: 433px;
background: #ffffff;
box-shadow: 0px 1px 18px rgba(0, 0, 0, 0.1);
border-radius: 15px;
border-top: 6px solid #fde6c1;
padding-top: 27px;
.con_tit {
font-size: 18px;
font-weight: 500;
line-height: 34px;
color: #333333;
text-align: center;
}
.con_line {
width: 31px;
height: 2px;
background: #c1ab85;
margin: 9px 0 0 183px;
}
.con_teacher {
padding: 0 33px;
position: relative;
.teacher-item:nth-child(even) {
border-bottom: none;
}
.teacher-item:last-child {
border-bottom: none;
}
.teacher-item {
padding: 29px 27px 33px 0;
border-bottom: 1px dashed #d5d5d5;
box-sizing: border-box;
.item_top {
display: flex;
align-items: center;
.top_img {
width: 60px;
height: 60px;
}
.top_name {
font-size: 18px;
font-weight: 500;
line-height: 34px;
color: #333333;
margin-left: 13px;
}
}
ol {
margin-top: 15px;
li {
list-style-type: disc;
color: #c1ab85 !important;
margin-left: 20px;
p {
font-size: 14px;
font-weight: 400;
line-height: 22px;
color: #666666;
width: 295px;
white-space: wrap;
}
}
}
}
}
}
}
.my-swiper {
--swiper-navigation-size: 14px;
--swiper-navigation-color: #333333;
position: relative;
height: 473px;
:deep(.swiper-slide) {
height: 33%;
}
}
.swiper-button-prev {
left: 5px;
top: -6%;
color: #333333;
}
.swiper-button-next {
right: 5px;
top: -6%;
color: #333333;
}
.swiper-button-next:after {
font-size: 12px;
}
.swiper-button-prev:after {
font-size: 12px;
}
}
.is-h5{
.teacher_list {
margin-top:0.3rem;
.con_tit {
font-size: 0.28rem;
font-weight: 500;
line-height: 34px;
color: #333333;
}
.con_teacher{
overflow-x: auto;
display: flex;
.teacher-item{
width: 5.49rem;
background: #F4F8FB;
padding:0.27rem 0.2rem;
border-radius: 0.16rem;
margin-right:0.2rem;
.item_top{
display: flex;
align-items: center;
.top_img{
width:0.86rem;
}
.top_name{
font-size: 0.28rem;
color: #333333;
margin-left: 0.15rem;
}
}
ol {
margin-top: 0.2rem;
li {
list-style-type: disc;
color: #c1ab85 !important;
margin-left: 0.3rem;
p {
font-size: 0.14rem;
font-weight: 400;
color: #666666;
width: 4.89rem;
white-space: wrap;
}
}
}
}
}
}
}
</style>
import type { RouteRecordRaw } from 'vue-router'
import AppLayout from '@/components/layout/Index.vue'
export const routes: Array<RouteRecordRaw> = [
{
path: '/shop',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/Index.vue') },
{ path: '/shop/detail/:id', component: () => import('./views/View.vue'), props: true }
]
}
]
<script lang="ts" setup>
import CourseList from '../components/CourseList.vue'
import { useShopStore } from '@/stores/shop'
const shopStore = useShopStore()
const handleTabClick = (tab: any) => {
if (tab.index === '4') {
window.open('https://prp.ezijing.com')
window.location.reload()
}
}
</script>
<template>
<div class="main_shop">
<img
src="https://webapp-pub.ezijing.com/project_online/fi/shop_banner.jpg"
class="shop_banner"
/>
<div class="shop_con">
<div class="con_tab">
<el-tabs class="my-tabs" @tab-click="handleTabClick">
<el-tab-pane
v-for="(item, index) in shopStore.filters.slice(0, 4)"
:key="index"
lazy
>
<template #label>
{{ item.label }}
</template>
<CourseList
:type="item.value"
:courseList="shopStore.shopList"
:key="index"
/>
</el-tab-pane>
</el-tabs>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.is-pc {
.main_shop {
background: #f7f8fa;
margin: auto;
.shop_banner {
width: 100%;
height: 537px;
object-fit: cover;
}
.shop_con {
width: 1200px;
padding: 0 0 40px 0;
margin: -36px auto;
position: relative;
z-index: 100;
box-sizing: border-box;
.con_tab {
margin-bottom: 20px;
:deep(.my-tabs) {
text-align: center;
box-sizing: border-box;
.el-tabs__active-bar,
.el-tabs__nav-wrap::after {
display: none;
}
.el-tabs__nav {
background: #ffffff;
box-shadow: 0px 3px 18px rgba(0, 0, 0, 0.1);
border-radius: 10px;
width: 1200px;
height: 76px;
display: flex;
justify-content: space-around;
align-items: center;
border-radius: 6px;
}
.el-tabs__content {
overflow: inherit;
}
.el-tabs__nav-scroll {
display: flex;
align-items: center;
justify-content: space-around;
}
.el-tabs__item {
display: flex;
align-items: center;
justify-content: space-around;
padding: 9px 31px 10px 26px;
border-radius: 6px;
border-bottom: none;
font-size: 18px;
font-weight: 400;
color: #535353;
box-sizing: border-box;
&.is-active {
background-color: #e8c484;
color: #ffffff;
}
}
}
}
}
}
}
.is-h5 {
padding: 0 0.3rem;
box-sizing: border-box;
.main_shop {
.shop_banner {
width: 100%;
}
}
:deep(.el-tabs__item) {
font-size: 0.28rem;
font-weight: 500;
line-height: 34px;
color: #eda020;
padding: 0 0.1rem !important;
box-sizing: border-box;
}
:deep(.el-tabs__nav-scroll) {
padding: 0 0.5rem;
}
}
:deep(.el-tabs__nav-scroll) {
overflow-x: auto;
}
:deep(.el-tabs__item.is-active) {
color: #eda020;
}
:deep(.el-tabs__active-bar) {
background: #eda020;
}
:deep(.el-tabs__nav-wrap::after) {
display: none;
}
:deep(.el-tabs__nav-next) {
.el-icon {
display: none;
}
}
:deep(.el-tabs__nav-prev) {
.el-icon {
display: none;
}
}
</style>
<script lang="ts" setup>
import DetailBanner from '../components/DetailBanner.vue'
import IncludeCourseCard from '../components/IncludeCourseCard.vue'
import CourseIntrouduce from '../components/CourseIntrouduce.vue'
import CourseFor from '../components/CourseFor.vue'
import CourseCatalogPC from '../components/CourseCatalogPC.vue'
import CourseCatalogH5 from '../components/CourseCatalogH5.vue'
import TeacherCard from '../components/TeacherCard.vue'
import RecommendCourse from '../components/RecommendCourse.vue'
import CourseFooter from '../components/CourseFooter.vue'
import { useShopStore } from '@/stores/shop'
import { useDevice } from '@/composables/useDevice'
const { mobile } = useDevice()
const shopStore = useShopStore()
const route = useRoute()
const payStatus: any = ref(route.query.payStatus)
const courseItem: any = ref([]) // 课程所属课程包
courseItem.value = shopStore.shopList.filter(
(item: any) => item.type === '课程包' && item.child_ids.includes(shopStore.shopItem?.id)
)
const recommendCourse = computed(() => {
if (shopStore.shopItem?.type === '课程包') {
// 课程包推荐课程
return shopStore.shopRelatedList
} else {
// 单一课程推荐的课程
return shopStore.shopRelatedListOther
}
})
</script>
<template>
<div class="course_detail" v-if="!mobile">
<DetailBanner :shopItem="shopStore.shopItem" :payStatus="payStatus" />
<div class="detail_con">
<div class="con_left">
<div>
<IncludeCourseCard v-if="shopStore.shopItem?.type !== '课程包'" :courseItem="courseItem" />
<div class="left_course">
<CourseIntrouduce :shopItem="shopStore.shopItem"/>
<CourseFor v-if="!mobile" :shopItem="shopStore.shopItem"/>
<CourseCatalogPC :shopItem="shopStore.shopItem"/>
</div>
</div>
</div>
<div class="con_right">
<TeacherCard :lecturerList="shopStore.shopItem?.lecturer_list" />
<RecommendCourse :shopRelatedList="recommendCourse" />
</div>
</div>
<CourseFooter :payStatus="payStatus" :shopItem="shopStore.shopItem"/>
</div>
<div class="course_detail" v-else>
<DetailBanner :shopItem="shopStore.shopItem" :payStatus="payStatus"/>
<IncludeCourseCard v-if="shopStore.shopItem?.type !== '课程包'" :courseItem="courseItem" />
<div class="detail_con">
<CourseIntrouduce :shopItem="shopStore.shopItem"/>
<TeacherCard :lecturerList="shopStore.shopItem?.lecturer_list" />
<CourseCatalogH5 :shopItem="shopStore.shopItem" />
</div>
<RecommendCourse :shopRelatedList="recommendCourse" />
<CourseFooter :payStatus="payStatus" :shopItem="shopStore.shopItem"/>
</div>
</template>
<style lang="scss" scoped>
.is-pc {
.course_detail {
background: #f7f8fa;
padding-bottom: 30px;
.detail_con {
width: 1200px;
margin: 77px auto;
display: flex;
justify-content: space-between;
.con_left {
width: 784px;
.left_course{
padding: 28px 45px 53px 45px;
background: #ffffff;
box-shadow: 0px 1px 18px rgba(0, 0, 0, 0.1);
border-radius: 15px;
}
}
.con_right {
width: 396px;
}
}
.detail_footer {
width: 1200px;
height: 100px;
background: #ffffff;
box-shadow: 0px 1px 18px rgba(0, 0, 0, 0.1);
border-radius: 15px;
margin: 30px auto;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 46px 0 60px;
box-sizing: border-box;
.left_status {
font-size: 24px;
font-weight: normal;
line-height: 34px;
color: #666666;
}
.footer_left {
.left_tit {
font-size: 16px;
font-weight: 400;
line-height: 34px;
color: #333333;
}
.left_desc {
font-size: 14px;
font-weight: 400;
line-height: 34px;
color: #999999;
}
}
.footer_price {
display: flex;
margin-left: 605px;
.price_icon {
font-size: 24px;
font-weight: 500;
line-height: 34px;
color: #aa1941;
}
.price_price {
font-size: 40px;
font-weight: normal;
line-height: 34px;
color: #aa1941;
}
}
.footer_btn {
width: 144px;
height: 48px;
line-height: 48px;
background: linear-gradient(180deg, #ffe9c6 0%, #e69b1c 100%);
border-radius: 24px;
font-size: 18px;
font-weight: bold;
color: #ffffff;
text-align: center;
margin-left: 43px;
cursor: pointer;
}
}
}
}
.is-h5{
.detail_con{
background: #ffffff;
margin:0.4rem 0.3rem;
padding:0.32rem 0.2rem;
border-radius: 0.12rem;
}
}
</style>
import * as api from '@/api/base'
/**
* 获取微信openId
* */
export function getCode() {
const href = location.href.includes('?') ? `${location.href}&is_pay=true` : `${location.href}?is_pay=true`
const redirectURI = `https://pages.ezijing.com/given/auth.html?redirect_uri=${encodeURIComponent(href)}`
location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx451c01d40d090d7a&redirect_uri=${redirectURI}&response_type=code&scope=snsapi_base`
}
/**
* 获取微信openId
* */
export function getOpenId(code:any, callback:any) {
if (!code) {
return getCode()
}
api.getOpenId({ code, identity: 'ezijing' }).then((resp:any) => {
const openId = resp.data.openid
openId && localStorage.setItem('openId', openId)
callback && callback(openId)
})
}
/**
* 微信JSAPI支付
* */
export function wxJSPay(order:any, callback:any) {
if (!order.payment_more_info) {
alert('订单创建错误')
return
}
const payInfo = JSON.parse(order.payment_more_info)
WeixinJSBridge.invoke('getBrandWCPayRequest', payInfo, (resp:any) => {
callback && callback(resp)
})
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论