提交 b1e7fee3 authored 作者: matian's avatar matian

h5页面开发

上级 e06aac96
......@@ -13,6 +13,8 @@
"element-plus": "^2.2.21",
"pinia": "^2.0.24",
"qrcode.vue": "^3.3.3",
"query-string": "^7.1.1",
"querystring": "^0.2.1",
"swiper": "^8.4.4",
"vue": "^3.2.45",
"vue-router": "^4.1.6"
......@@ -1281,6 +1283,14 @@
}
}
},
"node_modules/decode-uri-component": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==",
"engines": {
"node": ">=0.10"
}
},
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
......@@ -2237,6 +2247,14 @@
"node": ">=8"
}
},
"node_modules/filter-obj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
"integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
......@@ -3562,6 +3580,32 @@
"node": ">=0.6"
}
},
"node_modules/query-string": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.1.tgz",
"integrity": "sha512-MplouLRDHBZSG9z7fpuAAcI7aAYjDLhtsiVZsevsfaHWDS2IDdORKbSd1kWUA+V4zyva/HZoSfpwnYMMQDhb0w==",
"dependencies": {
"decode-uri-component": "^0.2.0",
"filter-obj": "^1.1.0",
"split-on-first": "^1.0.0",
"strict-uri-encode": "^2.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/querystring": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz",
"integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==",
"deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
"engines": {
"node": ">=0.4.x"
}
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
......@@ -3902,6 +3946,14 @@
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
},
"node_modules/split-on-first": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
"integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==",
"engines": {
"node": ">=6"
}
},
"node_modules/ssr-window": {
"version": "4.0.2",
"resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-4.0.2.tgz",
......@@ -3938,6 +3990,14 @@
"node": ">=4.0.0"
}
},
"node_modules/strict-uri-encode": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
"integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==",
"engines": {
"node": ">=4"
}
},
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz",
......@@ -5554,6 +5614,11 @@
"ms": "2.1.2"
}
},
"decode-uri-component": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og=="
},
"deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
......@@ -6186,6 +6251,11 @@
"to-regex-range": "^5.0.1"
}
},
"filter-obj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
"integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="
},
"find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
......@@ -7209,6 +7279,22 @@
"side-channel": "^1.0.4"
}
},
"query-string": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.1.tgz",
"integrity": "sha512-MplouLRDHBZSG9z7fpuAAcI7aAYjDLhtsiVZsevsfaHWDS2IDdORKbSd1kWUA+V4zyva/HZoSfpwnYMMQDhb0w==",
"requires": {
"decode-uri-component": "^0.2.0",
"filter-obj": "^1.1.0",
"split-on-first": "^1.0.0",
"strict-uri-encode": "^2.0.0"
}
},
"querystring": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz",
"integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg=="
},
"queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
......@@ -7448,6 +7534,11 @@
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
},
"split-on-first": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
"integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="
},
"ssr-window": {
"version": "4.0.2",
"resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-4.0.2.tgz",
......@@ -7478,6 +7569,11 @@
"integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==",
"dev": true
},
"strict-uri-encode": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
"integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz",
......
......@@ -20,6 +20,8 @@
"element-plus": "^2.2.21",
"pinia": "^2.0.24",
"qrcode.vue": "^3.3.3",
"query-string": "^7.1.1",
"querystring": "^0.2.1",
"swiper": "^8.4.4",
"vue": "^3.2.45",
"vue-router": "^4.1.6"
......
......@@ -58,3 +58,13 @@ export function postNes(data: any) {
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' }
})
}
......@@ -3,22 +3,33 @@ import { ElMessage } from 'element-plus'
import { Check } from '@element-plus/icons-vue'
import { useUserStore } from '@/stores/user'
import { useDevice } from '@/composables/useDevice'
const { mobile } = useDevice()
import queryString from 'query-string'
import { getOpenId, wxJSPay } from '@/utils/wxpay'
import { createOrder, getOrderList } from '../api'
const { mobile, wechat, alipay } = useDevice()
const user = useUserStore()
defineProps({
shopItem: {
type: Object
}
})
const orderInfo: any = ref([])
const orderInfoDetail: any = ref([])
const payMode = ref(1)
const isAgree = ref(false)
const currentCheck = ref('12')
const query = $computed(() => {
return queryString.parse(location.search, { parseBooleans: true })
})
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 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
}
......@@ -27,37 +38,89 @@ const end_time = getDateTime(90)
const emit = defineEmits<{
(e: 'success', params: object): void
}>()
// 创建订单
const handleCreateOrder = () => {
if (wechat) {
const openId = localStorage.getItem('openId')
if (!openId) {
getOpenId(query.code, pay)
return Promise.reject('openId不存在')
}
pay()
} else if (alipay) {
pay()
}
}
// 去支付
function pay() {
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 (currentCheck.value === '4' && wechat) {
params.payment_method = '4'
// 微信扫码支付
} else if (currentCheck.value === '12' && alipay) {
params.payment_method = '12'
}
createOrder(params).then((order) => {
orderInfo.value = order
if (wechat) {
wxJSPay(order, getOrder())
} else if (alipay) {
location.href = orderInfo.value[0]?.payment_url
}
})
}
// 获取订单
function getOrder() {
return getOrderList({
order_detail_id: orderInfo.value[0].order_detail_id
}).then((resp) => {
orderInfoDetail.value = resp.data[0]
const params = {
status: 'success',
orderId: orderInfoDetail.value.order_id,
payPrice: orderInfoDetail.value.payment_money,
payStatus: orderInfoDetail.value.order_status
}
emit('success', params)
})
}
const handlePay = () => {
if (isAgree.value === false) {
ElMessage.warning('请先勾选紫荆金保服务协议')
} else {
if (user.isLogin) {
if(mobile){
const params = {
payMode: currentCheck.value,
status: 'success'
}
emit('success', params)
}else{
if (mobile) {
handleCreateOrder()
} else {
const params = {
payMode: payMode.value,
status: 'order'
}
emit('success', params)
}
} else {
window.location.href = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(location.href)}`
window.location.href = `${
import.meta.env.VITE_LOGIN_URL
}?rd=${encodeURIComponent(location.href)}`
}
}
}
const checkdChange = (val:string) => {
const checkdChange = (val: string) => {
currentCheck.value = val
}
</script>
<template>
<div >
<div>
<div class="main_con" v-if="!mobile">
<div class="con_tit">课程信息确认</div>
<div class="con_pay">
......@@ -68,24 +131,32 @@ const checkdChange = (val:string) => {
/>
<div class="course_info">
<div class="info_tit">{{ shopItem?.title }}</div>
<div class="info_range">有效期:{{ start_time }}{{ end_time }}</div>
<div class="info_range">
有效期:{{ start_time }}{{ end_time }}
</div>
<div class="info_price">
<div class="price_icon">¥</div>
<div class="price_num">{{ shopItem?.price }}</div>
</div>
</div>
</div>
<div class="con_message" v-if="user.isLogin">课程提醒将发送到您的手机:{{ user?.mobile }}</div>
<div class="con_message" v-if="user.isLogin">
课程提醒将发送到您的手机:{{ user?.mobile }}
</div>
<div class="con_mode">
<div class="mode_tit">支付方式</div>
<div class="mode_radio">
<el-radio-group v-model="payMode">
<el-radio :label="1" size="large" border>
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/pay_ali.png" />
<img
src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/pay_ali.png"
/>
<span class="radio_tit">支付宝支付</span>
</el-radio>
<el-radio :label="2" size="large" border>
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/pay_wechat.png" />
<img
src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/pay_wechat.png"
/>
<span class="radio_tit">微信支付</span>
</el-radio>
</el-radio-group>
......@@ -94,10 +165,18 @@ const checkdChange = (val:string) => {
<div class="con_footer">
<div class="footer_left">
<el-checkbox v-model="isAgree"
><span style="color: #666666; font-size: 16px; font-weight: 400">同意</span
><a style="color: #e3a232; font-size: 16px; font-weight: 400">紫荆金保服务协议</a></el-checkbox
><span style="color: #666666; font-size: 16px; font-weight: 400"
>同意</span
><a style="color: #e3a232; font-size: 16px; font-weight: 400"
>紫荆金保服务协议</a
></el-checkbox
>
<div class="left_desc" :class="isAgree === false ? 'left_desc_active' : ''">请先勾选紫荆金保服务协议</div>
<div
class="left_desc"
:class="isAgree === false ? 'left_desc_active' : ''"
>
请先勾选紫荆金保服务协议
</div>
</div>
<div class="footer_right">
<div class="right_top">
......@@ -114,7 +193,11 @@ const checkdChange = (val:string) => {
</div>
<div class="main_con" v-else>
<div class="con_nav">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/prev_mini.png" alt="" srcset="">
<img
src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/prev_mini.png"
alt=""
srcset=""
/>
<div class="nav_title">确认订单</div>
</div>
<div class="course_con">
......@@ -124,26 +207,44 @@ const checkdChange = (val:string) => {
/>
<div class="course_dec">
<div class="info_title">{{ shopItem?.title }}</div>
<div class="info_date">有效期:{{ start_time }}{{ end_time }}</div>
</div>
<div class="info_date">
有效期:{{ start_time }}{{ end_time }}
</div>
</div>
</div>
<div class="pay_con">
<div class="pay_phone">课程提醒将发送到您的手机:<i style="font-weight: bold;">13900012345</i></div>
<div class="pay_phone">
课程提醒将发送到您的手机:<i style="font-weight: bold">13900012345</i>
</div>
<div class="pay_line"></div>
<div class="pay_mode">
<div class="mode_item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/pay_ali.png" />
<img
src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/pay_ali.png"
/>
<div class="radio_tit">支付宝支付</div>
<div :class="currentCheck === '12' ? 'radio_check_active':'radio_check'" @click="checkdChange('12')">
<div
:class="
currentCheck === '12' ? 'radio_check_active' : 'radio_check'
"
@click="checkdChange('12')"
>
<template v-if="currentCheck === '12'">
<el-icon><Check /></el-icon>
</template>
</div>
</div>
<div class="mode_item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/pay_wechat.png" />
<img
src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/pay_wechat.png"
/>
<div class="radio_tit">微信支付</div>
<div :class="currentCheck === '4' ? 'radio_check_active':'radio_check'" @click="checkdChange('4')">
<div
:class="
currentCheck === '4' ? 'radio_check_active' : 'radio_check'
"
@click="checkdChange('4')"
>
<template v-if="currentCheck === '4'">
<el-icon><Check /></el-icon>
</template>
......@@ -152,16 +253,24 @@ const checkdChange = (val:string) => {
</div>
</div>
<div class="argreement_con">
<el-checkbox v-model="isAgree"
><span style="color: #666666; font-size: 16px; font-weight: 400">同意</span
><a style="color: #e3a232; font-size: 16px; font-weight: 400">紫荆金保服务协议</a></el-checkbox
>
<div class="left_desc" :class="isAgree === false ? 'left_desc_active' : ''">请先勾选紫荆金保服务协议</div>
<el-checkbox v-model="isAgree"
><span style="color: #666666; font-size: 16px; font-weight: 400"
>同意</span
><a style="color: #e3a232; font-size: 16px; font-weight: 400"
>紫荆金保服务协议</a
></el-checkbox
>
<div
class="left_desc"
:class="isAgree === false ? 'left_desc_active' : ''"
>
请先勾选紫荆金保服务协议
</div>
</div>
<div class="to_pay_main" @click="handlePay">
<div class="pay_price">
<span class="to_pay">立即支付</span>
<span class="to_price"><i style="font-size: 12px;">¥</i>1999.00</span>
<span class="to_price"><i style="font-size: 12px">¥</i>1999.00</span>
</div>
</div>
</div>
......@@ -170,28 +279,28 @@ const checkdChange = (val:string) => {
<style lang="scss" scoped>
.is-h5 {
.main_con{
.main_con {
padding: 0 0.28rem;
.con_nav{
.con_nav {
display: flex;
align-items: center;
justify-content: center;
position: relative;
img{
img {
position: absolute;
left:0;
left: 0;
}
.nav_title{
.nav_title {
font-size: 0.32rem;
font-weight: 500;
line-height: 0.34rem;
color: #333333;
}
}
.course_con{
.course_con {
margin: 0.3rem 0;
height: 1.97rem;
background: #FFFFFF;
background: #ffffff;
opacity: 1;
border-radius: 0.12rem;
display: flex;
......@@ -199,23 +308,23 @@ const checkdChange = (val:string) => {
justify-content: space-between;
padding: 0.28rem 0.2rem;
box-sizing: border-box;
gap:0.2rem;
img{
gap: 0.2rem;
img {
width: 2.2rem;
height: 1.4rem;
}
.course_dec{
.course_dec {
display: flex;
flex-direction: column;
gap:0.2rem;
.info_title{
gap: 0.2rem;
.info_title {
height: 0.64rem;
font-size: 0.28rem;
font-weight: 500;
line-height: 0.36rem;
color: #333333;
}
.info_date{
.info_date {
height: 0.22rem;
font-size: 0.22rem;
font-weight: 400;
......@@ -224,40 +333,40 @@ const checkdChange = (val:string) => {
}
}
}
.pay_con{
width: 6.90rem;
.pay_con {
width: 6.9rem;
box-sizing: border-box;
margin-bottom: 0.53rem;
background: #fff;
border-radius: 0.12rem;
padding: 0.54rem 0.4rem;
.pay_phone{
.pay_phone {
text-align: center;
font-size: 0.24rem;
color: #333333;
}
.pay_line{
.pay_line {
height: 0px;
border: 1px solid #F8F8F8;
border: 1px solid #f8f8f8;
opacity: 1;
margin: 0.57rem 0 0.54rem 0;
margin: 0.57rem 0 0.54rem 0;
}
.pay_mode{
.pay_mode {
display: flex;
flex-direction: column;
gap: 0.4rem;
.mode_item{
.mode_item {
display: flex;
align-items: center;
position: relative;
img{
img {
width: 0.3rem;
height: 0.3rem;
}
.radio_tit{
.radio_tit {
margin-left: 0.2rem;
}
.radio_check_active{
.radio_check_active {
position: absolute;
right: 0;
width: 0.25rem;
......@@ -267,10 +376,10 @@ const checkdChange = (val:string) => {
align-items: center;
font-size: 12px;
color: #fff;
background-color: #F1B44E;
background-color: #f1b44e;
box-sizing: border-box;
}
.radio_check{
.radio_check {
position: absolute;
right: 0;
width: 0.25rem;
......@@ -286,14 +395,14 @@ const checkdChange = (val:string) => {
}
}
}
.argreement_con{
text-align: center;
.left_desc{
color: #8888;
margin-left: 0.3rem;
}
.argreement_con {
text-align: center;
.left_desc {
color: #8888;
margin-left: 0.3rem;
}
}
.to_pay_main{
.to_pay_main {
position: fixed;
bottom: 0;
left: 0;
......@@ -305,20 +414,20 @@ const checkdChange = (val:string) => {
border-radius: 0.2rem 0.2rem 0px 0px;
padding: 0.24rem 0.3rem 0.16rem 0.3rem;
box-sizing: border-box;
.pay_price{
.pay_price {
width: 100%;
height: 0.8rem;
background: linear-gradient(102deg, #F2CA8C 0%, #E69B1C 100%);
background: linear-gradient(102deg, #f2ca8c 0%, #e69b1c 100%);
border-radius: 0.4rem;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
gap:0.18rem;
.to_pay{
gap: 0.18rem;
.to_pay {
font-size: 0.28rem;
}
.to_price{
.to_price {
font-size: 0.4rem;
}
}
......@@ -327,149 +436,149 @@ const checkdChange = (val:string) => {
}
.is-pc {
.main_con {
width: 1200px;
margin: auto;
width: 1200px;
margin: auto;
.con_tit {
font-size: 28px;
font-weight: 500;
line-height: 34px;
color: #333333;
padding-top: 39px;
}
.con_pay {
height: 721px;
background: #ffffff;
margin-top: 26px;
padding: 52px 60px 107px 40px;
box-sizing: border-box;
.pay_course {
display: flex;
padding-bottom: 41px;
border-bottom: 1px solid #e6e6e6;
.con_tit {
font-size: 28px;
font-weight: 500;
line-height: 34px;
color: #333333;
padding-top: 39px;
}
.con_pay {
height: 721px;
background: #ffffff;
margin-top: 26px;
padding: 52px 60px 107px 40px;
box-sizing: border-box;
.pay_course {
display: flex;
padding-bottom: 41px;
border-bottom: 1px solid #e6e6e6;
img {
width: 257px;
height: 166px;
}
.course_info {
margin-left: 35px;
.info_tit {
font-size: 24px;
font-weight: 500;
line-height: 34px;
color: #333333;
img {
width: 257px;
height: 166px;
}
.info_range {
font-size: 14px;
font-weight: 400;
line-height: 34px;
color: #666666;
margin-top: 26px;
}
.info_price {
display: flex;
align-items: flex-end;
margin-top: 42px;
.price_icon {
font-size: 20px;
.course_info {
margin-left: 35px;
.info_tit {
font-size: 24px;
font-weight: 500;
color: #aa1941;
line-height: 34px;
color: #333333;
}
.price_num {
font-size: 30px;
font-weight: normal;
.info_range {
font-size: 14px;
font-weight: 400;
line-height: 34px;
color: #aa1941;
color: #666666;
margin-top: 26px;
}
.info_price {
display: flex;
align-items: flex-end;
margin-top: 42px;
.price_icon {
font-size: 20px;
font-weight: 500;
color: #aa1941;
}
.price_num {
font-size: 30px;
font-weight: normal;
line-height: 34px;
color: #aa1941;
}
}
}
}
}
}
.con_message {
margin-top: 30px;
font-size: 18px;
font-weight: 500;
line-height: 34px;
color: #333333;
}
.con_mode {
margin-top: 43px;
display: flex;
align-items: center;
.mode_tit {
font-size: 16px;
font-weight: 400;
.con_message {
margin-top: 30px;
font-size: 18px;
font-weight: 500;
line-height: 34px;
color: #333333;
}
.mode_radio {
margin-left: 44px;
}
}
.con_footer {
margin-top: 74px;
display: flex;
justify-content: space-between;
.footer_left {
padding-top: 12px;
.left_desc {
font-size: 14px;
.con_mode {
margin-top: 43px;
display: flex;
align-items: center;
.mode_tit {
font-size: 16px;
font-weight: 400;
color: #999999;
margin: 14px 0 0 21px;
line-height: 34px;
color: #333333;
}
.left_desc_active {
color: #aa1941;
.mode_radio {
margin-left: 44px;
}
}
.footer_right {
.con_footer {
margin-top: 74px;
display: flex;
flex-direction: column;
align-items: flex-end;
.right_top {
display: flex;
.top_tit {
font-size: 16px;
justify-content: space-between;
.footer_left {
padding-top: 12px;
.left_desc {
font-size: 14px;
font-weight: 400;
line-height: 34px;
color: #333333;
color: #999999;
margin: 14px 0 0 21px;
}
.left_desc_active {
color: #aa1941;
}
.top_price {
}
.footer_right {
display: flex;
flex-direction: column;
align-items: flex-end;
.right_top {
display: flex;
margin-left: 53px;
.price_icon {
font-size: 22px;
font-weight: 500;
.top_tit {
font-size: 16px;
font-weight: 400;
line-height: 34px;
color: #aa1941;
color: #333333;
}
.price_num {
font-size: 36px;
font-weight: normal;
line-height: 34px;
color: #aa1941;
.top_price {
display: flex;
margin-left: 53px;
.price_icon {
font-size: 22px;
font-weight: 500;
line-height: 34px;
color: #aa1941;
}
.price_num {
font-size: 36px;
font-weight: normal;
line-height: 34px;
color: #aa1941;
}
}
}
}
.right_btn {
width: 153px;
height: 48px;
background: #edb24c;
border-radius: 24px;
font-size: 18px;
font-weight: 400;
line-height: 48px;
color: #ffffff;
text-align: center;
margin-top: 20px;
cursor: pointer;
.right_btn {
width: 153px;
height: 48px;
background: #edb24c;
border-radius: 24px;
font-size: 18px;
font-weight: 400;
line-height: 48px;
color: #ffffff;
text-align: center;
margin-top: 20px;
cursor: pointer;
}
}
}
}
}
}
:deep(.el-radio) {
width: 220px;
......
......@@ -50,7 +50,7 @@ onMounted(() => {
})
const handleGetOrderList = (id: any) => {
getOrderList({ order_detail_id: id }).then(res => {
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') {
......@@ -78,7 +78,7 @@ const handleGetOrderList = (id: any) => {
<div class="price_tit">支付金额:</div>
<div class="price_con">
<div class="con_icon">¥</div>
<div class="con_num">1999.00</div>
<div class="con_num">{{ shopItem?.price }}</div>
</div>
</div>
<div class="line"></div>
......@@ -93,8 +93,13 @@ const handleGetOrderList = (id: any) => {
"
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" />
<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">
......@@ -102,8 +107,15 @@ const handleGetOrderList = (id: any) => {
<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
class="left_desc"
:class="payMethod === 1 ? 'left_desc_ali' : 'left_desc_wechat'"
>
{{
payMethod === 1
? '请打开手机支付宝,扫一扫完成支付'
: '请打开手机微信,扫一扫完成支付'
}}
</div>
</div>
<img
......
<script setup lang="ts">
import { useDevice } from "@/composables/useDevice";
const { mobile } = useDevice();
const router = useRouter();
import { useDevice } from '@/composables/useDevice'
const { mobile } = useDevice()
const router = useRouter()
const props = defineProps({
payInfo: {
type: Object,
type: Object
},
shopItem: {
type: Object,
},
});
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");
};
window.open('https://paa-learning.ezijing.com')
}
const handlePrev = () => {
router.push({
path: `/shop/detail/${props.shopItem?.id}`,
query: {
payStatus: props.payInfo?.payStatus,
},
});
};
payStatus: props.payInfo?.payStatus
}
})
}
</script>
<template>
......@@ -78,16 +91,22 @@ const handlePrev = () => {
/>
<div class="course_dec">
<div class="info_title">{{ shopItem?.title }}</div>
<div class="info_date">有效期: 2022-11-11 至 2022-11-11</div>
<div class="info_date">有效期:{{ start_time }}{{ end_time }}</div>
</div>
</div>
<div class="order_main">
<div class="order_num">商品订单:<span>GN390001234512345</span></div>
<div class="order_price">支付金额:<span>¥1999.00</span></div>
<div class="order_after_sales">若有疑问请与客服联系,我们将尽快为您提供服务</div>
<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 class="study_con" @click="handleStudy">开始学习</div>
</div>
</div>
</template>
......@@ -153,7 +172,7 @@ const handlePrev = () => {
}
}
}
.order_main{
.order_main {
width: 100%;
background: #fff;
border-radius: 0.12rem;
......@@ -162,35 +181,36 @@ const handlePrev = () => {
box-sizing: border-box;
display: flex;
flex-direction: column;
gap:0.36rem;
gap: 0.36rem;
font-weight: 400;
.order_num,.order_price{
.order_num,
.order_price {
font-size: 0.24rem;
color: #333;
span{
span {
color: #999;
}
}
.order_after_sales{
.order_after_sales {
font-size: 0.22rem;
color: #999;
}
}
.start_study{
.start_study {
display: flex;
align-items: center;
justify-content: center;
.study_con{
width: 6.10rem;
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;
}
.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;
}
}
}
}
......
......@@ -3,12 +3,13 @@ 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) => {
console.log(data,'123')
payMethod.value = data.payMode
status.value = data.status
}
......@@ -16,13 +17,43 @@ 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">
<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 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>
......
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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论