Commit f31000f9 authored by FE-安焕焕's avatar FE-安焕焕 👣

商城首页开发

parent c3371c4c
import request from '@/service/httpDecorator';
import config from '@/config';
const { talosApi } = config;
const { talosHost } = config;
const queryPayInfo = function(data) {
return request.post(`${talosApi}/open/checkout`, data);
return request.post(`${talosHost}/open/checkout`, data);
};
const prepay = function(data) {
console.log('prepay-param', data);
return request.post(`${talosApi}/open/checkout/prepay`, data);
return request.post(`${talosHost}/open/checkout/prepay`, data);
};
const pay = function(data) {
return request.post(`${talosApi}/open/checkout/pay`, data, {
return request.post(`${talosHost}/open/checkout/pay`, data, {
needScDeviceId: true
});
};
const queryPayStatus = function(data) {
return request.post(`${talosApi}/open/checkout/pay_status/query`, data);
return request.post(`${talosHost}/open/checkout/pay_status/query`, data);
};
const sendSms = function(data) {
return request.post(`${talosApi}/open/checkout/send_sms`, data);
return request.post(`${talosHost}/open/checkout/send_sms`, data);
};
const desSalt = function() {
return request.get(`${talosApi}/vcc/account/salt`);
return request.get(`${talosHost}/vcc/account/salt`);
};
const h5AppyUrl = function() {
return request.get(`${talosApi}/vcc/xyqb_mall/app_url`);
return request.get(`${talosHost}/vcc/xyqb_mall/app_url`);
};
const getCoupon = function(params) {
return request.post(`${talosApi}/open/checkout/pay_coupon_list`, params);
return request.post(`${talosHost}/open/checkout/pay_coupon_list`, params);
};
const ocrFaceId = function(params) {
return request.post(`${talosApi}open/checkout/ocr_faceId`, params);
return request.post(`${talosHost}open/checkout/ocr_faceId`, params);
};
export {
......
......@@ -8,11 +8,13 @@ export default {
return http.get(talosHost + '/api/kdsp/virtual/recharge-center/config');
},
// VIP充值中心SKU列表
getSkuList() {
return http.get(talosHost + '/api/kdsp/virtual/recharge-center/recharge-list');
getSkuList(spuNos, type) {
return http.get(
`${talosHost}/api/kdsp/virtual/recharge-center/recharge-list?spuNos=${spuNos}&type=${type}`
);
},
// 查询归属地
getPhoneHome() {
return http.get(talosHost + '/api/kdsp/virtual/recharge-center/phone-home');
getPhoneHome(phoneNo) {
return http.get(`${talosHost}/api/kdsp/virtual/recharge-center/phone-home?phoneNo=${phoneNo}`);
}
};
src/assets/images/addicon.png

1.06 KB | W: | H:

src/assets/images/addicon.png

465 Bytes | W: | H:

src/assets/images/addicon.png
src/assets/images/addicon.png
src/assets/images/addicon.png
src/assets/images/addicon.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/images/paying.png

4.36 KB | W: | H:

src/assets/images/paying.png

1.13 KB | W: | H:

src/assets/images/paying.png
src/assets/images/paying.png
src/assets/images/paying.png
src/assets/images/paying.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -14,11 +14,6 @@ let protocol = window.location.protocol;
let payHost = protocol + '//mapi-qa.liangkebang.net/pay';
let shenceHost = 'https://bn.xyqb.com/sa?project=default'; // 测试地址
<<<<<<< HEAD
let talosHost = 'http://yapi.quantgroups.com/mock/351'; // 电商分期测试环境服务地址
// let talosHost = 'https://talos-vcc2.liangkebang.net'; // 电商分期测试环境服务地址
=======
let talosApi = 'http://yapi.quantgroups.com/mock/410'; // 电商分期测试环境服务地址
>>>>>>> 支付开发
let operatorHost = 'https://operator.liangkebang.com';
export default { talosApi, operatorHost, payHost, shenceHost, test: true };
export default { talosHost, operatorHost, payHost, shenceHost, test: true };
export default [
{
path: '/',
redirect: '/pay'
redirect: '/home'
},
{
path: '/home',
name: 'home',
meta: {
title: '充值中心'
},
component: () => import('../views/home')
},
{
path: '/pay',
......@@ -9,7 +17,7 @@ export default [
meta: {
title: '收银台'
},
component: () => import('../pay')
component: () => import('../views/pay')
},
{
path: '/payFail',
......@@ -18,7 +26,7 @@ export default [
meta: {
title: '支付失败'
},
component: () => import('../pay/payResult')
component: () => import('../views/pay/payResult')
},
{
path: '/paySuccess',
......@@ -28,7 +36,7 @@ export default [
title: '支付成功',
success: true
},
component: () => import('../pay/payResult')
component: () => import('../views/pay/payResult')
},
{
path: '/vipLife',
......@@ -53,28 +61,15 @@ export default [
title: '订单详情'
},
component: () => import('../views/orderDetail')
},{
},
{
path: '/payWaiting',
name: 'payWaiting',
meta: {
title: '支付中',
success: true
},
component: () => import('../pay/payWaiting')
},
{
path: '/demo',
alias: ['/demo-page'],
name: 'demo-page',
back: false,
meta: {
title: 'DEMO',
has: {
header: true,
footer: true
}
},
component: () => import('../views/demo')
component: () => import('../views/pay/payWaiting')
},
{
path: '/error',
......
......@@ -27,14 +27,11 @@ import {
Sticky,
Tab,
Tabs,
<<<<<<< HEAD
Empty
=======
Empty,
CountDown,
PwdField,
AuthcodeField,
CouponList
>>>>>>> 支付开发
} from '@qg/cherry-ui';
import DialogFn from '@qg/cherry-ui/src/dialog/func';
// import "@qg/cherry-ui/dist/cherry.css";
......@@ -64,14 +61,11 @@ Vue.use(Loading);
Vue.use(List);
Vue.use(Tab);
Vue.use(Tabs);
<<<<<<< HEAD
Vue.use(Empty);
=======
Vue.use(CountDown);
Vue.use(PwdField);
Vue.use(AuthcodeField);
Vue.use(CouponList);
>>>>>>> 支付开发
// const _proto = Vue.prototype;
// const proto = Object.create(_proto);
......
import HttpRequest from '@qg/ui-request';
import { Toast } from '@qg/cherry-ui';
import store from '@/store';
console.log(HttpRequest);
const http = new HttpRequest(
{},
{},
......@@ -10,6 +11,5 @@ const http = new HttpRequest(
function(loadingState) {
store.dispatch('change_loading', loadingState);
}
).getInstance();
);
export default http;
......@@ -314,12 +314,31 @@ export function idNoFormat(value) {
export function dateFormat(value) {
return value.replace(/(\d{4})(\d{2})(\d{2})/, '$1.$2.$3');
}
<<<<<<< HEAD
export function phoneFormat(value) {
return value.replace(/(\d{3})(\d{4})(\d{4})/, '$1 $2 $3');
=======
export function phoneFormat(mobile) {
/* 将手机号格式化 */
if (!mobile) return;
let value = mobile.replace(/\D/g, '').substr(0, 11); // 不允许输入非数字字符,超过11位数字截取前11位
let len = value.length;
if (len > 3 && len < 8) {
value = value.replace(/^(\d{3})/g, '$1 ');
} else if (len >= 8) {
value = value.replace(/^(\d{3})(\d{4})/g, '$1 $2 ');
}
return value;
}
export function checkPhoneFormat(mobile) {
/* 校验手机号格式 */
if (!mobile) return;
const reg = /^1(3[0-9]|4[5,7]|5[0,1,2,3,5,6,7,8,9]|6[2,5,6,7]|7[0,1,7,8]|8[0-9]|9[1,8,9])\d{8}$/;
return reg.test(mobile);
}
export function phoneTrim(mobile) {
if (!mobile) return;
return mobile.replace(/\s/g, '');
}
export function isObject(value) {
return Object.prototype.toString.call(value) === '[object Object]';
>>>>>>> 支付开发
}
<template>
<div class="center">
<cr-tabs
v-model="rechargeType"
background="#ffffff"
class="center-recharge"
@change="changeRechargeType"
>
<cr-tab title="话费充值" :title-style="tabItemStyle" name="recharge">
<PhoneRechargeList
:list="rechargeList.recharge"
:info="selectedRechargeInfo"
:three-col="true"
/>
</cr-tab>
<cr-tab title="话费慢冲" :title-style="tabItemStyle" name="slowRecharge">
<PhoneRechargeList
:list="rechargeList.slowRecharge"
:info="selectedRechargeInfo"
:three-col="true"
/></cr-tab>
</cr-tabs>
</div>
</template>
<script>
import api from '@/api/recharge.api';
import PhoneRechargeList from '../vipLife/components/SkuList.vue';
const { getSpuList, getSkuList } = api;
export default {
components: {
PhoneRechargeList
},
props: { info: Object },
data() {
return {
tabItemStyle: {
width: '75px',
flex: 'none'
},
rechargeList: {
recharge: [],
slowRecharge: []
},
rechargeTel: 'recharge',
selectedRechargeInfo: {}
};
},
async mounted() {
const [data] = await getSpuList();
if (data) {
this.vipLife = data.vipLife || [];
this.phoneRecharge = data.phoneRecharge || {};
this.userPhoneInfo = data.userPhoneInfo || {};
this.changeTelFormat(this.userPhoneInfo.phoneNo);
this.phoneNoHome = this.userPhoneInfo.phoneNoHome;
this.changeRechargeType('recharge');
}
},
methods: {
async changeRechargeType(name) {
const [data] = await getSkuList(
this.phoneRecharge[`${name}SpuNo`],
this.phoneRecharge[`${name}Type`]
);
this.rechargeList[name] = data.rechargeList || [];
},
handleSkuSelected(item) {
this.selectedRechargeInfo = item;
this.$emit('selectedRecherge', item);
}
}
};
</script>
<style lang="less">
@import './index';
</style>
.center {
height: 100%;
.top {
width: 100%;
height: 132px;
padding: 10px;
box-sizing: border-box;
background: url('../../assets/images/ellipse.png');
background-size: 100%;
background-repeat: no-repeat;
&-link {
text-align: right;
&-title {
.text-14();
width: 64px;
padding: 0 @padding-xs;
color: @white;
&-first {
border-right: 1px solid @white;
}
}
}
&-tabs {
position: relative;
height: 108px;
width: 351px;
box-sizing: border-box;
overflow: hidden;
margin: auto;
border-radius: 8px;
background: @white;
padding: @padding-xs @padding-sm;
top: 16px;
&-title {
.text-14();
font-weight: bold;
color: @black;
}
&-recharge {
display: flex;
margin-top: 10px;
overflow-x: auto;
overflow-y: hidden;
justify-content: space-between;
}
}
}
.recharge {
width: 55px;
height: 55px;
text-align: center;
&-name {
.text-12();
color: @gray-5;
}
}
.center {
width: 351px;
height: 451px;
box-sizing: border-box;
background: @white;
border-radius: 8px;
padding: 14px;
margin: auto;
margin-top: 50px;
&-phone {
border-bottom: 1px solid #dcdcdc;
.cr-cell__title {
display: none;
}
.cr-cell {
padding: @padding-xs 0;
font-size: 24px;
color: @black;
}
&-location {
.text-12();
color: @gray-5;
}
}
&-recharge {
height: 300px;
margin-top: @padding-xs;
margin-bottom: @padding-xs;
}
.button{
.text-18();
}
}
}
\ No newline at end of file
<template>
<div class="center">
<div class="top">
<div class="top-link">
<a href="#" class="top-link-title top-link-title-first" @click="goOrderList">充值订单</a>
<a href="#" class="top-link-title" @click="goHelper">联系客服</a>
</div>
<div class="top-tabs">
<p class="top-tabs-title">娱乐生活</p>
<div class="top-tabs-recharge">
<div v-for="life in vipLife" :key="life.type" class="recharge" @click="goVipLife(life)">
<cr-image width="34px" height="34px" :src="life.icon" />
<p class="recharge-name">{{ life.name }}</p>
</div>
</div>
</div>
</div>
<div class="center">
<p class="center-phone">
<span v-if="rechargeTel" class="center-phone-location"
>{{ isDefaultphone ? '默认号码' : '未知号码'
}}{{ phoneNoHome ? `(${phoneNoHome})` : '' }}</span
>
<cr-field
v-model="rechargeTel"
type="tel"
@input="changeTelFormat"
@blur="searchPhoneNoHome"
/>
</p>
<!-- <PhoneRecharge :info="phoneRecharge" /> -->
<cr-tabs
v-model="rechargeType"
background="#ffffff"
class="center-recharge"
@change="changeRechargeType"
>
<cr-tab title="话费充值" :title-style="tabItemStyle" name="recharge">
<PhoneRechargeList
:list="rechargeList.recharge"
:info="selectedRechargeInfo"
:three-col="true"
/>
</cr-tab>
<cr-tab title="话费慢冲" :title-style="tabItemStyle" name="slowRecharge">
<PhoneRechargeList
:list="rechargeList.slowRecharge"
:info="selectedRechargeInfo"
:three-col="true"
/></cr-tab>
</cr-tabs>
<cr-button
type="primary"
block
shape="circle"
:disabled="!disabled"
class="button"
@click="goOrder"
>
{{ selectedRechargeInfo.salePrice ? `¥${selectedRechargeInfo.salePrice}` : '' }}立即充值
</cr-button>
</div>
</div>
</template>
<script>
import { phoneFormat, phoneTrim, checkPhoneFormat } from '@/service/utils.service';
import api from '@/api/recharge.api';
import PhoneRechargeList from '../vipLife/components/SkuList.vue';
const { getSpuList, getPhoneHome, getSkuList } = api;
// 组件抽离
// 下订单
export default {
components: {
PhoneRechargeList
},
data() {
return {
vipLife: [],
phoneNoHome: '',
rechargeType: null,
rechargeAmount: 0,
tabItemStyle: {
width: '75px',
flex: 'none'
},
phoneRecharge: {},
userPhoneInfo: {},
rechargeList: {
recharge: [],
slowRecharge: []
},
rechargeTel: 'recharge',
selectedRechargeInfo: {}
};
},
computed: {
disabled: function() {
return (
this.rechargeTel &&
phoneTrim(this.rechargeTel).length === 11 &&
checkPhoneFormat(this.phoneNo) &&
this.selectedRechargeInfo.salePrice
);
},
isDefaultphone: function() {
return phoneTrim(this.rechargeTel) === this.userPhoneInfo.phoneNo;
},
phoneNo: function() {
return phoneTrim(this.rechargeTel);
}
},
created() {},
async mounted() {
const [data] = await getSpuList();
if (data) {
this.vipLife = data.vipLife || [];
this.phoneRecharge = data.phoneRecharge || {};
this.userPhoneInfo = data.userPhoneInfo || {};
this.changeTelFormat(this.userPhoneInfo.phoneNo);
this.phoneNoHome = this.userPhoneInfo.phoneNoHome;
this.changeRechargeType('recharge');
}
},
methods: {
changeTelFormat(phone) {
this.rechargeTel = phoneFormat(phone);
},
async searchPhoneNoHome() {
if (!this.phoneNo) return;
if (!checkPhoneFormat(this.phoneNo)) {
this.$toast.fail('请您输入正确的手机号');
}
const [data] = await getPhoneHome(this.phoneNo);
this.phoneNoHome = data.phoneNoHome;
},
async changeRechargeType(name) {
const [data] = await getSkuList(
this.phoneRecharge[`${name}SpuNo`],
this.phoneRecharge[`${name}Type`]
);
this.rechargeList[name] = data.rechargeList || [];
},
handleSkuSelected(item) {
this.selectedRechargeInfo = item;
},
goOrder() {},
goOrderList() {
this.$router.push({ name: 'orderList' });
},
goHelper() {},
goVipLife(spu) {
this.$router.push({
name: 'vipLife',
query: {
spuType: spu.type
}
});
}
}
};
</script>
<style lang="less">
@import './index';
</style>
......@@ -132,7 +132,7 @@ export default {
margin-top: -12px;
left: 50%;
margin-left: -12px;
background: url('../../assets/images/addicon.png') no-repeat;
background: url('../../../assets/images/addicon.png') no-repeat;
background-size: 100%;
}
}
......
<template>
<div class="card">
<div class="info">
<cr-image width="63px" height="63px" class="info__image" src="../assets/images/paying.png" />
<cr-image
width="63px"
height="63px"
class="info__image"
src="../../assets/images/paying.png"
/>
<div class="info__desc">
<p class="info__text">{{ time }}s)支付中...</p>
</div>
......@@ -19,7 +24,7 @@
</template>
<script>
import { registeredEvents } from '@/service/sa.service';
import { queryPayStatus } from '../api/pay.api';
import { queryPayStatus } from '@/api/pay.api';
export default {
components: {},
data() {
......
......@@ -6,12 +6,13 @@
class="Vl__sku-item"
:class="{
cheap: item.price - item.salePrice > 0,
active: props.info.skuNo === item.skuNo
active: props.info.skuNo === item.skuNo,
nohhird: (index + 1) % 3 !== 0
}"
@click="parent.handleSkuSelected(item, index)"
>
<div class="Vl__sku-name">{{ item.skuName }}</div>
<div class="Vl__sku-price">{{ item.salePrice }}</div>
<div class="Vl__sku-name">{{ props.threeCol ? item.salePrice : item.skuName }}</div>
<div class="Vl__sku-price">售价{{ props.threeCol ? item.price : item.salePrice }}</div>
<div class="Vl__sku-tag">优惠</div>
</div>
</div>
......@@ -39,6 +40,7 @@ export default {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-content: flex-start;
position: relative;
z-index: 1;
&.disabled::before {
......@@ -53,6 +55,12 @@ export default {
background: rgba(255, 255, 255, 0.6);
}
&.three-col {
height: 250px;
justify-content: flex-start;
overflow: auto;
.nohhird {
margin-right: 4px;
}
.Vl__sku-item {
width: 103px;
}
......
<template>
<div class="page page__nopad">
<cr-tabs v-model="currentTab" @change="handleTabChange">
<cr-tab v-for="(item, index) in spuData" :key="index" :title="item.name" :name="index" />
<cr-tab v-for="(item, index) in spuData" :key="index" :title="item.name" :name="+item.type" />
</cr-tabs>
<spu-list :list="spuList" :info="spuInfo" />
<div class="Vl__panel">
......@@ -50,7 +50,7 @@ export default {
return this.spuInfo.rechargeAccountType !== 2 && !this.account;
},
spuList() {
return this.spuData[this.currentTab] ? this.spuData[this.currentTab].itemList : [];
return this.spuData[this.currentTab - 1] ? this.spuData[this.currentTab - 1].itemList : [];
},
tips() {
return tipsData[this.spuInfo.spuNo];
......@@ -58,6 +58,7 @@ export default {
},
mounted() {
this.currentTab = +this.$route.query.spuType || 0;
console.log(this.currentTab);
this.$nextTick(() => {
this.getList();
});
......
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