Commit 7900ec19 authored by FE-安焕焕's avatar FE-安焕焕 👣

Merge branch 'pay' into 'master'

Pay

See merge request !4
parents 6aa1b0ca 8a43632a
...@@ -1159,9 +1159,9 @@ ...@@ -1159,9 +1159,9 @@
} }
}, },
"@qg/ui-request": { "@qg/ui-request": {
"version": "0.0.8", "version": "0.0.15",
"resolved": "http://npmprivate.quantgroups.com/@qg%2fui-request/-/ui-request-0.0.8.tgz", "resolved": "http://npmprivate.quantgroups.com/@qg%2fui-request/-/ui-request-0.0.15.tgz",
"integrity": "sha512-BeS7fWiTM5uI/FzGpZ5phuU0ZQXWsjX5LDiMq6FhMz5IXQthd3gMn+Q1DyYF6YyQI6rG9eDq18CMvWMdkbtt/Q==", "integrity": "sha512-ZYR/7NMFDY0NBU0B71D3/ENdI29YTKhmk0BE68IFlt63rPwKXeUWzUtmfsA1Wgx/iMkNE8qfJMKt7lPLreYYWA==",
"requires": { "requires": {
"axios": "^0.19.2" "axios": "^0.19.2"
} }
...@@ -3973,9 +3973,9 @@ ...@@ -3973,9 +3973,9 @@
} }
}, },
"crypto-js": { "crypto-js": {
"version": "3.1.9-1", "version": "3.3.0",
"resolved": "http://npmprivate.quantgroups.com/crypto-js/-/crypto-js-3.1.9-1.tgz", "resolved": "http://npmprivate.quantgroups.com/crypto-js/-/crypto-js-3.3.0.tgz",
"integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" "integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q=="
}, },
"css": { "css": {
"version": "2.2.4", "version": "2.2.4",
......
...@@ -19,10 +19,11 @@ export default { ...@@ -19,10 +19,11 @@ export default {
}, },
// 订单详情查询接口 // 订单详情查询接口
orderDetail(data) { orderDetail(data) {
return http.get(`${talosHost}/api/kdsp/order-info/virtual-recharge/detail`, data); return http.get(`${talosHost}/api/kdsp/order-info/virtual-recharge/detail`, { params: data });
}, },
// 订单创建 // 订单创建
orderCreate(data) { orderCreate(data) {
return http.post(`${talosHost}/api/kdsp/order-info/e/vmSubmit`, { data: encryption(data) }); console.log(data);
return http.post(`${talosHost}/api/kdsp/order-info/e/vmSubmit`, encryption(data));
} }
}; };
import request from '@/service/httpDecorator'; import request from '@/service/httpDecorator';
import config from '@/config'; import config from '@/config';
import { encryption } from '@/service/encrypt'; import { saDeviceId } from '@/service/sa.service';
const { talosHost } = config; const { talosHost } = config;
const queryPayInfo = function(data) { const queryPayInfo = function(data) {
return request.post(`${talosHost}/open/checkout`, data); return request.post(`${talosHost}/open/checkout`, data);
}; };
const prepay = function(data) { const prepay = async function(data) {
console.log('prepay-param', data); const scDeviceId = await saDeviceId();
return request.post(`${talosHost}/open/checkout/prepay`, data); return request.post(`${talosHost}/open/checkout/prepay`, data, {
customHeader: {
scDeviceId
}
});
}; };
const pay = function(data) { const pay = async function(data) {
return request.post( const scDeviceId = await saDeviceId();
`${talosHost}/open/checkout/pay`, return request.post(`${talosHost}/open/checkout/pay`, data, {
{ data: encryption(data) }, customHeader: {
{ scDeviceId
needScDeviceId: true
} }
); });
}; };
const queryPayStatus = function(data) { const queryPayStatus = function(data) {
...@@ -52,6 +55,11 @@ const getGoodsList = function(data) { ...@@ -52,6 +55,11 @@ const getGoodsList = function(data) {
}); });
}; };
// KA流程节点
const kaGetNextUrl = function() {
return request.get(`${talosHost}/api/kdsp/ka/process/get-next-url`);
};
export { export {
pay, pay,
prepay, prepay,
...@@ -62,5 +70,6 @@ export { ...@@ -62,5 +70,6 @@ export {
ocrFaceId, ocrFaceId,
queryPayInfo, queryPayInfo,
getGoodsList, getGoodsList,
kaGetNextUrl,
queryPayStatus queryPayStatus
}; };
export default { export default {
101: `<p>充值类商品售出<strong>后无法进行退换</strong>,非充值用户请谨慎购买。</p>`, 1: {
102: `<p>充值类商品售出<strong>后无法进行退换</strong>,非充值用户请谨慎购买。</p>` title: '温馨提示',
content: `<p>充值类商品售出后无法进行退换,非充值用户请谨慎购买。</p>`
},
2: {
title: '温馨提示',
content: `<p>充值类商品售出后无法进行退换,非充值用户请谨慎购买。</p>`
},
401: {
title: '使用方法',
content: `<p>1. 进入猫眼APP,登陆后打开“我的”,点击“优惠券”;</p>
<p>2. 进入“优惠券”,在页面上方白框中输入13位优惠券密码,点击“添加”即可;</p>
<p>3. 返回,选定场次并完成选座;</p>
<p>4. 核对购票信息、结算金额,点击“确认支付”完成选座购票;</p>
<p>5. 用户到影城“取票机”取票即可使用。</p>`
},
301: {
title: '使用方法',
content: `<p>1. 进入饿了么APP-选择我的-点击会员,使用兑换码兑换会员,输入兑换码即可兑换;</p>
<p>2. 饿了么月度会员含4个5元的红包总计20元,全品类通用(早餐及帮买帮送等特殊订单除外),红包仅限购买会员时选择的城市使用;</p>
<p>3. 每完成1笔在线订单(实际支付金额大于等于20元),即可获得1个奖励金,奖励金可累计并兑换各种无门槛红包及高额商家红包。</p>`
}
}; };
...@@ -26,9 +26,6 @@ export default { ...@@ -26,9 +26,6 @@ export default {
components: { components: {
Items Items
}, },
// props: {
// list: Array
// },
data() { data() {
return { return {
finished: true, finished: true,
...@@ -48,11 +45,14 @@ export default { ...@@ -48,11 +45,14 @@ export default {
return this.list.filter((item, index) => index % 2); return this.list.filter((item, index) => index % 2);
} }
}, },
mounted() {
this.onLoad();
},
methods: { methods: {
async onLoad() { async onLoad() {
this.loading = true; this.loading = true;
const [data = {}] = await getGoodsList({ pageNo: 1, pageSize: 10 }); const [data = {}] = await getGoodsList({ pageNo: 1, pageSize: 10 });
this.list = [...this.list, ...data?.goodsList]; this.list = [...this.list, ...(data?.goodsList ?? [])];
this.loading = false; this.loading = false;
} }
} }
......
...@@ -14,6 +14,7 @@ let protocol = window.location.protocol; ...@@ -14,6 +14,7 @@ let protocol = window.location.protocol;
let payHost = protocol + '//mapi-qa.liangkebang.net/pay'; let payHost = protocol + '//mapi-qa.liangkebang.net/pay';
let shenceHost = 'https://bn.xyqb.com/sa?project=default'; // 测试地址 let shenceHost = 'https://bn.xyqb.com/sa?project=default'; // 测试地址
let talosHost = 'http://yapi.quantgroups.com/mock/351'; // 电商分期测试环境服务地址 let talosHost = 'http://talos-vcc2.liangkebang.net'; // 电商分期测试环境服务地址
let operatorHost = 'https://operator.liangkebang.com'; let operatorHost = 'https://operator.liangkebang.com';
export default { talosHost, operatorHost, payHost, shenceHost, test: true }; const toBHost = 'https://tob.liangkebang.net';
export default { talosHost, operatorHost, payHost, shenceHost, test: true, toBHost };
...@@ -4,11 +4,13 @@ const operatorHost = protocol + '//auth.quantgroup.cn'; ...@@ -4,11 +4,13 @@ const operatorHost = protocol + '//auth.quantgroup.cn';
// const payHost = protocol + '//mapi.q-gp.com/pay'; // const payHost = protocol + '//mapi.q-gp.com/pay';
const payHost = protocol + '//payapi.xyqb.com'; const payHost = protocol + '//payapi.xyqb.com';
const shenceHost = 'https://bn.xyqb.com/sa?project=production'; const shenceHost = 'https://bn.xyqb.com/sa?project=production';
const toBHost = 'https://tob.liangkebang.net';
export default { export default {
// apiHost, // apiHost,
test: false, test: false,
shenceHost, shenceHost,
talosHost, talosHost,
payHost, payHost,
toBHost,
operatorHost operatorHost
}; };
...@@ -20,6 +20,7 @@ if (process.env.SENTRY_ENV !== 'test' && process.env.NODE_ENV === 'production') ...@@ -20,6 +20,7 @@ if (process.env.SENTRY_ENV !== 'test' && process.env.NODE_ENV === 'production')
.install(); .install();
} }
Vue.prototype.util = new Bridge(); Vue.prototype.util = new Bridge();
window.Bridge = Bridge;
saService.init(router); saService.init(router);
......
...@@ -39,6 +39,7 @@ export function encryption(data = '') { ...@@ -39,6 +39,7 @@ export function encryption(data = '') {
* @return {String} 加密后的数据16进制 * @return {String} 加密后的数据16进制
*/ */
export async function encryptByDESModeEBC(message) { export async function encryptByDESModeEBC(message) {
console.log(message);
const [{ payPwdSalt }] = await desSalt(); const [{ payPwdSalt }] = await desSalt();
var keyHex = CryptoJS.enc.Utf8.parse(payPwdSalt); var keyHex = CryptoJS.enc.Utf8.parse(payPwdSalt);
var encrypted = CryptoJS.DES.encrypt(message, keyHex, { var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
......
import HttpRequest from '@qg/ui-request'; import HttpRequest from '@qg/ui-request';
import { Toast } from '@qg/cherry-ui'; import { Toast } from '@qg/cherry-ui';
import store from '@/store'; import store from '@/store';
import { appVersion } from '@/service/validation.service';
const http = new HttpRequest( const http = new HttpRequest(
{}, {},
{}, {
headers: {
'x-user-terminal': 'H5',
version: appVersion || '7.9.0'
}
},
function(msg) { function(msg) {
Toast(msg); Toast(msg);
}, },
......
...@@ -14,6 +14,7 @@ const localStorageParams = [ ...@@ -14,6 +14,7 @@ const localStorageParams = [
'formXcxPage' 'formXcxPage'
]; ];
const cookiesParams = ['h']; const cookiesParams = ['h'];
const sessionStorageParams = ['target'];
export default { export default {
// token校验,整个流程都是登陆后的 // token校验,整个流程都是登陆后的
...@@ -28,7 +29,9 @@ export default { ...@@ -28,7 +29,9 @@ export default {
cookiesParams.forEach(item => { cookiesParams.forEach(item => {
to.query[item] && Cookies.set(item, to.query[item]); to.query[item] && Cookies.set(item, to.query[item]);
}); });
sessionStorageParams.forEach(item => {
to.query[item] && localStorage.set(item, to.query[item], 'sessionStorage');
});
(isWechat || isApp || Cookies.get('h') === '0') && store.commit('CHANGE_HEADER', false); // 改变header (isWechat || isApp || Cookies.get('h') === '0') && store.commit('CHANGE_HEADER', false); // 改变header
document.body.className = store.state.pay.header ? 'has-header' : ''; document.body.className = store.state.pay.header ? 'has-header' : '';
store.commit('CHANGE_TITLE', meta?.title); // 改变title store.commit('CHANGE_TITLE', meta?.title); // 改变title
......
export default { export default {
get(key) { get(key, storageType = 'localStorage') {
let result = window.localStorage.getItem(key); let result = window[storageType].getItem(key);
try { try {
return JSON.parse(result); return JSON.parse(result);
} catch (e) { } catch (e) {
return result; return result;
} }
}, },
set(key, value) { set(key, value, storageType = 'localStorage') {
let toString = Object.prototype.toString; let toString = Object.prototype.toString;
if (toString.call(value) === '[object Array]' || toString.call(value) === '[object Object]') { if (toString.call(value) === '[object Array]' || toString.call(value) === '[object Object]') {
value = JSON.stringify(value); value = JSON.stringify(value);
} }
return window.localStorage.setItem(key, value); return window[storageType].setItem(key, value);
}, },
remove(key) { remove(key, storageType = 'localStorage') {
return window.localStorage.removeItem(key); return window[storageType].removeItem(key);
}, },
clear() { clear(storageType = 'localStorage') {
return window.localStorage.clear(); return window[storageType].clear();
} }
}; };
...@@ -77,12 +77,12 @@ function payByWeixinH5(info) { ...@@ -77,12 +77,12 @@ function payByWeixinH5(info) {
* @return: * @return:
*/ */
function payByALIH5(info) { function payByALIH5(info) {
if (!info.order_string) return; if (!info.url) return;
console.log('ali:', info.order_string); console.log('ali:', info.url);
const aliWrap = document.createElement('div'); const aliWrap = document.createElement('div');
aliWrap.id = 'ALIWEB_WRAP'; aliWrap.id = 'ALIWEB_WRAP';
aliWrap.setAttribute('id', 'ALIWEB_WRAP'); aliWrap.setAttribute('id', 'ALIWEB_WRAP');
aliWrap.innerHTML = info.order_string; aliWrap.innerHTML = info.url;
document.body.appendChild(aliWrap); document.body.appendChild(aliWrap);
document.forms[0].submit(); document.forms[0].submit();
......
import { isAndroid, isIOS } from './validation.service'; import { isAndroid, isIOS, isApp } from './validation.service';
import Clipboard from 'clipboard'; import Clipboard from 'clipboard';
/** /**
...@@ -378,3 +378,53 @@ export function setClipboardData( ...@@ -378,3 +378,53 @@ export function setClipboardData(
fakeEl.click(); fakeEl.click();
document.body.removeChild(fakeEl); document.body.removeChild(fakeEl);
} }
export function getTokenFromNative() {
return new Promise((resolve, reject) => {
if (!isApp) {
reject();
console.log('not app or wxmp');
navToDlApp();
return;
}
const nativeBridge = new window.Bridge();
window.xyqbNativeEvent = function(res) {
const json = typeof res === 'string' ? JSON.parse(res) : res;
if (json.event === 'getTokenSuccess') {
const appData = json.data || {};
if (appData && appData.token) {
localStorage.set('vccToken', appData.token);
resolve(true);
} else {
reject();
}
} else {
reject();
}
};
nativeBridge.getToken();
});
}
export function navToDlApp() {
window.location.href = 'xyqb://openApp';
setTimeout(() => {
window.location.href = APP_DOWN_URL;
const nextPage = document.createElement('a');
nextPage.setAttribute('href', APP_DOWN_URL);
nextPage.click();
}, 2000);
}
export const APP_DOWN_URL = 'https://misc.lkbang.net/download/yxm.html';
export function throttle(fn, wait) {
let flag = true;
return function() {
if (flag) {
fn.apply(this, arguments);
flag = false;
setTimeout(() => {
flag = true;
}, wait);
}
};
}
...@@ -109,4 +109,10 @@ strong { ...@@ -109,4 +109,10 @@ strong {
.text-14(); .text-14();
margin-bottom: @padding-xs; margin-bottom: @padding-xs;
} }
}
.cr-dialog--header {
padding: @padding-xl;
&--isolated {
padding-bottom: 0;
}
} }
\ No newline at end of file
...@@ -31,15 +31,13 @@ ...@@ -31,15 +31,13 @@
@cell-clear-color: @gray-4; @cell-clear-color: @gray-4;
@field-label-width: 75px; @field-label-width: 75px;
@dialog-width: 290px;
@dialog-font-size: 14px;
@dialog-border-radius: @border-radius-lg; @dialog-border-radius: @border-radius-lg;
@dialog-message-font-size: 16px; @dialog-has-title-message-text-color: @text-grey;
@dialog-has-title-message-text-color: @text-color;
@dialog-confirm-button-text-color: @red;
@navbar-default-height: @nav-bar-height; @navbar-default-height: @nav-bar-height;
@picker-toolbar-padding: @padding-unit - 2 @padding-md; @picker-toolbar-padding: @padding-unit - 2 @padding-md;
@picker-font-size: 14px; @picker-font-size: 14px;
@tabs-nav-background-color: @background-color; @tabs-nav-background-color: @background-color;
\ No newline at end of file
@loading-text-color: @white;
\ No newline at end of file
<template> <template>
<p class="center-phone"> <div class="center-phone">
<span v-if="rechargeTel" class="center-phone-location" <span v-if="rechargeTel" class="center-phone-location"
>{{ isDefaultphone ? '默认号码' : '未知号码' >{{ isDefaultphone ? '默认号码' : '未知号码'
}}{{ phoneNoHome ? `(${phoneNoHome})` : '' }}</span }}{{ phoneNoHome ? `(${phoneNoHome})` : '' }}</span
...@@ -10,9 +10,21 @@ ...@@ -10,9 +10,21 @@
class="center-phone-field" class="center-phone-field"
placeholder="请输入手机号码" placeholder="请输入手机号码"
@input="changeTelFormat" @input="changeTelFormat"
@blur="searchPhoneNoHome" @blur="searchPhoneNo(rechargeTel)"
@focus="inputBlur = true"
/> />
</p> <div class="center-phone__list" :class="{ show: inputBlur }">
<div
v-for="(item, index) in historyPhoneNoList"
:key="index"
class="center-phone__list-item"
@click="selectPhone(item)"
>
<span class="phone">{{ phoneFormat(item) }}</span>
<span v-if="index === 0" class="current">上次充值</span>
</div>
</div>
</div>
</template> </template>
<script> <script>
import api from '@/api/recharge.api'; import api from '@/api/recharge.api';
...@@ -20,43 +32,68 @@ import { phoneFormat, phoneTrim, checkPhoneFormat } from '@/service/utils.servic ...@@ -20,43 +32,68 @@ import { phoneFormat, phoneTrim, checkPhoneFormat } from '@/service/utils.servic
const { getPhoneHome } = api; const { getPhoneHome } = api;
export default { export default {
props: { props: {
userPhoneInfo: Object userPhoneInfo: {
type: Object,
default: () => {}
}
}, },
data() { data() {
return { return {
phoneNoHome: null, phoneNoHome: null,
rechargeTel: null rechargeTel: null,
inputBlur: false
}; };
}, },
computed: { computed: {
isDefaultphone: function() { isDefaultphone: function() {
return this.phoneNo === this.userPhoneInfo?.phoneNo; return this.phoneNo === this.userPhoneInfo?.phoneNo;
}, },
historyPhoneNoList() {
return this.userPhoneInfo?.historyPhoneNoList || [];
},
phoneNo: function() { phoneNo: function() {
return phoneTrim(this.rechargeTel); return phoneTrim(this.rechargeTel);
} }
}, },
watch: { watch: {
userPhoneInfo: function(val) { userPhoneInfo: function(val) {
this.phoneNoHome = val?.phoneNoHome;
this.changeTelFormat(val?.phoneNo); this.changeTelFormat(val?.phoneNo);
this.phoneNoHome = val.phoneNoHome;
} }
}, },
created() {},
methods: { methods: {
phoneFormat,
changeTelFormat(phone) { changeTelFormat(phone) {
this.phoneNoHome = ''; this.phoneNoHome = '';
this.rechargeTel = phoneFormat(phone); this.rechargeTel = phoneFormat(phone);
if (this.rechargeTel.length > 12) {
this.queryhome();
}
}, },
async searchPhoneNoHome() { async searchPhoneNo() {
this.inputBlur = false;
if (!this.phoneNo) return; if (!this.phoneNo) return;
if (!checkPhoneFormat(this.phoneNo)) { if (!checkPhoneFormat(this.phoneNo)) {
this.$toast.fail('请您输入正确的手机号'); this.$toast.fail('请您输入正确的手机号');
this.$emit('input', { phoneNo: '', phoneNoHome: this.phoneNoHome }); this.input();
return; return;
} }
!this.phoneHome && this.queryhome();
this.input();
},
selectPhone(phone) {
this.inputBlur = false;
if (phone) {
this.rechargeTel = phoneFormat(phone);
}
this.searchPhoneNo();
},
async queryhome() {
const [data] = await getPhoneHome(this.phoneNo); const [data] = await getPhoneHome(this.phoneNo);
this.phoneNoHome = data?.phoneHome; this.phoneNoHome = data?.phoneHome;
this.input();
},
input() {
this.$emit('input', { phoneNo: this.phoneNo, phoneNoHome: this.phoneNoHome }); this.$emit('input', { phoneNo: this.phoneNo, phoneNoHome: this.phoneNoHome });
} }
} }
...@@ -64,8 +101,12 @@ export default { ...@@ -64,8 +101,12 @@ export default {
</script> </script>
<style lang="less"> <style lang="less">
.center { .center {
position: relative;
&-phone { &-phone {
border-bottom: @border-width-base solid @gray-2; border-bottom: @border-width-base solid @gray-2;
.cr-field:not(:last-child)::after {
display: none;
}
.cr-cell__title { .cr-cell__title {
display: none; display: none;
} }
...@@ -81,6 +122,46 @@ export default { ...@@ -81,6 +122,46 @@ export default {
&-field { &-field {
text-indent: -2px; text-indent: -2px;
} }
&__list {
display: none;
position: absolute;
top: 100px;
width: 100%;
margin: auto;
left: -@padding-lg;
right: -@padding-lg;
z-index: 3;
background-color: @white;
box-shadow: 0px 7px 12px 0px rgba(0, 0, 0, 0.1);
&.show {
display: block;
}
&-item {
display: flex;
align-items: center;
padding: @padding-lg / 2 @padding-lg;
.phone {
color: @text-color;
.text-14();
margin-right: @padding-xs;
}
.phone-home {
color: @text-color;
.text-12();
max-width: 180px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
flex-shrink: 0;
overflow: hidden;
}
.current {
color: @text-grey;
.text-10();
margin-left: auto;
}
}
}
} }
} }
</style> </style>
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
:three-col="true" :three-col="true"
/> />
</cr-tab> </cr-tab>
<cr-tab title="话费慢" :title-style="tabItemStyle" name="slowRecharge"> <cr-tab title="话费慢" :title-style="tabItemStyle" name="slowRecharge">
<PhoneRechargeList <PhoneRechargeList
:list="rechargeList.slowRecharge" :list="rechargeList.slowRecharge"
:info="selectedRechargeInfo" :info="selectedRechargeInfo"
...@@ -51,14 +51,15 @@ export default { ...@@ -51,14 +51,15 @@ export default {
methods: { methods: {
async changeRechargeType(name) { async changeRechargeType(name) {
const [data] = await getSkuList( const [data] = await getSkuList(
this.phoneRecharge[`${name}SpuNo`], this.phoneRecharge[`${name}SpuNos`],
this.phoneRecharge[`${name}Type`] this.phoneRecharge[`${name}Type`]
); );
this.$emit('changeRechargetype', name);
this.rechargeList[name] = data?.rechargeList || []; this.rechargeList[name] = data?.rechargeList || [];
}, },
handleSkuSelected(item) { handleSkuSelected(item) {
this.selectedRechargeInfo = item; this.selectedRechargeInfo = item;
this.$emit('selectedRecharge', item); this.$emit('selectedRecharge', { rechargeInfo: item });
} }
} }
}; };
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
</div> </div>
</template> </template>
<script> <script>
import { getTokenFromNative } from '@/service/utils.service';
import localStorage from '@/service/localStorage.service';
export default { export default {
props: { props: {
value: Array value: Array
...@@ -43,7 +45,11 @@ export default { ...@@ -43,7 +45,11 @@ export default {
} }
}); });
}, },
goOrderList() { async goOrderList() {
const token = localStorage.get('vccToken');
if (!token) {
await getTokenFromNative();
}
this.$router.push({ name: 'orderList' }); this.$router.push({ name: 'orderList' });
} }
} }
......
...@@ -13,4 +13,10 @@ ...@@ -13,4 +13,10 @@
.text-18(); .text-18();
} }
} }
.slowRechargeTip{
.text-12();
color: @gray-4;
text-align: center;
margin-bottom: @padding-sm;
}
} }
\ No newline at end of file
...@@ -2,8 +2,19 @@ ...@@ -2,8 +2,19 @@
<div class="home"> <div class="home">
<RechargeTop v-model="vipLife" /> <RechargeTop v-model="vipLife" />
<div class="center"> <div class="center">
<RechargeInput v-model="rechargePhoneInfo" :user-phone-info="userPhoneInfo" /> <RechargeInput
<RechargeList :phone-recharge="phoneRecharge" @selectedRecharge="selectedRecharge" /> v-model="rechargePhoneInfo"
:user-phone-info="userPhoneInfo"
:list="historyRecordList"
/>
<RechargeList
:phone-recharge="phoneRecharge"
@selectedRecharge="selectedRecharge"
@changeRechargetype="rechargeType = $event"
/>
<p v-if="rechargeType === 'slowRecharge'" class="slowRechargeTip">
充值后预计最迟48小时内到账,请耐心等待
</p>
<cr-button <cr-button
block block
type="primary" type="primary"
...@@ -24,6 +35,7 @@ import RechargeTop from './components/RechargeTop.vue'; ...@@ -24,6 +35,7 @@ import RechargeTop from './components/RechargeTop.vue';
import RechargeList from './components/RechargeList.vue'; import RechargeList from './components/RechargeList.vue';
import RechargeInput from './components/RechargeInput.vue'; import RechargeInput from './components/RechargeInput.vue';
import localStorage from '@/service/localStorage.service'; import localStorage from '@/service/localStorage.service';
import { getTokenFromNative, throttle } from '@/service/utils.service';
const { getSpuList } = api; const { getSpuList } = api;
export default { export default {
components: { components: {
...@@ -37,7 +49,8 @@ export default { ...@@ -37,7 +49,8 @@ export default {
rechargeAmount: 0, rechargeAmount: 0,
phoneRecharge: {}, phoneRecharge: {},
userPhoneInfo: {}, userPhoneInfo: {},
rechargeType: null, rechargeType: 'recharge',
historyRecordList: [],
rechargePhoneInfo: {}, rechargePhoneInfo: {},
selectedRechargeInfo: {} selectedRechargeInfo: {}
}; };
...@@ -47,26 +60,36 @@ export default { ...@@ -47,26 +60,36 @@ export default {
return this.rechargePhoneInfo.phoneNo && this.selectedRechargeInfo.salePrice; return this.rechargePhoneInfo.phoneNo && this.selectedRechargeInfo.salePrice;
} }
}, },
created() {}, created() {
this.goOrder = throttle.call(this, this.goOrderApi, 1000);
},
async mounted() { async mounted() {
const [data] = await getSpuList(); const [data] = await getSpuList();
if (data) { if (data) {
this.vipLife = data.vipLife || []; this.vipLife = data.vipLife || [];
this.phoneRecharge = data.phoneRecharge || {}; this.phoneRecharge = data?.phoneRecharge || {};
this.userPhoneInfo = data.userPhoneInfo || {}; this.userPhoneInfo = data?.userPhoneInfo || {};
this.rechargePhoneInfo = data.userPhoneInfo || {}; this.rechargePhoneInfo = data?.userPhoneInfo || {};
localStorage.set('phoneNo', data.userPhoneInfo.phoneNo); localStorage.set('phoneNo', data?.userPhoneInfo?.phoneNo);
} }
}, },
methods: { methods: {
selectedRecharge(item) { throttle,
this.selectedRechargeInfo = item; selectedRecharge({ rechargeInfo }) {
this.selectedRechargeInfo = rechargeInfo;
}, },
async goOrder() { async goOrderApi() {
/* 需要加防抖 */
const { skuNo, salePrice } = this.selectedRechargeInfo; const { skuNo, salePrice } = this.selectedRechargeInfo;
const token = localStorage.get('vccToken');
if (!token) {
await getTokenFromNative();
}
const [res] = await orderApi.orderCreate({ const [res] = await orderApi.orderCreate({
totalFee: salePrice, totalFee: salePrice,
registrationLocation: this.rechargePhoneInfo.phoneNoHome, terminal: 'H5',
account: this.rechargePhoneInfo?.phoneNo,
registrationLocation: this.rechargePhoneInfo?.phoneNoHome,
virtualRechargeType: this.phoneRecharge[`${this.rechargeType}Type`], virtualRechargeType: this.phoneRecharge[`${this.rechargeType}Type`],
skuList: [ skuList: [
{ {
......
...@@ -51,7 +51,12 @@ ...@@ -51,7 +51,12 @@
} }
} }
&__info { &__info {
&-right {
margin-left: auto;
color: @red !important;
}
&-item { &-item {
display: flex;
padding: 8px 0; padding: 8px 0;
color: @text-grey; color: @text-grey;
.text-13(); .text-13();
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
<div class="Od__item Od__info"> <div class="Od__item Od__info">
<div class="Od__info-item"> <div class="Od__info-item">
订单编号:<span>{{ orderInfo.orderDetail.orderNo || '' }}</span> 订单编号:<span>{{ orderInfo.orderDetail.orderNo || '' }}</span>
<span class="Od__info-right" @click="copyPwd(orderNo)">复制</span>
</div> </div>
<div class="Od__info-item"> <div class="Od__info-item">
下单时间:<span>{{ orderInfo.orderDetail.orderTime || '' }}</span> 下单时间:<span>{{ orderInfo.orderDetail.orderTime || '' }}</span>
...@@ -78,7 +79,7 @@ ...@@ -78,7 +79,7 @@
v-if="orderInfo.orderStatusInfo.orderStatus === 11" v-if="orderInfo.orderStatusInfo.orderStatus === 11"
size="small" size="small"
plain plain
type="primary" type="default"
shape="circle" shape="circle"
@click="openCancelPopup" @click="openCancelPopup"
> >
...@@ -98,7 +99,7 @@ ...@@ -98,7 +99,7 @@
v-if="orderInfo.orderStatusInfo.orderStatus === 21" v-if="orderInfo.orderStatusInfo.orderStatus === 21"
size="small" size="small"
plain plain
type="primary" type="default"
shape="circle" shape="circle"
@click="orderNotify" @click="orderNotify"
> >
...@@ -115,12 +116,10 @@ ...@@ -115,12 +116,10 @@
再次购买 再次购买
</cr-button> </cr-button>
</div> </div>
<cancel-popup v-model="showCancelPopup" :order-info="currentOrder" />
</div> </div>
</template> </template>
<script> <script>
import ListItem from '../orderList/components/ListItem.vue'; import ListItem from '../orderList/components/ListItem.vue';
import CancelPopup from '../orderList/components/CancelPopup.vue';
import { setClipboardData } from '@/service/utils.service'; import { setClipboardData } from '@/service/utils.service';
import orderApi from '@/api/order.api'; import orderApi from '@/api/order.api';
import img11 from '@/assets/images/order/11.png'; import img11 from '@/assets/images/order/11.png';
...@@ -138,11 +137,11 @@ const orderStatusImgs = { ...@@ -138,11 +137,11 @@ const orderStatusImgs = {
export default { export default {
name: 'OrderDetail', name: 'OrderDetail',
components: { components: {
ListItem, ListItem
CancelPopup
}, },
data() { data() {
return { return {
orderNo: '',
orderInfo: { orderInfo: {
feeInfo: {}, feeInfo: {},
orderDetail: {}, orderDetail: {},
...@@ -151,8 +150,7 @@ export default { ...@@ -151,8 +150,7 @@ export default {
skuList: [], skuList: [],
payDetail: {}, payDetail: {},
orderNo: '' orderNo: ''
}, }
showCancelPopup: false
}; };
}, },
computed: { computed: {
...@@ -166,6 +164,9 @@ export default { ...@@ -166,6 +164,9 @@ export default {
}, },
payType() { payType() {
return this.orderInfo.orderDetail.payType === 1 ? '微信' : '支付宝'; return this.orderInfo.orderDetail.payType === 1 ? '微信' : '支付宝';
},
isKeyChange() {
return this.currentOrder.virtualChargeAttrs && this.currentOrder.virtualChargeAttrs.cardKey;
} }
}, },
mounted() { mounted() {
...@@ -182,25 +183,46 @@ export default { ...@@ -182,25 +183,46 @@ export default {
'https://www.sobot.com/chat/h5/v2/index.html?sysnum=84ed0ad93caa47b0a9d1600824546b35&source=2'; 'https://www.sobot.com/chat/h5/v2/index.html?sysnum=84ed0ad93caa47b0a9d1600824546b35&source=2';
}, },
openCancelPopup() { openCancelPopup() {
this.showCancelPopup = true; this.$dialog({
title: '取消订单',
message: '您真的要取消吗?',
confirmButtonText: '仍要取消',
cancelButtonText: '留下商品',
onConfirm: () => {
this.handleRadioSubmit();
}
});
},
async handleRadioSubmit() {
const [res] = await orderApi.orderCancel({
orderNo: this.currentOrder.orderNo,
cancelReason: '不想买了',
cancelReasonType: 4
});
if (res) {
this.$toast('已取消');
this.$set(this.orderInfo.orderStatusInfo, `orderStatus`, 51);
this.$set(this.orderInfo.orderStatusInfo, `orderStatusText`, '交易关闭');
}
}, },
toPay() { toPay() {
this.$router.push({ path: '/pay', query: { orderNo: this.currentOrder.orderNo } }); this.$router.push({ path: '/pay', query: { orderNo: this.orderNo } });
}, },
toGoods() { toGoods() {
this.$router.push({ path: '/goods' }); this.$router.push({
path: this.isKeyChange ? '/vipLife' : '/home'
});
}, },
orderNotify() { orderNotify() {
this.$toast.success('已通知卖家'); this.$toast.success('已通知卖家');
}, },
copyPwd(item) { copyPwd(item) {
setClipboardData({ setClipboardData({
data: `${item.cardPassword}`, data: '' + item,
success: () => { success: () => {
this.$toast.success('已复制'); this.$toast.success('已复制');
} }
}); });
console.log(item);
} }
} }
}; };
......
...@@ -72,7 +72,7 @@ export default { ...@@ -72,7 +72,7 @@ export default {
}, },
computed: { computed: {
reason() { reason() {
return this.reasonList.find(item => item.cancelReasonType === this.reasonList); return this.reasonList.find(item => item.cancelReasonType === this.reasonType);
} }
}, },
watch: { watch: {
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
<div class="Ol__foot"> <div class="Ol__foot">
<div class="Ol__foot-settle"> <div class="Ol__foot-settle">
<span>总价¥{{ item.totalFee }}</span> <span>总价¥{{ item.totalFee }}</span>
<span>优惠¥{{ item.reduceFee }}</span> <span v-if="item.reduceFee">优惠¥{{ item.reduceFee }}</span>
<span> <span>
实付款<strong>¥{{ item.originalFee }}</strong> 实付款<strong>¥{{ item.originalFee }}</strong>
</span> </span>
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
plain plain
type="default" type="default"
shape="circle" shape="circle"
@click="onOptionClick(item, 'cancel')" @click.stop="onOptionClick(item, index, 'cancel')"
> >
取消订单 取消订单
</cr-button> </cr-button>
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
plain plain
type="primary" type="primary"
shape="circle" shape="circle"
@click="onOptionClick(item, 'pay')" @click.stop="onOptionClick(item, index, 'pay')"
> >
付款 付款
</cr-button> </cr-button>
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
plain plain
type="default" type="default"
shape="circle" shape="circle"
@click="onOptionClick(item, 'notify')" @click.stop="onOptionClick(item, index, 'notify')"
> >
提醒发货 提醒发货
</cr-button> </cr-button>
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
plain plain
type="primary" type="primary"
shape="circle" shape="circle"
@click="onOptionClick(item, 'again')" @click.stop="onOptionClick(item, index, 'again')"
> >
再次购买 再次购买
</cr-button> </cr-button>
...@@ -119,8 +119,8 @@ export default { ...@@ -119,8 +119,8 @@ export default {
onLoad() { onLoad() {
this.$emit(EVENT_LOADING); this.$emit(EVENT_LOADING);
}, },
onOptionClick(orderInfo, eventType) { onOptionClick(orderInfo, index, eventType) {
this.$emit(EVENT_CLICK, { orderInfo, eventType }); this.$emit(EVENT_CLICK, { orderInfo: { ...orderInfo, index }, eventType });
}, },
toHome() { toHome() {
this.$router.replace({ path: '/home' }); this.$router.replace({ path: '/home' });
......
...@@ -12,26 +12,26 @@ ...@@ -12,26 +12,26 @@
<div v-if="it.count" class="Ol__body-row"> <div v-if="it.count" class="Ol__body-row">
<span class="Ol__body-count">{{ it.count }}</span> <span class="Ol__body-count">{{ it.count }}</span>
</div> </div>
<div class="Ol__body-skus"> <div v-if="it.virtualRechargeAttrs" class="Ol__body-skus">
<div v-if="it.virtualChargeAttrs.account" class="Ol__body-sku"> <div v-if="it.virtualRechargeAttrs.account" class="Ol__body-sku">
<span>充值帐户:</span> <span>充值帐户:</span>
<span class="Ol__body-val">{{ it.virtualChargeAttrs.account }}</span> <span class="Ol__body-val">{{ it.virtualRechargeAttrs.account }}</span>
</div> </div>
<div v-if="it.virtualChargeAttrs.registrationLocation" class="Ol__body-sku"> <div v-if="it.virtualRechargeAttrs.registrationLocation" class="Ol__body-sku">
<span>归属地:</span> <span>归属地:</span>
<span class="Ol__body-val">{{ it.virtualChargeAttrs.account }}</span> <span class="Ol__body-val">{{ it.virtualRechargeAttrs.registrationLocation }}</span>
</div> </div>
<div v-if="it.virtualChargeAttrs.cardNo" class="Ol__body-sku"> <div v-if="it.virtualRechargeAttrs.cardNo" class="Ol__body-sku">
<span>卡号:</span> <span>卡号:</span>
<span class="Ol__body-val">{{ it.virtualChargeAttrs.cardNo }}</span> <span class="Ol__body-val">{{ it.virtualRechargeAttrs.cardNo }}</span>
</div> </div>
<div v-if="it.virtualChargeAttrs.cardPassword" class="Ol__body-sku"> <div v-if="it.virtualRechargeAttrs.cardPassword" class="Ol__body-sku">
<span>卡密:</span> <span>卡密:</span>
<span class="Ol__body-val">{{ it.virtualChargeAttrs.cardPassword }}</span> <span class="Ol__body-val">{{ it.virtualRechargeAttrs.cardPassword }}</span>
<a <a
v-if="props.showCopy" v-if="props.showCopy"
href="javascript:;" href="javascript:;"
@click="parent.copyPwd(it.virtualChargeAttrs)" @click="parent.copyPwd(it.virtualRechargeAttrs.cardPassword)"
> >
复制 复制
</a> </a>
......
...@@ -11,14 +11,12 @@ ...@@ -11,14 +11,12 @@
/> />
</cr-tab> </cr-tab>
</cr-tabs> </cr-tabs>
<cancel-popup v-model="showCancelPopup" :order-info="currentOrder" />
</div> </div>
</template> </template>
<script> <script>
import orderApi from '@/api/order.api'; import orderApi from '@/api/order.api';
import List from './components/List'; import List from './components/List';
import { isApp } from '@/service/validation.service'; import { isApp } from '@/service/validation.service';
import CancelPopup from './components/CancelPopup';
const commonParams = { const commonParams = {
loading: false, loading: false,
finished: false, finished: false,
...@@ -29,13 +27,11 @@ const commonParams = { ...@@ -29,13 +27,11 @@ const commonParams = {
export default { export default {
name: 'OrderList', name: 'OrderList',
components: { components: {
List, List
CancelPopup
}, },
data() { data() {
return { return {
isApp, isApp,
showCancelPopup: false,
currentTab: 0, currentTab: 0,
navList: [ navList: [
{ {
...@@ -44,22 +40,22 @@ export default { ...@@ -44,22 +40,22 @@ export default {
...JSON.parse(JSON.stringify(commonParams)) ...JSON.parse(JSON.stringify(commonParams))
}, },
{ {
state: 1, state: 11,
title: '待付款', title: '待付款',
...JSON.parse(JSON.stringify(commonParams)) ...JSON.parse(JSON.stringify(commonParams))
}, },
{ {
state: 2, state: 21,
title: '待发货', title: '待发货',
...JSON.parse(JSON.stringify(commonParams)) ...JSON.parse(JSON.stringify(commonParams))
}, },
{ {
state: 3, state: 31,
title: '待收货', title: '待收货',
...JSON.parse(JSON.stringify(commonParams)) ...JSON.parse(JSON.stringify(commonParams))
}, },
{ {
state: 4, state: 41,
title: '已完成', title: '已完成',
...JSON.parse(JSON.stringify(commonParams)) ...JSON.parse(JSON.stringify(commonParams))
} }
...@@ -94,13 +90,11 @@ export default { ...@@ -94,13 +90,11 @@ export default {
this.toGoods(); this.toGoods();
break; break;
default: default:
this.currentItems = {}; this.currentOrder = {};
break; break;
} }
}, },
orderCancelPopup() {
this.showCancelPopup = true;
},
toPay() { toPay() {
this.$router.push({ path: '/pay', query: { orderNo: this.currentOrder.orderNo } }); this.$router.push({ path: '/pay', query: { orderNo: this.currentOrder.orderNo } });
}, },
...@@ -113,12 +107,39 @@ export default { ...@@ -113,12 +107,39 @@ export default {
setNavListData(key, val) { setNavListData(key, val) {
this.$set(this.navList[this.currentTab], key, val); this.$set(this.navList[this.currentTab], key, val);
}, },
orderCancelPopup() {
this.$dialog({
title: '取消订单',
message: '您真的要取消吗?',
confirmButtonText: '仍要取消',
cancelButtonText: '留下商品',
onConfirm: () => {
this.handleRadioSubmit();
}
});
},
async handleRadioSubmit() {
const [res] = await orderApi.orderCancel({
orderNo: this.currentOrder.orderNo,
cancelReason: '不想买了',
cancelReasonType: 4
});
if (res) {
this.$toast('已取消');
this.$set(this.navList[this.currentTab].list[this.currentOrder.index], `orderStatus`, 51);
this.$set(
this.navList[this.currentTab].list[this.currentOrder.index],
`orderStatusText`,
'交易关闭'
);
}
},
async getList() { async getList() {
let { finished, page, pageSize, list, state: orderStatus } = this.navList[this.currentTab]; let { finished, page, pageSize, list, state: orderStatus } = this.navList[this.currentTab];
if (finished) return; if (finished) return;
this.setNavListData('loading', true); this.setNavListData('loading', true);
const [res] = await orderApi.orderList({ const [res] = await orderApi.orderList({
page, pageNo: page,
pageSize, pageSize,
orderStatus orderStatus
}); });
......
...@@ -45,6 +45,7 @@ const IS_CREDIT_PAY = method => ...@@ -45,6 +45,7 @@ const IS_CREDIT_PAY = method =>
const PAYMENT_CODE_PAY = 1; // 支付密码 const PAYMENT_CODE_PAY = 1; // 支付密码
const SMS_VERIFICATION_CODE_PAY = 2; //短信验证码 const SMS_VERIFICATION_CODE_PAY = 2; //短信验证码
const FACE_VERIFICATION_CODE_PAY = 4; //短信验证码
const PAY_SUCCESS = 3; // 支付成功 const PAY_SUCCESS = 3; // 支付成功
const PAY_PAYING = 2; //支付中 const PAY_PAYING = 2; //支付中
...@@ -70,7 +71,7 @@ function isDetentionFn() { ...@@ -70,7 +71,7 @@ function isDetentionFn() {
this.creditPayList.isGroupPay this.creditPayList.isGroupPay
) { ) {
this.$dialog({ this.$dialog({
message: '使用组合支付部分金额可免使用40天哦!', message: '使用组合支付部分金额可免使用40天哦!',
confirmButtonText: '组合支付', confirmButtonText: '组合支付',
cancelButtonText: '继续支付', cancelButtonText: '继续支付',
confirmButtonColor: '#EC1500', confirmButtonColor: '#EC1500',
...@@ -83,6 +84,7 @@ function isDetentionFn() { ...@@ -83,6 +84,7 @@ function isDetentionFn() {
if (this.creditPayList.payList[key].isRecommend) { if (this.creditPayList.payList[key].isRecommend) {
const type = this.creditPayList.payList[key].payType; const type = this.creditPayList.payList[key].payType;
this.changePayType(type, this.creditPayList.payList[key].mergePayPretreatmentInfo); this.changePayType(type, this.creditPayList.payList[key].mergePayPretreatmentInfo);
this.isCheckAgreement = true;
this.pay(); this.pay();
return; return;
} }
...@@ -94,7 +96,7 @@ function isDetentionFn() { ...@@ -94,7 +96,7 @@ function isDetentionFn() {
!this.creditPayList.isGroupPay !this.creditPayList.isGroupPay
) { ) {
this.$dialog({ this.$dialog({
message: '使用享花卡支付可免使用40天哦', message: '使用享花卡支付可免使用40天哦',
confirmButtonText: '享花卡支付', confirmButtonText: '享花卡支付',
cancelButtonText: '继续支付', cancelButtonText: '继续支付',
confirmButtonColor: '#EC1500', confirmButtonColor: '#EC1500',
...@@ -104,6 +106,7 @@ function isDetentionFn() { ...@@ -104,6 +106,7 @@ function isDetentionFn() {
onConfirm: () => { onConfirm: () => {
// 切换享花卡支付 // 切换享花卡支付
this.changePayType(CREDIT_PAY); this.changePayType(CREDIT_PAY);
this.isCheckAgreement = true;
this.pay(); this.pay();
} }
}); });
...@@ -145,5 +148,6 @@ export { ...@@ -145,5 +148,6 @@ export {
ACCOUNT_APPLY_SUCCESS, ACCOUNT_APPLY_SUCCESS,
ACCOUNT_APPLY_AUDITING, ACCOUNT_APPLY_AUDITING,
ACCOUNT_APPLY_AUDIT_FAIL, ACCOUNT_APPLY_AUDIT_FAIL,
SMS_VERIFICATION_CODE_PAY SMS_VERIFICATION_CODE_PAY,
FACE_VERIFICATION_CODE_PAY
}; };
...@@ -23,11 +23,12 @@ ...@@ -23,11 +23,12 @@
export default { export default {
name: 'Contract', name: 'Contract',
props: { props: {
contractList: Array contractList: Array,
value: Boolean
}, },
data() { data() {
return { return {
isCheck: false isCheck: this.value
}; };
}, },
methods: { methods: {
...@@ -35,7 +36,7 @@ export default { ...@@ -35,7 +36,7 @@ export default {
window.location.href = url; window.location.href = url;
}, },
change(e) { change(e) {
this.$emit('change', e); this.$emit('input', e);
} }
} }
}; };
...@@ -48,14 +49,7 @@ export default { ...@@ -48,14 +49,7 @@ export default {
align-items: flex-start; align-items: flex-start;
color: @gray-5; color: @gray-5;
.text-10; .text-10;
&-checkbox {
// margin-right: 2px;
// height: 14px;
}
&-list { &-list {
display: inline-flex;
justify-content: flex-start;
flex-wrap: wrap;
color: @gray-5; color: @gray-5;
span { span {
color: @red; color: @red;
......
...@@ -6,14 +6,16 @@ ...@@ -6,14 +6,16 @@
<cr-image :src="value.icon" class="icon" mode="aspectFit" width="39" height="39" /> <cr-image :src="value.icon" class="icon" mode="aspectFit" width="39" height="39" />
<div class="content-info-con"> <div class="content-info-con">
<div class="content-info-tit"> <div class="content-info-tit">
<p class="content-info-tit">{{ value.name }}</p> <div class="content-info-tit-wrap">
<p v-if="value.tagName" class="content-info-tit_tag">{{ value.tagName }}</p> <p class="content-info-tit">{{ value.name }}</p>
<p v-if="value.tagName" class="content-info-tit_tag">{{ value.tagName }}</p>
</div>
<p v-if="isGroupPay && value.payAmt" class="content-info-amount">
{{ value.payAmt }}
</p>
</div> </div>
<p>{{ value.accountStatusDesc }}</p> <p>{{ value.accountStatusDesc }}</p>
</div> </div>
<p v-if="isGroupPay && value.mergePayPretreatmentInfo" class="content-info-amount">
{{ value.mergePayPretreatmentInfo && value.mergePayPretreatmentInfo.creditPayAmt }}
</p>
</div> </div>
<div <div
v-if="showCoupon && value.payType === 1" v-if="showCoupon && value.payType === 1"
...@@ -42,11 +44,11 @@ ...@@ -42,11 +44,11 @@
</template> </template>
<script> <script>
// import { registeredEvents } from '@/utils/sa'; // import { registeredEvents } from '@/utils/sa';
const payTypeE = [ // const payTypeE = [
'PD_YXMMAEC_UserClickCashierSelectXiangHuaCardPay', // 'PD_YXMMAEC_UserClickCashierSelectXiangHuaCardPay',
'PD_YXMMAEC_UserClickCashierSelectWechatPay' // 'PD_YXMMAEC_UserClickCashierSelectWechatPay'
]; // ];
const payTypeMiniAppE = ['c_cashierselectxianghuacardpay', 'c_cashierselectwechatpay']; // const payTypeMiniAppE = ['c_cashierselectxianghuacardpay', 'c_cashierselectwechatpay'];
export default { export default {
name: 'PayCardItem', name: 'PayCardItem',
inject: ['payCard', 'pay'], inject: ['payCard', 'pay'],
...@@ -61,12 +63,12 @@ export default { ...@@ -61,12 +63,12 @@ export default {
couponDisabled: Boolean couponDisabled: Boolean
}, },
methods: { methods: {
changePayType({ payType }) { changePayType({ payType, mergePayPretreatmentInfo }) {
if (this.disabled || this.value.disabled) { if (this.disabled || this.value.disabled) {
return; return;
} }
this.$emit('click'); this.$emit('click');
this.pay.changePayType(payType); this.pay.changePayType(payType, mergePayPretreatmentInfo);
}, },
openCouponModal() { openCouponModal() {
if (this.couponDisabled) return; if (this.couponDisabled) return;
...@@ -110,7 +112,6 @@ export default { ...@@ -110,7 +112,6 @@ export default {
} }
.type-item { .type-item {
width: 100%; width: 100%;
// height: 134rpx;
padding: 12px 8px 12px 12px; padding: 12px 8px 12px 12px;
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
...@@ -123,7 +124,6 @@ export default { ...@@ -123,7 +124,6 @@ export default {
&-content-info { &-content-info {
width: 100%; width: 100%;
display: flex; display: flex;
// width: 308px;
align-items: center; align-items: center;
} }
&-checkbox { &-checkbox {
...@@ -141,6 +141,10 @@ export default { ...@@ -141,6 +141,10 @@ export default {
margin-bottom: 2px; margin-bottom: 2px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
&-wrap {
display: flex;
}
&_tag { &_tag {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
...@@ -161,6 +165,9 @@ export default { ...@@ -161,6 +165,9 @@ export default {
color: @font-color-light; color: @font-color-light;
} }
.content-info-amount { .content-info-amount {
width: 100px;
text-align: left;
word-break: break-all;
&::before { &::before {
content: '¥'; content: '¥';
} }
......
...@@ -8,16 +8,19 @@ ...@@ -8,16 +8,19 @@
:show-coupon="showCoupon" :show-coupon="showCoupon"
:risk-limit="riskLimit" :risk-limit="riskLimit"
/> />
<p class="dashed"> </div>
<cr-checkbox <div class="dashed">
v-model="thirdPayInfo.isCheck" <p class="dashed-line" />
shape="round" <cr-checkbox
checked-color="#EC1500" v-model="thirdPayInfo.isCheck"
:disabled="disabled || thirdPayInfo.disabled" shape="round"
class="dashed-checkbox" checked-color="#EC1500"
@click.native="changePayType(thirdPayInfo)" :disabled="disabled || thirdPayInfo.disabled"
/> class="dashed-checkbox"
</p> @click.native="changePayType(thirdPayInfo)"
/>
</div>
<div class="groupCard">
<PayCardItem :is-group-pay="true" :value="thirdPayInfo" /> <PayCardItem :is-group-pay="true" :value="thirdPayInfo" />
</div> </div>
<p class="group-more b-t" @click="openMore">更多支付组合<cr-icon type="arrow" size="15px" /></p> <p class="group-more b-t" @click="openMore">更多支付组合<cr-icon type="arrow" size="15px" /></p>
...@@ -65,7 +68,13 @@ export default { ...@@ -65,7 +68,13 @@ export default {
let temp = {}; let temp = {};
for (const key in this.value) { for (const key in this.value) {
if (this.value[key].isRecommend || this.value[key].isCheck) { if (this.value[key].isRecommend || this.value[key].isCheck) {
temp = { ...this.value[key] }; const mergePayPretreatmentInfo = this.value[key]?.mergePayPretreatmentInfo || {};
temp = {
...this.value[key],
payAmt: mergePayPretreatmentInfo?.otherPayAmt
};
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
this.creditPayInfo.payAmt = mergePayPretreatmentInfo.creditPayAmt;
} }
} }
return temp; return temp;
...@@ -80,6 +89,7 @@ export default { ...@@ -80,6 +89,7 @@ export default {
}, },
methods: { methods: {
changePayType({ payType, mergePayPretreatmentInfo }) { changePayType({ payType, mergePayPretreatmentInfo }) {
console.log(mergePayPretreatmentInfo, 'mergePayPretreatmentInfo');
if (this.disabled || this.creditPayInfo.disabled) { if (this.disabled || this.creditPayInfo.disabled) {
return; return;
} }
...@@ -97,7 +107,7 @@ export default { ...@@ -97,7 +107,7 @@ export default {
</script> </script>
<style lang="less"> <style lang="less">
.groupCard { .groupCard {
width: 320px; width: 100%;
} }
.group-more { .group-more {
.text-13; .text-13;
...@@ -114,28 +124,21 @@ export default { ...@@ -114,28 +124,21 @@ export default {
z-index: 2; z-index: 2;
} }
.dashed { .dashed {
width: 309px; width: 100%;
margin: auto; padding: 0 12px;
position: relative; box-sizing: border-box;
border-bottom: 1px dashed #dcdcdc; display: flex;
justify-content: space-between;
align-items: center;
&-line {
width: 310px;
border-bottom: 1px dashed #dcdcdc;
}
&-checkbox { &-checkbox {
width: 18px; width: 18px;
position: absolute;
right: -22px;
top: -8px;
}
&::after {
content: '';
width: 24px;
height: 28px;
position: absolute;
margin-top: -12px;
left: 50%;
margin-left: -12px;
background: url('../../../assets/images/addicon.png') no-repeat;
background-size: 100%;
} }
} }
.more-title { .more-title {
.text-16; .text-16;
display: flex; display: flex;
......
<template> <template>
<cr-overlay :show="value" @click="closeModal"> <cr-overlay :show="value">
<div class="sms-modal"> <div class="sms-modal">
<div class="sms"> <div class="sms">
<p class="sms-icon"><cr-icon type="cross" color="#999999" @click="closeModal" /></p> <p class="sms-icon"><cr-icon type="cross" color="#999999" @click="closeModal" /></p>
<p class="sms-title">请输入短信验证码</p> <p class="sms-title">请输入短信验证码</p>
<p class="sms-des">为保证您账户安全,此笔交易需要短信验证</p> <p class="sms-des">为保证您账户安全,此笔交易需要短信验证</p>
<p class="phone">已发送至 {{ getPhone() }}17611682272</p> <p class="phone">已发送至 {{ getPhone() }}</p>
<cr-authcode-field <cr-authcode-field
span-size="20px" span-size="20px"
type="number" type="number"
...@@ -87,7 +87,7 @@ export default { ...@@ -87,7 +87,7 @@ export default {
}, },
getPhone() { getPhone() {
const phone = localStorage.get('phoneNo'); const phone = localStorage.get('phoneNo');
const phoneS = phone.replace(/(\d{3})\d*(\d{4})/, '+86 $1 **** $2'); const phoneS = `${phone}`.replace(/(\d{3})\d*(\d{4})/, '+86 $1 **** $2');
return phoneS; return phoneS;
}, },
sendSa() { sendSa() {
......
import localStorage from '@/service/localStorage.service';
import config from '@/config/index';
const { toBHost } = config;
export const goUrlExtends = {
methods: {
goHome() {
// 商城地址
const tob = this.getTarget();
if (tob) {
window.location.replace = `${toBHost}`;
return;
}
this.$router.replace({ name: 'home' });
},
goOrderList() {
const tob = this.getTarget();
if (tob) {
window.location.replace = `${toBHost}/orderList`;
return;
}
this.$router.replace({ name: 'orderList' }, 'sessionStorage');
},
goOrderDetail() {
const tob = this.getTarget();
const orderNo = localStorage.get('orderNo')?.orderNo;
if (tob) {
window.location.replace = `${toBHost}/orderDetail?orderNo=${orderNo}`;
return;
}
this.$router.replace({
name: 'orderDetail',
query: { orderNo }
});
},
getTarget() {
const tob = localStorage.get('target', 'sessionStorage');
return tob;
}
}
};
<template> <template>
<div class="pay"> <div class="pay">
<!-- 支付倒计时 --> <!-- 支付倒计时 -->
<div class="price-box"> <div v-if="success" class="price-box">
<p class="price">{{ displayInfo.orderAmt }}100</p> <p class="price">{{ displayInfo.orderAmt }}</p>
<p v-if="!overtime" class="time"> <p v-if="!overtime" class="time">
支付剩余时间: 支付剩余时间:
<cr-count-down :time="displayInfo.periodSeconds" @finish="timeup" /> <cr-count-down :time="displayInfo.periodSeconds" @finish="timeup" />
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
<!-- 推荐信用支付 --> <!-- 推荐信用支付 -->
<cr-pay-card <cr-pay-card
v-if="getObjectKey(creditPayList.payList).length"
v-model="creditPayList" v-model="creditPayList"
:pay-type="payType" :pay-type="payType"
:disabled="overtime" :disabled="overtime"
...@@ -25,6 +26,7 @@ ...@@ -25,6 +26,7 @@
<!-- 其他支付方式 --> <!-- 其他支付方式 -->
<cr-pay-card <cr-pay-card
v-if="getObjectKey(thirdPayList.payList).length"
v-model="thirdPayList" v-model="thirdPayList"
:pay-type="payType" :pay-type="payType"
:disabled="overtime" :disabled="overtime"
...@@ -41,20 +43,15 @@ ...@@ -41,20 +43,15 @@
<cr-contract <cr-contract
v-if="isShowProtocol" v-if="isShowProtocol"
ref="agreement" ref="agreement"
v-model="isCheckAgreement"
:contract-list="payContractInfo.contractInfos" :contract-list="payContractInfo.contractInfos"
@change="$event => (isCheckAgreement = $event)"
/> />
<cr-button <cr-button type="primary" class="btn-primary" :disabled="!payType" @click="nextAction">
type="primary"
class="btn-primary"
:disabled="!payType || (isShowProtocol && !isCheckAgreement)"
@click="nextAction"
>
{{ accountS.text }} {{ accountS.text }}
</cr-button> </cr-button>
</p> </p>
<p v-if="overtime" class="btn"> <p v-if="overtime" class="btn">
<cr-button type="default" class="btn-default" @click="goOrderDetail">查看订单</cr-button> <cr-button type="default" class="btn-default" @click="goOrderList">我的订单</cr-button>
<cr-button type="primary" class="btn-primary" @click="goHome">返回商城</cr-button> <cr-button type="primary" class="btn-primary" @click="goHome">返回商城</cr-button>
</p> </p>
<p class="placeholder" /> <p class="placeholder" />
...@@ -81,7 +78,7 @@ ...@@ -81,7 +78,7 @@
no-render-disable-tab no-render-disable-tab
:show-coupon="couponPopup" :show-coupon="couponPopup"
:enable-list="payCouponList" :enable-list="payCouponList"
:value="selectedCoupon.pickupId" :value="selectedCoupon.id"
@click="selectCouponItem" @click="selectCouponItem"
@change="handleSelectCoupon" @change="handleSelectCoupon"
/> />
...@@ -98,16 +95,14 @@ import { isWechat } from '@/service/validation.service'; ...@@ -98,16 +95,14 @@ import { isWechat } from '@/service/validation.service';
import { encryptByDESModeEBC } from '@/service/encrypt'; import { encryptByDESModeEBC } from '@/service/encrypt';
import { registeredEvents } from '@/service/sa.service'; import { registeredEvents } from '@/service/sa.service';
import localStorage from '@/service/localStorage.service'; import localStorage from '@/service/localStorage.service';
import { throttle } from '@/service/utils.service';
import { goUrlExtends } from './extends';
import { import {
status,
codeArr, codeArr,
payTypeE, payTypeE,
PAY_PAYING,
CREDIT_PAY, CREDIT_PAY,
WECHAT_PAY, WECHAT_PAY,
ALIPAY_PAY,
PAY_SUCCESS, PAY_SUCCESS,
payTypeText,
creditStatus, creditStatus,
IS_THIRD_PAY, IS_THIRD_PAY,
IS_GROUP_PAY, IS_GROUP_PAY,
...@@ -119,9 +114,18 @@ import { ...@@ -119,9 +114,18 @@ import {
creditPayStatusType, creditPayStatusType,
ACCOUNT_APPLY_SUCCESS, ACCOUNT_APPLY_SUCCESS,
ACCOUNT_APPLY_AUDIT_FAIL, ACCOUNT_APPLY_AUDIT_FAIL,
SMS_VERIFICATION_CODE_PAY //短信验证码 SMS_VERIFICATION_CODE_PAY, //短信验证码
FACE_VERIFICATION_CODE_PAY
} from './STATIC_DATA'; } from './STATIC_DATA';
import { pay, prepay, getCoupon, h5AppyUrl, ocrFaceId, queryPayInfo } from '@/api/pay.api.js'; import {
pay,
prepay,
getCoupon,
h5AppyUrl,
ocrFaceId,
queryPayInfo,
kaGetNextUrl
} from '@/api/pay.api.js';
const VCC_CHANNEL = localStorage.get('vccChannel'); const VCC_CHANNEL = localStorage.get('vccChannel');
export default { export default {
components: { components: {
...@@ -134,17 +138,19 @@ export default { ...@@ -134,17 +138,19 @@ export default {
pay: this pay: this
}; };
}, },
extends: goUrlExtends,
data() { data() {
return { return {
error: '', error: '',
random: '', random: '',
orderNo: '', orderNo: '',
success: false,
payType: null, payType: null,
isReady: false, isReady: false,
overtime: false, overtime: false,
pwdModal: false, pwdModal: false,
smsModal: false, smsModal: false,
showCoupon: true, showCoupon: false,
flowOrderNo: null, flowOrderNo: null,
couponPopup: false, couponPopup: false,
showGoFaceTip: false, // h5支付活体提示怎么处理 showGoFaceTip: false, // h5支付活体提示怎么处理
...@@ -206,11 +212,21 @@ export default { ...@@ -206,11 +212,21 @@ export default {
/* 查询支付信息 */ /* 查询支付信息 */
async queryPayInfo() { async queryPayInfo() {
const [data, error] = await queryPayInfo({ orderNo: this.orderNo }); const [data, error] = await queryPayInfo({ orderNo: this.orderNo });
if (error) return; if (error) {
this.payResult('Fail');
return;
}
this.isReady = true; this.isReady = true;
const { displayInfo = {}, payMethods } = data || {}; const { displayInfo = {}, payMethods } = data || {};
this.overtime = displayInfo.periodSeconds <= 0;
this.success = true;
if (this.overtime) {
this.displayInfo.orderAmt = displayInfo.orderAmt;
return;
}
if (displayInfo.payCouponInfo && displayInfo.payCouponInfo.optimalPayCoupon) { if (displayInfo.payCouponInfo && displayInfo.payCouponInfo.optimalPayCoupon) {
this.selectedCoupon = displayInfo.payCouponInfo.optimalPayCoupon; this.selectedCoupon = displayInfo.payCouponInfo.optimalPayCoupon;
this.selectedCoupon.id = this.selectedCoupon.pickupId;
this.showCoupon = displayInfo.payCouponInfo.optimalType === 3; this.showCoupon = displayInfo.payCouponInfo.optimalType === 3;
} }
this.payContractInfo = displayInfo.payContractInfo || {}; this.payContractInfo = displayInfo.payContractInfo || {};
...@@ -243,6 +259,9 @@ export default { ...@@ -243,6 +259,9 @@ export default {
displayInfo[key].disabled = true; displayInfo[key].disabled = true;
} }
this.creditPayList.isGroupPay = IS_GROUP_PAY(p.method); this.creditPayList.isGroupPay = IS_GROUP_PAY(p.method);
if (p.isDefault) {
this.mergePayPretreatmentInfo = p.mergePayPretreatmentInfo;
}
this.$set(this.creditPayList.payList, key, { this.$set(this.creditPayList.payList, key, {
...displayInfo[key], ...displayInfo[key],
...p, ...p,
...@@ -251,10 +270,18 @@ export default { ...@@ -251,10 +270,18 @@ export default {
isCheck: p.isDefault || false, isCheck: p.isDefault || false,
isGroupPay: IS_GROUP_PAY(p.method) isGroupPay: IS_GROUP_PAY(p.method)
}); });
if (!('creditPayInfo' in this.creditPayList.payList)) {
this.$set(this.creditPayList.payList, 'creditPayInfo', {
...displayInfo['creditPayInfo'],
show: true,
isCheck: false
});
}
break; break;
} }
} }
} }
if (this.payType === CREDIT_PAY && displayInfo.creditPayInfo.disabled) { if (this.payType === CREDIT_PAY && displayInfo.creditPayInfo.disabled) {
this.payType = null; this.payType = null;
} }
...@@ -265,7 +292,7 @@ export default { ...@@ -265,7 +292,7 @@ export default {
this.displayInfo = displayInfo || {}; this.displayInfo = displayInfo || {};
this.creditPayInfo = displayInfo.creditPayInfo || {}; this.creditPayInfo = displayInfo.creditPayInfo || {};
this.overtime = displayInfo.periodSeconds <= 0; displayInfo.periodSeconds = displayInfo.periodSeconds * 1000;
this.getBtnStatus(this.isRiskLimit()); this.getBtnStatus(this.isRiskLimit());
}, },
checkStatus({ accountStatus, canAmt }, { orderAmt }) { checkStatus({ accountStatus, canAmt }, { orderAmt }) {
...@@ -324,7 +351,7 @@ export default { ...@@ -324,7 +351,7 @@ export default {
}; };
} }
} else { } else {
const txt = `确认付款`; const txt = `确认支付`;
this.accountS = { this.accountS = {
text: txt, text: txt,
fn: this.pay fn: this.pay
...@@ -334,54 +361,31 @@ export default { ...@@ -334,54 +361,31 @@ export default {
/* 获取优惠券信息 */ /* 获取优惠券信息 */
async getCouponList(orderNo) { async getCouponList(orderNo) {
const [data] = await getCoupon({ orderNo: orderNo }); const [data] = await getCoupon({ orderNo: orderNo });
this.payCouponList = [];
if (data && data.coupons) { if (data && data.coupons) {
this.payCouponList = data.coupons.filter(item => { data.coupons.forEach(item => {
if (item.couponCategory === 21) { if (item.couponCategory === 21) {
return { this.payCouponList.push({
...item, ...item,
id: item.pickupId id: item.pickupId,
}; pickupAble: 1,
limitAmount: item.limitDesc
});
} }
}); });
} }
this.payCouponList = [
{
id: 33,
name: '仅新用户购买自营商品',
startDate: '2020.8.6',
endDate: '2021.8.16',
faceValue: 200,
limitAmount: '满99元可用',
couponCategory: 1,
iconUrl: 'http://talos-image-fe.liangkebang.net/pcm/1599553158123.png',
pickupAble: 1
},
{
id: 44,
name: '仅新用户购买自营商品',
startDate: '2020.8.6',
endDate: '2021.8.16',
faceValue: 200,
limitAmount: '满99元可用',
couponCategory: 1,
iconUrl: 'http://talos-image-fe.liangkebang.net/pcm/1599553158123.png',
pickupAble: 1
}
];
}, },
nextAction() { nextAction: throttle(function() {
registeredEvents('PD_YXMMACP_UserClickCashierConfirmPaymentBtn', {
order_id: this.orderNo,
pay_method: payTypeText[this.payType - 1],
vcc_state: status[this.creditPayInfo.accountStatus - 1],
buttons_name: this.accountS.text
});
this.accountS.fn(); this.accountS.fn();
}, }, 1000),
/* 预支付 */ /* 预支付 */
async pay(params) { async pay(params) {
// 组合支付的提示和享花卡支付逻辑 // 组合支付的提示和享花卡支付逻辑
this.error = ''; this.error = '';
if (this.isShowProtocol && !this.isCheckAgreement) {
this.$toast('请仔细阅读并同意相关协议');
return;
}
if (!params && !this.isDetention && IS_THIRD_PAY(this.payType)) { if (!params && !this.isDetention && IS_THIRD_PAY(this.payType)) {
this.isDetention = true; this.isDetention = true;
isDetentionFn.call(this); isDetentionFn.call(this);
...@@ -390,72 +394,88 @@ export default { ...@@ -390,72 +394,88 @@ export default {
this.isDetention = false; this.isDetention = false;
/* 设置密码 */ /* 设置密码 */
if (this.payType === CREDIT_PAY && !this.creditPayInfo.hasPwd) { if (this.payType === CREDIT_PAY && !this.creditPayInfo.hasPwd) {
const url = `${this.creditPayInfo.pwdSetJumpUrl}&vccChannel=${VCC_CHANNEL}`; this.retrieveLink();
this.goH5(url);
return; return;
} }
localStorage.set('orderNo', { orderNo: this.orderNo });
const paramsData = { const paramsData = {
...params, ...params,
quitUrl: `${window.location.origin}/payWaiting`,
returnUrl: `${window.location.origin}/payWaiting`,
ocrAuth: { ocrAuth: {
isH5: true isH5: true
}, },
orderNo: this.orderNo, orderNo: this.orderNo,
payMethod: this.payType, payMethod: this.payType,
payCouponId: this.selectedCoupon.pickupId || '' payCouponId: this.selectedCoupon.id || '',
mergePayPretreatmentId: this.mergePayPretreatmentInfo?.mergePayPretreatmentId
}; };
const [data, error] = params ? await pay(paramsData) : await prepay(paramsData); const [data, error] = params ? await pay(paramsData) : await prepay(paramsData);
/* 支付失败 */ /* 支付失败 */
if (error) { if (error) {
if (error?.response?.businessCode === '3001') {
/* 有享花卡未支付的订单 */
this.$dialog({
message: '您的享花卡额度被其他订单占用,暂时不可使用享花卡支付哦!',
confirmButtonText: '重新选择',
showCancelButton: false,
confirmButtonColor: '#EC1500'
});
return;
}
if (error?.response?.businessCode === '3005') {
/* 已锁定组合支付,不能切换其他支付方式 */
return;
}
if (codeArr.indexOf(error.response.businessCode) < 0) { if (codeArr.indexOf(error.response.businessCode) < 0) {
this.payResult('Fail', error.msg); this.payResult('Fail', error.message);
return; return;
} }
this.error = error.msg; this.error = error.message;
this.retrieve();
return; return;
} }
const { creditPayInfo = {}, wxPayInfo, flowOrderNo, aliPayInfo } = data; const { creditPayInfo = {}, wxPayInfo = {}, flowOrderNo, aliPayInfo = {} } = data;
const creditPayStatus = creditPayInfo.creditPayStatus; const creditPayStatus = creditPayInfo.creditPayStatus;
this.flowOrderNo = flowOrderNo; this.flowOrderNo = flowOrderNo;
if (wxPayInfo.mwebUrl) {
if (!params && this.payType === WECHAT_PAY) {
/* 微信支付 */ /* 微信支付 */
payByWay(this.tradeType, { ...wxPayInfo, url: wxPayInfo.mwebUrl }); payByWay(this.tradeType, { ...wxPayInfo, url: wxPayInfo.mwebUrl });
return; return;
} } else if (aliPayInfo.order_string) {
if (!params && this.payType === ALIPAY_PAY) {
/* 支付宝支付 */ /* 支付宝支付 */
payByWay('ALIWEB', aliPayInfo); payByWay('ALIWEB', { ...aliPayInfo, url: aliPayInfo.order_string });
return;
}
if (creditPayStatus === PAY_PAYING) {
/* 支付中 */
this.payResult('Waiting');
return; return;
} } else if (creditPayStatus === PAY_SUCCESS) {
if (creditPayStatus === PAY_SUCCESS) { /* 信用支付成功 */
/* 支付成功 */ this.close();
this.payResult('Success'); this.payResult('Success');
return; return;
} } else if (
if (creditPayStatus === PAYMENT_CODE_PAY || creditPayStatus === SMS_VERIFICATION_CODE_PAY) { creditPayStatus === PAYMENT_CODE_PAY ||
creditPayStatus === SMS_VERIFICATION_CODE_PAY
) {
/* 密码或者短信鉴权 */ /* 密码或者短信鉴权 */
this.close(); this.close();
this[`${creditPayStatusType[creditPayStatus]}Modal`] = true; this[`${creditPayStatusType[creditPayStatus]}Modal`] = true;
return;
} else if (creditPayStatus === FACE_VERIFICATION_CODE_PAY) {
/* 人脸鉴权 */
this.goOcr();
} }
}, },
payResult(type, error) { payResult(type, error) {
const finalAmt = const finalAmt =
this.payType === WECHAT_PAY || !this.showCoupon IS_THIRD_PAY(this.payType) || !this.showCoupon
? this.displayInfo.orderAmt || '0.00' ? this.displayInfo.orderAmt || '0.00'
: (this.displayInfo.orderAmt - this.selectedCoupon.faceValue || 0).toFixed(2); : (this.displayInfo.orderAmt - this.selectedCoupon.faceValue || 0).toFixed(2);
const freeAmount = this.showCoupon ? this.selectedCoupon.faceValue || '0.00' : '0.00'; const freeAmount = this.showCoupon ? this.selectedCoupon.faceValue || '0.00' : '0.00';
localStorage.set('amount', { finalAmt, freeAmount });
/* 跳转支付结果页面 */ /* 跳转支付结果页面 */
this.$router.push({ this.$router.replace({
name: `pay${type}`, name: `pay${type}`,
query: { query: {
freeAmount,
reason: error, reason: error,
amount: finalAmt,
orderNo: this.orderNo orderNo: this.orderNo
} }
}); });
...@@ -475,10 +495,8 @@ export default { ...@@ -475,10 +495,8 @@ export default {
}, },
/* 选取优惠券 */ /* 选取优惠券 */
handleSelectCoupon(id, selectedCoupon) { handleSelectCoupon(id, selectedCoupon) {
console.log(id, selectedCoupon);
registeredEvents('PD_YXMMACP_UserClickCouponPopupWindowComfirmBtn'); registeredEvents('PD_YXMMACP_UserClickCouponPopupWindowComfirmBtn');
this.selectedCoupon = selectedCoupon || {}; this.selectedCoupon = selectedCoupon || {};
console.log(this.selectedCoupon);
const status = this.checkStatus(this.creditPayInfo, this.displayInfo); const status = this.checkStatus(this.creditPayInfo, this.displayInfo);
if (status) { if (status) {
this.displayInfo.creditPayInfo.disabled = true; this.displayInfo.creditPayInfo.disabled = true;
...@@ -510,10 +528,19 @@ export default { ...@@ -510,10 +528,19 @@ export default {
}, },
/* 进入h5授信流程 */ /* 进入h5授信流程 */
async goApply() { async goApply() {
if (this.$route.query.ka) {
this.getKaGetNextUrl();
return;
}
const [{ url }] = await h5AppyUrl(); const [{ url }] = await h5AppyUrl();
if (url) return; if (!url) return;
window.location.href = url; window.location.href = url;
}, },
async getKaGetNextUrl() {
const [{ nextUrl }] = await kaGetNextUrl();
if (!nextUrl) return;
window.location.href = `${nextUrl}&returnUrl=${window.location.href}`;
},
/* 走h5活体流程 */ /* 走h5活体流程 */
async goOcr() { async goOcr() {
const [{ url }] = await ocrFaceId({ const [{ url }] = await ocrFaceId({
...@@ -538,14 +565,12 @@ export default { ...@@ -538,14 +565,12 @@ export default {
}, },
/* 忘记密码 */ /* 忘记密码 */
retrieveLink() { retrieveLink() {
const url = `${this.creditPayInfo.forgetPwdJumpUrl}&vccChannel=${VCC_CHANNEL}`; let url = `${this.creditPayInfo.forgetPwdJumpUrl}&vccChannel=${VCC_CHANNEL}&redirectUrl=${window.location.href}`;
url = url.replace('{token}', localStorage.get('vccToken'));
window.location.href = url; window.location.href = url;
}, },
goHome() { getObjectKey(obj) {
// 商城地址 return Object.keys(obj);
},
goOrderDetail() {
// 订单详情地址
} }
} }
}; };
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<cr-button shape="circle" class="actions__back" :plain="true" type="primary" @click="goHome" <cr-button shape="circle" class="actions__back" :plain="true" type="primary" @click="goHome"
>返回首页</cr-button >返回首页</cr-button
> >
<cr-button shape="circle" type="primary" @click="goOrderDetail">查看订单</cr-button> <cr-button shape="circle" type="primary" @click="goOrderList">查看订单</cr-button>
</div> </div>
</div> </div>
<div v-else class="card"> <div v-else class="card">
...@@ -47,41 +47,35 @@ ...@@ -47,41 +47,35 @@
<script> <script>
import { registeredEvents } from '@/service/sa.service'; import { registeredEvents } from '@/service/sa.service';
import RecoGoods from '@/components/RecoGoods.vue'; import RecoGoods from '@/components/RecoGoods.vue';
import localStorage from '@/service/localStorage.service';
import { goUrlExtends } from './extends';
export default { export default {
components: { RecoGoods }, components: { RecoGoods },
extends: goUrlExtends,
data() { data() {
return { return {
money: '00.00', money: '00.00',
orderNo: null, orderNo: null,
isSuccess: null, isSuccess: false,
freeAmount: null freeAmount: 0
}; };
}, },
created() { created() {
const { amount, orderNo, freeAmount, reason } = this.$route.query; const { orderNo, reason } = this.$route.query;
const { success } = this.$route.meta; const { success } = this.$route.meta;
console.log(this.$route.meta); const amount = localStorage.get('amount');
this.money = amount; this.money = amount.finalAmt;
this.orderNo = orderNo; this.orderNo = orderNo;
this.reason = reason || ''; this.reason = reason || '';
this.isSuccess = success || false; this.isSuccess = success || false;
this.freeAmount = freeAmount; this.freeAmount = amount.freeAmount;
}, },
methods: { methods: {
goHome() {
// 去页面
},
goOrderDetail() {
registeredEvents('PD_YXMMAEC_UserClickCashierCheckOrderBtn', {
order_id: this.orderNo
});
// 去订单详情页面
},
goPay() { goPay() {
registeredEvents('PD_YXMMAEC_UserClickCashierPaymentAgainBtn', { registeredEvents('PD_YXMMAEC_UserClickCashierPaymentAgainBtn', {
order_id: this.orderNo order_id: this.orderNo
}); });
this.$router.push({ name: 'pay', query: { order: this.orderNo } }); this.$router.replace({ name: 'pay', query: { orderNo: this.orderNo } });
} }
} }
}; };
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
class="info__image" class="info__image"
src="../../assets/images/paying.png" src="../../assets/images/paying.png"
/> />
<div class="info__desc"> <div v-if="init" class="info__desc">
<p class="info__text">{{ time }}s)支付中...</p> <p class="info__text">{{ time }}s)支付中...</p>
</div> </div>
</div> </div>
...@@ -23,47 +23,73 @@ ...@@ -23,47 +23,73 @@
</div> </div>
</template> </template>
<script> <script>
import { registeredEvents } from '@/service/sa.service';
import { queryPayStatus } from '@/api/pay.api'; import { queryPayStatus } from '@/api/pay.api';
import localStorage from '@/service/localStorage.service';
import { goUrlExtends } from './extends';
export default { export default {
components: {}, components: {},
extends: goUrlExtends,
data() { data() {
return { return {
orderNo: null, orderNo: null,
timer: null, timer: null,
time: 10 time: 10,
init: false
}; };
}, },
created() { created() {
const { orderNo } = this.$route.query; this.orderNo = this.$route.query.orderNo || localStorage.get('orderNo')?.orderNo;
this.orderNo = orderNo;
}, },
mounted() { mounted() {
this.timer = setInterval(() => { this.$dialog({
this.time -= 1; message: '请确认订单已完成支付',
if (this.time % 2 === 0) { confirmButtonText: '已完成支付',
queryPayStatus({ orderNo: this.orderNo }); cancelButtonText: '重新支付',
confirmButtonColor: '#EC1500',
onCancel: () => {
this.goPay();
},
onConfirm: () => {
this.init = true;
this.loop();
} }
if (this.time < 1) { });
clearInterval(this.timer); },
} beforeDestroy() {
}, 2000); clearInterval(this.timer);
}, },
methods: { methods: {
goHome() { loop() {
// 去页面 this.query();
this.timer = setInterval(() => {
this.time -= 1;
if (this.time % 2 === 0) {
this.query();
}
if (this.time < 1) {
clearInterval(this.timer);
}
}, 2000);
}, },
goOrderDetail() { goSuccess() {
registeredEvents('PD_YXMMAEC_UserClickCashierCheckOrderBtn', { // 支付成功
order_id: this.orderNo this.$router.replace({ name: 'paySuccess' });
});
// 去订单详情页面
}, },
goPay() { goPay() {
registeredEvents('PD_YXMMAEC_UserClickCashierPaymentAgainBtn', { this.$router.replace({ name: 'pay', query: { orderNo: this.orderNo } });
order_id: this.orderNo },
}); async query() {
this.$router.push({ name: 'pay', query: { order: this.orderNo } }); const [data, error] = await queryPayStatus({ orderNo: this.orderNo });
if (error) {
this.$router.replace({
name: 'payFail',
query: { reason: error.message, orderNo: this.orderNo }
});
return;
}
if (+data?.payStatus === 3) {
this.goSuccess();
}
} }
} }
}; };
......
...@@ -2,7 +2,13 @@ ...@@ -2,7 +2,13 @@
<div class="Vl__account"> <div class="Vl__account">
<cr-field v-model="accountMask" :placeholder="`请输入${info.name || ''}账号`" clearable> <cr-field v-model="accountMask" :placeholder="`请输入${info.name || ''}账号`" clearable>
<template #button> <template #button>
<cr-image v-if="info.icon" :src="info.icon" width="0.64rem" height="0.64rem" /> <cr-image
v-if="info.icon"
:src="info.icon"
fit="contain"
width="0.64rem"
height="0.64rem"
/>
</template> </template>
</cr-field> </cr-field>
<!-- <div class="Vl__list" :class="{ show: !inputBlur }"> <!-- <div class="Vl__list" :class="{ show: !inputBlur }">
...@@ -46,7 +52,7 @@ export default { ...@@ -46,7 +52,7 @@ export default {
computed: { computed: {
accountMask: { accountMask: {
get() { get() {
return this.info.rechargeAccountType !== 3 ? this.phoneFormat(this.value) : this.value; return this.info.type !== 101 ? this.phoneFormat(this.value) : this.value;
}, },
set(val) { set(val) {
this.$emit('input', val.replace(/\s/g, '')); this.$emit('input', val.replace(/\s/g, ''));
......
<template functional> <template functional>
<div class="Vl__sku" :class="{ disabled: props.disabled, 'three-col': props.threeCol }"> <div class="Vl__sku" :class="{ disabled: props.disabled, 'three-col': props.threeCol }">
<div <template v-if="props.list.length">
v-for="(item, index) in props.list" <div
:key="index" v-for="(item, index) in props.list"
class="Vl__sku-item" :key="index"
:class="{ class="Vl__sku-item"
cheap: item.price - item.salePrice > 0, :class="{
active: props.info.skuNo === item.skuNo, cheap: item.price - item.salePrice > 0,
nohhird: (index + 1) % 3 !== 0 active: props.info.skuNo === item.skuNo,
}" 'no-stock': !item.hasStock,
@click="parent.handleSkuSelected(item, index)" nohhird: (index + 1) % 3 !== 0
> }"
<div class="Vl__sku-name"> @click="item.hasStock && parent.handleSkuSelected(item, index)"
{{ props.threeCol ? item.salePrice : item.skuName }}{{ showUnit ? '' : '' }} >
<div class="Vl__sku-name">
{{ props.threeCol ? item.salePrice : item.skuName }}{{ props.showUnit ? '' : '' }}
</div>
<div class="Vl__sku-price">售价{{ item.price }}</div>
</div> </div>
<div class="Vl__sku-price">售价{{ props.threeCol ? item.price : item.salePrice }}</div> </template>
<div class="Vl__sku-tag">优惠</div> <cr-empty v-else class="Vl__sku-empty" image="commodity" description="暂无商品~" />
</div>
</div> </div>
</template> </template>
<script> <script>
...@@ -49,6 +52,9 @@ export default { ...@@ -49,6 +52,9 @@ export default {
align-content: flex-start; align-content: flex-start;
position: relative; position: relative;
z-index: 1; z-index: 1;
&-empty {
flex-flow: wrap;
}
&.disabled::before { &.disabled::before {
content: ' '; content: ' ';
z-index: 2; z-index: 2;
...@@ -85,13 +91,45 @@ export default { ...@@ -85,13 +91,45 @@ export default {
position: relative; position: relative;
margin-bottom: @padding-xs; margin-bottom: @padding-xs;
transition: all 0.1s linear; transition: all 0.1s linear;
&::before {
content: ' ';
background: @gray-2;
.text-10();
border-radius: 0 @border-radius-sm - 2 0 @border-radius-sm - 2;
padding: 0 @padding-unit;
position: absolute;
top: 0;
right: 0;
display: none;
}
// 优惠
&.cheap { &.cheap {
.Vl__sku-tag { &::before {
content: '\4f18\60e0';
display: block; display: block;
color: @white; color: @white;
background: linear-gradient(269deg, #ff5d00 12%, #ff1900 86%); background: linear-gradient(269deg, #ff5d00 12%, #ff1900 86%);
} }
} }
// 补货中
&.no-stock {
background: @white !important;
border-color: @grey-border !important;
pointer-events: none;
cursor: not-allowed;
&::before {
content: '\8865\8d27\4e2d';
display: block;
color: @white;
background: linear-gradient(90deg, #cecece 2%, #989898 98%);
}
.Vl__sku-name {
color: @gray-4 !important;
}
.Vl__sku-price {
color: @gray-4 !important;
}
}
&.active { &.active {
background: #fff5f5; background: #fff5f5;
border: 1px solid @red; border: 1px solid @red;
...@@ -117,16 +155,6 @@ export default { ...@@ -117,16 +155,6 @@ export default {
color: @gray-5; color: @gray-5;
.text-12(); .text-12();
} }
&-tag {
background: @gray-2;
.text-10();
border-radius: 0 @border-radius-sm - 2 0 @border-radius-sm - 2;
padding: 0 @padding-unit;
position: absolute;
top: 0;
right: 0;
display: none;
}
} }
} }
</style> </style>
<template> <template>
<div ref="spuList" class="Vl__spu-wrapper"> <div ref="spuList" class="Vl__spu-wrapper">
<div class="Vl__spu" :style="{ width: numAddUnit(contentWidth) }"> <div class="Vl__spu" :style="{ minWidth: numAddUnit(contentWidth) }">
<div <div
v-for="(item, index) in list" v-for="(item, index) in list"
:key="index" :key="index"
class="Vl__spu-item" class="Vl__spu-item"
:class="{ 'Vl__spu-item_active': info.spuNo === item.spuNo }" :class="{ 'Vl__spu-item_active': info.spuNos === item.spuNos }"
@click="handleSpuClick($event, item, index)" @click="handleSpuClick($event, item, index)"
> >
<cr-image :src="item.icon" height="1.093333rem" width="1.093333rem" class="Vl__spu-icon" /> <cr-image
:src="item.icon"
height="1.093333rem"
width="1.093333rem"
fit="contain"
class="Vl__spu-icon"
/>
<div class="Vl__spu-name">{{ item.name }}</div> <div class="Vl__spu-name">{{ item.name }}</div>
</div> </div>
<div class="Vl__spu-placeholder" :style="{ width: numAddUnit(placeholderWidth) }" />
</div> </div>
</div> </div>
</template> </template>
...@@ -25,7 +30,7 @@ export default { ...@@ -25,7 +30,7 @@ export default {
type: Array, type: Array,
default: () => [ default: () => [
{ {
spuNo: '', spuNos: '',
icon: '', icon: '',
name: '' name: ''
} }
...@@ -42,34 +47,44 @@ export default { ...@@ -42,34 +47,44 @@ export default {
}; };
}, },
computed: { computed: {
contentWidth() {
return ITEM_WIDTH * (this.list.length + 2.34);
}
},
watch: {
contentWidth() { contentWidth() {
this.$nextTick(() => { this.$nextTick(() => {
this.listWrapper && this.listWrapper.refresh(); this.listWrapper.scrollTo(0, 0);
this.listWrapper.refresh();
}); });
return ITEM_WIDTH * this.list.length + this.placeholderWidth;
},
placeholderWidth() {
return ((this.list.length % 4) + 1.335) * ITEM_WIDTH;
} }
}, },
mounted() { mounted() {
this.$nextTick(() => { this.createScroller();
this.listWrapper = new BScroll(this.$refs.spuList, { },
click: true, beforeDestroy() {
scrollX: true, this.listWrapper.destroy();
scrollY: false
});
});
}, },
methods: { methods: {
createScroller() {
this.$nextTick(() => {
if (this.listWrapper) {
this.listWrapper.destroy();
}
this.listWrapper = new BScroll(this.$refs.spuList, {
click: true,
scrollX: true,
scrollY: false
});
});
},
numAddUnit(num) { numAddUnit(num) {
return num / 37.5 + 'rem'; return num / 37.5 + 'rem';
}, },
handleSpuClick(e, item, index) { handleSpuClick(e, item, index) {
this.$parent.handleSpuSelected(item, index); this.$parent.handleSpuSelected(item, index);
const target = e.path.find(item => item.className.indexOf('Vl__spu-item') > -1); const target = e.path.find(item => item.className.indexOf('Vl__spu-item') > -1);
console.dir(target);
this.listWrapper.scrollToElement(target, 500, -10, 0); this.listWrapper.scrollToElement(target, 500, -10, 0);
} }
} }
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
position: fixed; position: fixed;
bottom: 0; bottom: 0;
left: 0; left: 0;
z-index: 2; z-index: 9;
right: 0; right: 0;
width: calc(100% - @padding-sm * 2); width: calc(100% - @padding-sm * 2);
background-color: @white; background-color: @white;
......
...@@ -15,15 +15,16 @@ ...@@ -15,15 +15,16 @@
<cr-loading color="#ec1500" /> <cr-loading color="#ec1500" />
</div> </div>
<template v-if="tips"> <template v-if="tips">
<div class="Vl__panel-title">温馨提示</div> <div class="Vl__panel-title">{{ tips.title }}</div>
<div class="Vl__panel-tips" v-html="tips" /> <div class="Vl__panel-tips" v-html="tips.content" />
</template> </template>
</div> </div>
<div v-if="!hideFixedBottom" class="Vl__bottom"> <div class="Vl__bottom">
<cr-button type="primary" block shape="circle" :disabled="disabled" @click="goOrder"> <cr-button type="primary" block shape="circle" :disabled="disabled" @click="goOrder">
立即充值 立即充值
</cr-button> </cr-button>
</div> </div>
<!-- v-show="!hideFixedBottom" -->
</div> </div>
</template> </template>
<script> <script>
...@@ -34,6 +35,7 @@ import tipsData from '@/api/tips'; ...@@ -34,6 +35,7 @@ import tipsData from '@/api/tips';
import SpuList from './components/SpuList.vue'; import SpuList from './components/SpuList.vue';
import SkuList from './components/SkuList.vue'; import SkuList from './components/SkuList.vue';
import AccountInput from './components/AccountInput.vue'; import AccountInput from './components/AccountInput.vue';
import { throttle } from '@/service/utils.service';
export default { export default {
name: 'VipLife', name: 'VipLife',
components: { components: {
...@@ -56,13 +58,15 @@ export default { ...@@ -56,13 +58,15 @@ export default {
}, },
computed: { computed: {
disabled() { disabled() {
return this.spuInfo.rechargeAccountType !== 2 && !this.account; return (this.spuInfo.rechargeAccountType !== 2 && !this.account) || !this.skuList.length;
}, },
spuList() { spuList() {
return this.spuData[this.currentTab - 1] ? this.spuData[this.currentTab - 1].itemList : []; return this.spuData[this.currentTab - 1] ? this.spuData[this.currentTab - 1].itemList : [];
}, },
tips() { tips() {
return tipsData[this.spuInfo.spuNo]; return this.spuInfo.type
? tipsData[this.spuInfo.type] || tipsData[+('' + this.spuInfo.type)[0]] || {}
: {};
} }
}, },
mounted() { mounted() {
...@@ -82,11 +86,11 @@ export default { ...@@ -82,11 +86,11 @@ export default {
methods: { methods: {
handleTabChange(name) { handleTabChange(name) {
this.currentTab = name; this.currentTab = name;
this.skuInfo = {};
this.updateSpuInfo(this.spuData[this.currentTab - 1].itemList[0]); this.updateSpuInfo(this.spuData[this.currentTab - 1].itemList[0]);
this.getSkuListDebounce(); this.getSkuListDebounce();
}, },
handleSpuSelected(item) { handleSpuSelected(item) {
this.spuInfo = item;
this.updateSpuInfo(item); this.updateSpuInfo(item);
this.getSkuListDebounce(); this.getSkuListDebounce();
}, },
...@@ -107,31 +111,32 @@ export default { ...@@ -107,31 +111,32 @@ export default {
}, },
getSkuListDebounce() { getSkuListDebounce() {
this.showLoading = true; this.showLoading = true;
this.skuList = [];
if (this.skuTimer) clearTimeout(this.skuTimer); if (this.skuTimer) clearTimeout(this.skuTimer);
this.skuTimer = setTimeout(() => { this.skuTimer = setTimeout(() => {
this.getSkuList(); this.getSkuList();
}, 600); }, 600);
}, },
async getSkuList() { async getSkuList() {
this.skuList = []; const { spuNos, type } = this.spuInfo;
const { spuNo: spuNos, type } = this.spuInfo; const [res] = await rechargeApi.getSkuList(spuNos, type);
const [res] = await rechargeApi.getSkuList({ spuNos, type });
if (res) { if (res) {
this.skuList = res.rechargeList; this.skuList = res.rechargeList;
this.handleSkuSelected(res.rechargeList[0], 0); const defaultItem = res.rechargeList.find(item => item.hasStock);
const defaultIndex = res.rechargeList.findIndex(item => item.hasStock);
defaultItem && this.handleSkuSelected(defaultItem, defaultIndex);
} }
this.showLoading = false; this.showLoading = false;
}, },
async goOrder() { goOrder: throttle(async function() {
if (!this.account && this.spuInfo.rechargeAccountType !== 2) if (!this.account && this.spuInfo.rechargeAccountType !== 2)
return this.$toast.fail('请填写账号!'); return this.$toast.fail('请填写账号!');
if (!this.skuInfo.skuNo) return this.$toast.fail('请选择类型!'); if (!this.skuInfo.skuNo) return this.$toast.fail('请选择类型!');
const { skuNo, salePrice } = this.skuInfo; const { skuNo, salePrice } = this.skuInfo;
const [res] = await orderApi.orderCreate({ const [res] = await orderApi.orderCreate({
account: this.account,
totalFee: salePrice, totalFee: salePrice,
orderCouponIds: '', virtualRechargeType: this.spuInfo.type,
freightCouponIds: '',
virtualRechargeType: this.spuInfo.rechargeAccountType,
skuList: [ skuList: [
{ {
skuNo, skuNo,
...@@ -140,7 +145,7 @@ export default { ...@@ -140,7 +145,7 @@ export default {
] ]
}); });
res && this.$router.push({ path: '/pay', query: { orderNo: res.orderNo } }); res && this.$router.push({ path: '/pay', query: { orderNo: res.orderNo } });
} }, 1000)
} }
}; };
</script> </script>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment