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

h5页面开发

上级 e06aac96
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
"element-plus": "^2.2.21", "element-plus": "^2.2.21",
"pinia": "^2.0.24", "pinia": "^2.0.24",
"qrcode.vue": "^3.3.3", "qrcode.vue": "^3.3.3",
"query-string": "^7.1.1",
"querystring": "^0.2.1",
"swiper": "^8.4.4", "swiper": "^8.4.4",
"vue": "^3.2.45", "vue": "^3.2.45",
"vue-router": "^4.1.6" "vue-router": "^4.1.6"
...@@ -1281,6 +1283,14 @@ ...@@ -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": { "node_modules/deep-is": {
"version": "0.1.4", "version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
...@@ -2237,6 +2247,14 @@ ...@@ -2237,6 +2247,14 @@
"node": ">=8" "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": { "node_modules/find-up": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
...@@ -3562,6 +3580,32 @@ ...@@ -3562,6 +3580,32 @@
"node": ">=0.6" "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": { "node_modules/queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
...@@ -3902,6 +3946,14 @@ ...@@ -3902,6 +3946,14 @@
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" "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": { "node_modules/ssr-window": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-4.0.2.tgz", "resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-4.0.2.tgz",
...@@ -3938,6 +3990,14 @@ ...@@ -3938,6 +3990,14 @@
"node": ">=4.0.0" "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": { "node_modules/string_decoder": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz",
...@@ -5554,6 +5614,11 @@ ...@@ -5554,6 +5614,11 @@
"ms": "2.1.2" "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": { "deep-is": {
"version": "0.1.4", "version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
...@@ -6186,6 +6251,11 @@ ...@@ -6186,6 +6251,11 @@
"to-regex-range": "^5.0.1" "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": { "find-up": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
...@@ -7209,6 +7279,22 @@ ...@@ -7209,6 +7279,22 @@
"side-channel": "^1.0.4" "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": { "queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
...@@ -7448,6 +7534,11 @@ ...@@ -7448,6 +7534,11 @@
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" "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": { "ssr-window": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-4.0.2.tgz", "resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-4.0.2.tgz",
...@@ -7478,6 +7569,11 @@ ...@@ -7478,6 +7569,11 @@
"integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==", "integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==",
"dev": true "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": { "string_decoder": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz",
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
"element-plus": "^2.2.21", "element-plus": "^2.2.21",
"pinia": "^2.0.24", "pinia": "^2.0.24",
"qrcode.vue": "^3.3.3", "qrcode.vue": "^3.3.3",
"query-string": "^7.1.1",
"querystring": "^0.2.1",
"swiper": "^8.4.4", "swiper": "^8.4.4",
"vue": "^3.2.45", "vue": "^3.2.45",
"vue-router": "^4.1.6" "vue-router": "^4.1.6"
......
...@@ -58,3 +58,13 @@ export function postNes(data: any) { ...@@ -58,3 +58,13 @@ 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' }
})
}
...@@ -3,22 +3,33 @@ import { ElMessage } from 'element-plus' ...@@ -3,22 +3,33 @@ import { ElMessage } from 'element-plus'
import { Check } from '@element-plus/icons-vue' import { Check } from '@element-plus/icons-vue'
import { useUserStore } from '@/stores/user' import { useUserStore } from '@/stores/user'
import { useDevice } from '@/composables/useDevice' 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() const user = useUserStore()
defineProps({ defineProps({
shopItem: { shopItem: {
type: Object type: Object
} }
}) })
const orderInfo: any = ref([])
const orderInfoDetail: any = ref([])
const payMode = ref(1) const payMode = ref(1)
const isAgree = ref(false) const isAgree = ref(false)
const currentCheck = ref('12') const currentCheck = ref('12')
const query = $computed(() => {
return queryString.parse(location.search, { parseBooleans: true })
})
function getDateTime(dayNum: any) { function getDateTime(dayNum: any) {
const dateDay = new Date() const dateDay = new Date()
dateDay.setDate(dateDay.getDate() + dayNum) //获取dayNum天后的日期 dateDay.setDate(dateDay.getDate() + dayNum) //获取dayNum天后的日期
console.log(dateDay) console.log(dateDay)
const y = dateDay.getFullYear() 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 const d = dateDay.getDate() < 10 ? '0' + dateDay.getDate() : dateDay.getDate() //获取当前几号,不足10补0
return y + '-' + m + '-' + d return y + '-' + m + '-' + d
} }
...@@ -27,37 +38,89 @@ const end_time = getDateTime(90) ...@@ -27,37 +38,89 @@ const end_time = getDateTime(90)
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'success', params: object): void (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 = () => { const handlePay = () => {
if (isAgree.value === false) { if (isAgree.value === false) {
ElMessage.warning('请先勾选紫荆金保服务协议') ElMessage.warning('请先勾选紫荆金保服务协议')
} else { } else {
if (user.isLogin) { if (user.isLogin) {
if(mobile){ if (mobile) {
const params = { handleCreateOrder()
payMode: currentCheck.value, } else {
status: 'success'
}
emit('success', params)
}else{
const params = { const params = {
payMode: payMode.value, payMode: payMode.value,
status: 'order' status: 'order'
} }
emit('success', params) emit('success', params)
} }
} else { } 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 currentCheck.value = val
} }
</script> </script>
<template> <template>
<div > <div>
<div class="main_con" v-if="!mobile"> <div class="main_con" v-if="!mobile">
<div class="con_tit">课程信息确认</div> <div class="con_tit">课程信息确认</div>
<div class="con_pay"> <div class="con_pay">
...@@ -68,24 +131,32 @@ const checkdChange = (val:string) => { ...@@ -68,24 +131,32 @@ const checkdChange = (val:string) => {
/> />
<div class="course_info"> <div class="course_info">
<div class="info_tit">{{ shopItem?.title }}</div> <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="info_price">
<div class="price_icon">¥</div> <div class="price_icon">¥</div>
<div class="price_num">{{ shopItem?.price }}</div> <div class="price_num">{{ shopItem?.price }}</div>
</div> </div>
</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="con_mode">
<div class="mode_tit">支付方式</div> <div class="mode_tit">支付方式</div>
<div class="mode_radio"> <div class="mode_radio">
<el-radio-group v-model="payMode"> <el-radio-group v-model="payMode">
<el-radio :label="1" size="large" border> <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> <span class="radio_tit">支付宝支付</span>
</el-radio> </el-radio>
<el-radio :label="2" size="large" border> <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> <span class="radio_tit">微信支付</span>
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
...@@ -94,10 +165,18 @@ const checkdChange = (val:string) => { ...@@ -94,10 +165,18 @@ const checkdChange = (val:string) => {
<div class="con_footer"> <div class="con_footer">
<div class="footer_left"> <div class="footer_left">
<el-checkbox v-model="isAgree" <el-checkbox v-model="isAgree"
><span style="color: #666666; font-size: 16px; font-weight: 400">同意</span ><span style="color: #666666; font-size: 16px; font-weight: 400"
><a style="color: #e3a232; font-size: 16px; font-weight: 400">紫荆金保服务协议</a></el-checkbox >同意</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>
<div class="footer_right"> <div class="footer_right">
<div class="right_top"> <div class="right_top">
...@@ -114,7 +193,11 @@ const checkdChange = (val:string) => { ...@@ -114,7 +193,11 @@ const checkdChange = (val:string) => {
</div> </div>
<div class="main_con" v-else> <div class="main_con" v-else>
<div class="con_nav"> <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 class="nav_title">确认订单</div>
</div> </div>
<div class="course_con"> <div class="course_con">
...@@ -124,26 +207,44 @@ const checkdChange = (val:string) => { ...@@ -124,26 +207,44 @@ const checkdChange = (val:string) => {
/> />
<div class="course_dec"> <div class="course_dec">
<div class="info_title">{{ shopItem?.title }}</div> <div class="info_title">{{ shopItem?.title }}</div>
<div class="info_date">有效期:{{ start_time }}{{ end_time }}</div> <div class="info_date">
</div> 有效期:{{ start_time }}{{ end_time }}
</div>
</div>
</div> </div>
<div class="pay_con"> <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_line"></div>
<div class="pay_mode"> <div class="pay_mode">
<div class="mode_item"> <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="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'"> <template v-if="currentCheck === '12'">
<el-icon><Check /></el-icon> <el-icon><Check /></el-icon>
</template> </template>
</div> </div>
</div> </div>
<div class="mode_item"> <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="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'"> <template v-if="currentCheck === '4'">
<el-icon><Check /></el-icon> <el-icon><Check /></el-icon>
</template> </template>
...@@ -152,16 +253,24 @@ const checkdChange = (val:string) => { ...@@ -152,16 +253,24 @@ const checkdChange = (val:string) => {
</div> </div>
</div> </div>
<div class="argreement_con"> <div class="argreement_con">
<el-checkbox v-model="isAgree" <el-checkbox v-model="isAgree"
><span style="color: #666666; font-size: 16px; font-weight: 400">同意</span ><span style="color: #666666; font-size: 16px; font-weight: 400"
><a style="color: #e3a232; font-size: 16px; font-weight: 400">紫荆金保服务协议</a></el-checkbox >同意</span
> ><a style="color: #e3a232; font-size: 16px; font-weight: 400"
<div class="left_desc" :class="isAgree === false ? 'left_desc_active' : ''">请先勾选紫荆金保服务协议</div> >紫荆金保服务协议</a
></el-checkbox
>
<div
class="left_desc"
:class="isAgree === false ? 'left_desc_active' : ''"
>
请先勾选紫荆金保服务协议
</div>
</div> </div>
<div class="to_pay_main" @click="handlePay"> <div class="to_pay_main" @click="handlePay">
<div class="pay_price"> <div class="pay_price">
<span class="to_pay">立即支付</span> <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> </div>
</div> </div>
...@@ -170,28 +279,28 @@ const checkdChange = (val:string) => { ...@@ -170,28 +279,28 @@ const checkdChange = (val:string) => {
<style lang="scss" scoped> <style lang="scss" scoped>
.is-h5 { .is-h5 {
.main_con{ .main_con {
padding: 0 0.28rem; padding: 0 0.28rem;
.con_nav{ .con_nav {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
position: relative; position: relative;
img{ img {
position: absolute; position: absolute;
left:0; left: 0;
} }
.nav_title{ .nav_title {
font-size: 0.32rem; font-size: 0.32rem;
font-weight: 500; font-weight: 500;
line-height: 0.34rem; line-height: 0.34rem;
color: #333333; color: #333333;
} }
} }
.course_con{ .course_con {
margin: 0.3rem 0; margin: 0.3rem 0;
height: 1.97rem; height: 1.97rem;
background: #FFFFFF; background: #ffffff;
opacity: 1; opacity: 1;
border-radius: 0.12rem; border-radius: 0.12rem;
display: flex; display: flex;
...@@ -199,23 +308,23 @@ const checkdChange = (val:string) => { ...@@ -199,23 +308,23 @@ const checkdChange = (val:string) => {
justify-content: space-between; justify-content: space-between;
padding: 0.28rem 0.2rem; padding: 0.28rem 0.2rem;
box-sizing: border-box; box-sizing: border-box;
gap:0.2rem; gap: 0.2rem;
img{ img {
width: 2.2rem; width: 2.2rem;
height: 1.4rem; height: 1.4rem;
} }
.course_dec{ .course_dec {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap:0.2rem; gap: 0.2rem;
.info_title{ .info_title {
height: 0.64rem; height: 0.64rem;
font-size: 0.28rem; font-size: 0.28rem;
font-weight: 500; font-weight: 500;
line-height: 0.36rem; line-height: 0.36rem;
color: #333333; color: #333333;
} }
.info_date{ .info_date {
height: 0.22rem; height: 0.22rem;
font-size: 0.22rem; font-size: 0.22rem;
font-weight: 400; font-weight: 400;
...@@ -224,40 +333,40 @@ const checkdChange = (val:string) => { ...@@ -224,40 +333,40 @@ const checkdChange = (val:string) => {
} }
} }
} }
.pay_con{ .pay_con {
width: 6.90rem; width: 6.9rem;
box-sizing: border-box; box-sizing: border-box;
margin-bottom: 0.53rem; margin-bottom: 0.53rem;
background: #fff; background: #fff;
border-radius: 0.12rem; border-radius: 0.12rem;
padding: 0.54rem 0.4rem; padding: 0.54rem 0.4rem;
.pay_phone{ .pay_phone {
text-align: center; text-align: center;
font-size: 0.24rem; font-size: 0.24rem;
color: #333333; color: #333333;
} }
.pay_line{ .pay_line {
height: 0px; height: 0px;
border: 1px solid #F8F8F8; border: 1px solid #f8f8f8;
opacity: 1; opacity: 1;
margin: 0.57rem 0 0.54rem 0; margin: 0.57rem 0 0.54rem 0;
} }
.pay_mode{ .pay_mode {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.4rem; gap: 0.4rem;
.mode_item{ .mode_item {
display: flex; display: flex;
align-items: center; align-items: center;
position: relative; position: relative;
img{ img {
width: 0.3rem; width: 0.3rem;
height: 0.3rem; height: 0.3rem;
} }
.radio_tit{ .radio_tit {
margin-left: 0.2rem; margin-left: 0.2rem;
} }
.radio_check_active{ .radio_check_active {
position: absolute; position: absolute;
right: 0; right: 0;
width: 0.25rem; width: 0.25rem;
...@@ -267,10 +376,10 @@ const checkdChange = (val:string) => { ...@@ -267,10 +376,10 @@ const checkdChange = (val:string) => {
align-items: center; align-items: center;
font-size: 12px; font-size: 12px;
color: #fff; color: #fff;
background-color: #F1B44E; background-color: #f1b44e;
box-sizing: border-box; box-sizing: border-box;
} }
.radio_check{ .radio_check {
position: absolute; position: absolute;
right: 0; right: 0;
width: 0.25rem; width: 0.25rem;
...@@ -286,14 +395,14 @@ const checkdChange = (val:string) => { ...@@ -286,14 +395,14 @@ const checkdChange = (val:string) => {
} }
} }
} }
.argreement_con{ .argreement_con {
text-align: center; text-align: center;
.left_desc{ .left_desc {
color: #8888; color: #8888;
margin-left: 0.3rem; margin-left: 0.3rem;
} }
} }
.to_pay_main{ .to_pay_main {
position: fixed; position: fixed;
bottom: 0; bottom: 0;
left: 0; left: 0;
...@@ -305,20 +414,20 @@ const checkdChange = (val:string) => { ...@@ -305,20 +414,20 @@ const checkdChange = (val:string) => {
border-radius: 0.2rem 0.2rem 0px 0px; border-radius: 0.2rem 0.2rem 0px 0px;
padding: 0.24rem 0.3rem 0.16rem 0.3rem; padding: 0.24rem 0.3rem 0.16rem 0.3rem;
box-sizing: border-box; box-sizing: border-box;
.pay_price{ .pay_price {
width: 100%; width: 100%;
height: 0.8rem; height: 0.8rem;
background: linear-gradient(102deg, #F2CA8C 0%, #E69B1C 100%); background: linear-gradient(102deg, #f2ca8c 0%, #e69b1c 100%);
border-radius: 0.4rem; border-radius: 0.4rem;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
color: #fff; color: #fff;
gap:0.18rem; gap: 0.18rem;
.to_pay{ .to_pay {
font-size: 0.28rem; font-size: 0.28rem;
} }
.to_price{ .to_price {
font-size: 0.4rem; font-size: 0.4rem;
} }
} }
...@@ -327,149 +436,149 @@ const checkdChange = (val:string) => { ...@@ -327,149 +436,149 @@ const checkdChange = (val:string) => {
} }
.is-pc { .is-pc {
.main_con { .main_con {
width: 1200px; width: 1200px;
margin: auto; margin: auto;
.con_tit { .con_tit {
font-size: 28px; font-size: 28px;
font-weight: 500; font-weight: 500;
line-height: 34px; line-height: 34px;
color: #333333; color: #333333;
padding-top: 39px; padding-top: 39px;
} }
.con_pay { .con_pay {
height: 721px; height: 721px;
background: #ffffff; background: #ffffff;
margin-top: 26px; margin-top: 26px;
padding: 52px 60px 107px 40px; padding: 52px 60px 107px 40px;
box-sizing: border-box; box-sizing: border-box;
.pay_course { .pay_course {
display: flex; display: flex;
padding-bottom: 41px; padding-bottom: 41px;
border-bottom: 1px solid #e6e6e6; border-bottom: 1px solid #e6e6e6;
img { img {
width: 257px; width: 257px;
height: 166px; height: 166px;
}
.course_info {
margin-left: 35px;
.info_tit {
font-size: 24px;
font-weight: 500;
line-height: 34px;
color: #333333;
} }
.info_range { .course_info {
font-size: 14px; margin-left: 35px;
font-weight: 400; .info_tit {
line-height: 34px; font-size: 24px;
color: #666666;
margin-top: 26px;
}
.info_price {
display: flex;
align-items: flex-end;
margin-top: 42px;
.price_icon {
font-size: 20px;
font-weight: 500; font-weight: 500;
color: #aa1941; line-height: 34px;
color: #333333;
} }
.price_num { .info_range {
font-size: 30px; font-size: 14px;
font-weight: normal; font-weight: 400;
line-height: 34px; 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 {
.con_message { margin-top: 30px;
margin-top: 30px; font-size: 18px;
font-size: 18px; font-weight: 500;
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;
line-height: 34px; line-height: 34px;
color: #333333; color: #333333;
} }
.mode_radio { .con_mode {
margin-left: 44px; margin-top: 43px;
} display: flex;
} align-items: center;
.con_footer { .mode_tit {
margin-top: 74px; font-size: 16px;
display: flex;
justify-content: space-between;
.footer_left {
padding-top: 12px;
.left_desc {
font-size: 14px;
font-weight: 400; font-weight: 400;
color: #999999; line-height: 34px;
margin: 14px 0 0 21px; color: #333333;
} }
.left_desc_active { .mode_radio {
color: #aa1941; margin-left: 44px;
} }
} }
.con_footer {
.footer_right { margin-top: 74px;
display: flex; display: flex;
flex-direction: column; justify-content: space-between;
align-items: flex-end; .footer_left {
.right_top { padding-top: 12px;
display: flex; .left_desc {
.top_tit { font-size: 14px;
font-size: 16px;
font-weight: 400; font-weight: 400;
line-height: 34px; color: #999999;
color: #333333; 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; display: flex;
margin-left: 53px; .top_tit {
.price_icon { font-size: 16px;
font-size: 22px; font-weight: 400;
font-weight: 500;
line-height: 34px; line-height: 34px;
color: #aa1941; color: #333333;
} }
.price_num { .top_price {
font-size: 36px; display: flex;
font-weight: normal; margin-left: 53px;
line-height: 34px; .price_icon {
color: #aa1941; 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 {
.right_btn { width: 153px;
width: 153px; height: 48px;
height: 48px; background: #edb24c;
background: #edb24c; border-radius: 24px;
border-radius: 24px; font-size: 18px;
font-size: 18px; font-weight: 400;
font-weight: 400; line-height: 48px;
line-height: 48px; color: #ffffff;
color: #ffffff; text-align: center;
text-align: center; margin-top: 20px;
margin-top: 20px; cursor: pointer;
cursor: pointer; }
} }
} }
} }
} }
}
:deep(.el-radio) { :deep(.el-radio) {
width: 220px; width: 220px;
......
...@@ -50,7 +50,7 @@ onMounted(() => { ...@@ -50,7 +50,7 @@ onMounted(() => {
}) })
const handleGetOrderList = (id: any) => { 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 payStatus.value = res.data[0].order_status
orderId.value = res.data[0].order_id orderId.value = res.data[0].order_id
if (payStatus.value === '4') { if (payStatus.value === '4') {
...@@ -78,7 +78,7 @@ const handleGetOrderList = (id: any) => { ...@@ -78,7 +78,7 @@ const handleGetOrderList = (id: any) => {
<div class="price_tit">支付金额:</div> <div class="price_tit">支付金额:</div>
<div class="price_con"> <div class="price_con">
<div class="con_icon">¥</div> <div class="con_icon">¥</div>
<div class="con_num">1999.00</div> <div class="con_num">{{ shopItem?.price }}</div>
</div> </div>
</div> </div>
<div class="line"></div> <div class="line"></div>
...@@ -93,8 +93,13 @@ const handleGetOrderList = (id: any) => { ...@@ -93,8 +93,13 @@ const handleGetOrderList = (id: any) => {
" "
class="con_style" class="con_style"
/> />
<span class="radio_tit">{{ payMethod === 1 ? '支付宝支付' : '微信支付' }}</span> <span class="radio_tit">{{
<img src="https://webapp-pub.ezijing.com/project_online/fi/icon_pay_checked.png" class="checked_img" /> payMethod === 1 ? '支付宝支付' : '微信支付'
}}</span>
<img
src="https://webapp-pub.ezijing.com/project_online/fi/icon_pay_checked.png"
class="checked_img"
/>
</div> </div>
</div> </div>
<div class="order_qaCode"> <div class="order_qaCode">
...@@ -102,8 +107,15 @@ const handleGetOrderList = (id: any) => { ...@@ -102,8 +107,15 @@ const handleGetOrderList = (id: any) => {
<div class="left_code"> <div class="left_code">
<qrcode-vue :value="qrCodeUrl" :size="197" level="H"></qrcode-vue> <qrcode-vue :value="qrCodeUrl" :size="197" level="H"></qrcode-vue>
</div> </div>
<div class="left_desc" :class="payMethod === 1 ? 'left_desc_ali' : 'left_desc_wechat'"> <div
{{ payMethod === 1 ? '请打开手机支付宝,扫一扫完成支付' : '请打开手机微信,扫一扫完成支付' }} class="left_desc"
:class="payMethod === 1 ? 'left_desc_ali' : 'left_desc_wechat'"
>
{{
payMethod === 1
? '请打开手机支付宝,扫一扫完成支付'
: '请打开手机微信,扫一扫完成支付'
}}
</div> </div>
</div> </div>
<img <img
......
<script setup lang="ts"> <script setup lang="ts">
import { useDevice } from "@/composables/useDevice"; import { useDevice } from '@/composables/useDevice'
const { mobile } = useDevice(); const { mobile } = useDevice()
const router = useRouter()
const router = useRouter();
const props = defineProps({ const props = defineProps({
payInfo: { payInfo: {
type: Object, type: Object
}, },
shopItem: { 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 = () => { const handleStudy = () => {
window.open("https://paa-learning.ezijing.com"); window.open('https://paa-learning.ezijing.com')
}; }
const handlePrev = () => { const handlePrev = () => {
router.push({ router.push({
path: `/shop/detail/${props.shopItem?.id}`, path: `/shop/detail/${props.shopItem?.id}`,
query: { query: {
payStatus: props.payInfo?.payStatus, payStatus: props.payInfo?.payStatus
}, }
}); })
}; }
</script> </script>
<template> <template>
...@@ -78,16 +91,22 @@ const handlePrev = () => { ...@@ -78,16 +91,22 @@ const handlePrev = () => {
/> />
<div class="course_dec"> <div class="course_dec">
<div class="info_title">{{ shopItem?.title }}</div> <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> </div>
<div class="order_main"> <div class="order_main">
<div class="order_num">商品订单:<span>GN390001234512345</span></div> <div class="order_num">
<div class="order_price">支付金额:<span>¥1999.00</span></div> 商品订单:<span>{{ payInfo?.orderId }}</span>
<div class="order_after_sales">若有疑问请与客服联系,我们将尽快为您提供服务</div> </div>
<div class="order_price">
支付金额:<span>{{ payInfo?.payPrice }}</span>
</div>
<div class="order_after_sales">
若有疑问请与客服联系,我们将尽快为您提供服务
</div>
</div> </div>
<div class="start_study"> <div class="start_study">
<div class="study_con" @click="handleStudy">开始学习</div> <div class="study_con" @click="handleStudy">开始学习</div>
</div> </div>
</div> </div>
</template> </template>
...@@ -153,7 +172,7 @@ const handlePrev = () => { ...@@ -153,7 +172,7 @@ const handlePrev = () => {
} }
} }
} }
.order_main{ .order_main {
width: 100%; width: 100%;
background: #fff; background: #fff;
border-radius: 0.12rem; border-radius: 0.12rem;
...@@ -162,35 +181,36 @@ const handlePrev = () => { ...@@ -162,35 +181,36 @@ const handlePrev = () => {
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap:0.36rem; gap: 0.36rem;
font-weight: 400; font-weight: 400;
.order_num,.order_price{ .order_num,
.order_price {
font-size: 0.24rem; font-size: 0.24rem;
color: #333; color: #333;
span{ span {
color: #999; color: #999;
} }
} }
.order_after_sales{ .order_after_sales {
font-size: 0.22rem; font-size: 0.22rem;
color: #999; color: #999;
} }
} }
.start_study{ .start_study {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
.study_con{ .study_con {
width: 6.10rem; width: 6.1rem;
height: 0.8rem; height: 0.8rem;
background: linear-gradient(102deg, #F2CA8C 0%, #E69B1C 100%); background: linear-gradient(102deg, #f2ca8c 0%, #e69b1c 100%);
opacity: 1; opacity: 1;
border-radius: 0.4rem; border-radius: 0.4rem;
text-align: center; text-align: center;
line-height: 0.8rem; line-height: 0.8rem;
color: #fff; color: #fff;
font-size: 0.28rem; font-size: 0.28rem;
} }
} }
} }
} }
......
...@@ -3,12 +3,13 @@ import Confirm from '../components/Confirm.vue' ...@@ -3,12 +3,13 @@ import Confirm from '../components/Confirm.vue'
import Order from '../components/Order.vue' import Order from '../components/Order.vue'
import PaySucess from '../components/PaySucess.vue' import PaySucess from '../components/PaySucess.vue'
import { useShopStore } from '@/stores/shop' import { useShopStore } from '@/stores/shop'
import { useDevice } from '@/composables/useDevice'
const { mobile } = useDevice()
const { shopItem } = useShopStore() const { shopItem } = useShopStore()
const status = ref('confirm') // confirm | order | success const status = ref('confirm') // confirm | order | success
const payMethod = ref(0) const payMethod = ref(0)
const payInfo = ref({}) const payInfo = ref({})
const handleSuccess = (data: any) => { const handleSuccess = (data: any) => {
console.log(data,'123')
payMethod.value = data.payMode payMethod.value = data.payMode
status.value = data.status status.value = data.status
} }
...@@ -16,13 +17,43 @@ const handleOrder = (data: any) => { ...@@ -16,13 +17,43 @@ const handleOrder = (data: any) => {
payInfo.value = data payInfo.value = data
status.value = data.status status.value = data.status
} }
const handleSuccessH5 = (data: any) => {
payInfo.value = data
status.value = data.status
}
</script> </script>
<template> <template>
<div class="pay_main"> <div class="pay_main" v-if="!mobile">
<Confirm :shopItem="shopItem" @success="handleSuccess" v-if="status === 'confirm'" /> <Confirm
<Order :shopItem="shopItem" :payMethod="payMethod" @update="handleOrder" v-if="status === 'order'" /> :shopItem="shopItem"
<PaySucess :shopItem="shopItem" :payInfo="payInfo" v-if="status === 'success'" /> @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> </div>
</template> </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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论