浏览代码

Merge branch 'feat-package' into develop

feat
JinxChen 1年前
父节点
当前提交
1fa1357e7e
共有 6 个文件被更改,包括 734 次插入12 次删除
  1. +8
    -1
      README.md
  2. +1
    -1
      src/config/models.js
  3. +2
    -1
      src/router/index.js
  4. +4
    -4
      src/views/buy-record/index.vue
  5. +49
    -5
      src/views/card-info/index.vue
  6. +670
    -0
      src/views/package-buy/index.vue

+ 8
- 1
README.md 查看文件

@@ -255,4 +255,11 @@ update
## v1.0.29
`2023.3.13`
feat
- 增加 套餐列表从接口获取
- 增加 套餐列表从接口获取

## v1.0.30
`2023.3.14`
feat
- cardInfo
- 增加 物联网卡套餐信息查询页面
- 增加 加油包合基础套餐购买页面

+ 1
- 1
src/config/models.js 查看文件

@@ -5,7 +5,7 @@
* @FilePath: \TelpoH5FrontendWeb\src\config\models.js
* @description:
*/
export const VERSION_MODEL = '1.0.29F'; //版本号
export const VERSION_MODEL = '1.0.30F'; //版本号
export const IMAGE_URL = {
production: 'http://zfb.ssjlai.com/web/',
test: 'http://zfb.ssjlai.com/web/',


+ 2
- 1
src/router/index.js 查看文件

@@ -1,7 +1,7 @@
/*
* @Date: 2023-02-25 16:34:35
* @LastEditors: JinxChen
* @LastEditTime: 2023-02-26 15:30:31
* @LastEditTime: 2023-03-14 09:33:17
* @FilePath: \TelpoH5FrontendWeb\src\router\index.js
* @description:
*/
@@ -25,6 +25,7 @@ const routes = [
{ path: '/packageList', name: 'packageList', component: resolve => require(['@/views/package-list'], resolve) },
{ path: '/payResult', name: 'payResult', component: resolve => require(['@/views/pay-result'], resolve) },
{ path: '/cardInfo', name: 'cardInfo', component: resolve => require(['@/views/card-info'], resolve) },
{ path: '/packageBuy', name: 'packageBuy', component: resolve => require(['@/views/package-buy'], resolve) },
{ path: '/buyRecord', name: 'buyRecord', component: resolve => require(['@/views/buy-record'], resolve) },
{ path: '/activeStatus', name: 'activeStatus', component: resolve => require(['@/views/active-status'], resolve) },
{ path: '/cardActive', name: 'cardActive', component: resolve => require(['@/views/card-active'], resolve) },


+ 4
- 4
src/views/buy-record/index.vue 查看文件

@@ -93,10 +93,10 @@ export default {
})
},
onNavBack() {
/* this.$router.push({
name: "check",
query: { serialNo: this.$route.query.serialNo, iccid: this.$route.query.iccid, isShowMenu: true}
}); */
this.$router.replace({
name: "cardInfo",
query: { imei: this.$route.query.imei, iccid: this.$route.query.iccid, isShowMenu: true}
});
},
// 复制订单号
onCopy(type) {


+ 49
- 5
src/views/card-info/index.vue 查看文件

@@ -1,7 +1,7 @@
<!--
* @Date: 2022-04-15 10:22:36
* @LastEditors: JinxChen
* @LastEditTime: 2023-02-26 15:05:41
* @LastEditTime: 2023-03-14 11:42:57
* @FilePath: \TelpoH5FrontendWeb\src\views\card-info\index.vue
* @description:
-->
@@ -71,6 +71,9 @@

<script>
import APIWx from "@/api/wx";
import { APIPay } from "@/api/pay";
import { isNotNull } from "@/utils/index";
import APICore from "@/api/core";
export default {
name:'cardInfo',
inject: ["reload"],
@@ -89,6 +92,7 @@ export default {
isUnicom: null, //是否是联通
},
isShowMenu: this.$route.query.isShowMenu,
params: {}
}
},
computed: {
@@ -102,9 +106,49 @@ export default {
}
},
created() {
this.getCardInfo();
this.getAuth();
this.getParams();
this.getCardInfo();
},
methods: {
// 获取core token
getAuth() {
let manufactorId = "5bf13062-a41e-4d00-ba14-1101aad12650";
APICore.getAuth({ manufactorId: manufactorId }).then(res => {
this.$store.commit("gatewayToken", res.data.data);
});
},
// 获取url传过来的参数
getParams() {
let params = this.$route.query;
if (params) {
let url = window.location.href.split("?code=")[1];
if ( isNotNull(url) || window.location.href.indexOf("code") > -1) {
let timeStamp = new Date().getTime();
let code = url.split("&")[0];
if (isNotNull(code)) {
this.$store.commit("wxAuthCode", `${code}`);
this.getOpenId();
}
}
this.params = {...params};
}
},
// 根据code获取openId
getOpenId() {
let code = this.$store.getters.wxAuthCode;
let openId = this.$store.getters.openId;
if(isNotNull(openId)) {
console.log("已经存在openId");
} else {
APIPay.getOpenId(code).then(res => {
let data= res.data;
if(data.code === 20000) {
this.$store.commit("openId", data.data.openId);
}
})
}
},
//获取小台风物联网卡信息
getCardInfo() {
this.$toast.loading({ message: '查询中...' });
@@ -147,14 +191,14 @@ export default {
},
// 购买套餐
onMealBuy() {
this.$router.push({
name: 'packageList',
this.$router.replace({
name: 'packageBuy',
query: { imei: this.$route.query.imei, iccid: this.$route.query.iccid, isShowMenu: this.isShowMenu}
})
},
// 订购记录
onRecordCheck () {
this.$router.push({
this.$router.replace({
name: 'buyRecord',
query: { imei: this.$route.query.imei, iccid: this.$route.query.iccid, isShowMenu: this.isShowMenu}
})


+ 670
- 0
src/views/package-buy/index.vue 查看文件

@@ -0,0 +1,670 @@
<!--
* @Date: 2023-03-14 09:32:37
* @LastEditors: JinxChen
* @LastEditTime: 2023-03-14 11:35:43
* @FilePath: \TelpoH5FrontendWeb\src\views\package-buy\index.vue
* @description:
-->
<template>
<div class="package-buy-container">
<van-nav-bar :left-arrow="false" :border="true">
<template #title>
<h5 style="font-size: 16px">套餐订购</h5>
</template>
</van-nav-bar>
<!-- 套餐内容 -->
<div class="package-container">
<van-tabs
type="line"
v-model="active"
color="#1890ff"
background="#fafafa"
swipeable
line-width="20%"
line-height="4px"
>
<van-tab title="加油包">
<div class="refuel-package" v-if="refuelPackageList.length > 0">
<div
class="refuel-item"
v-for="(item, index) in refuelPackageList"
:key="index"
>
<div class="title">
<p>{{item.packagesName}}</p>
</div>
<div class="bottom">
<span>
{{item.packagesPrice}}
<span class="price-span">元</span>
</span>
<div class="btn-button" @click="onBuyRefuel(item)">
<p>立即订购</p>
</div>
</div>
</div>
</div>
<div class="data-null" v-else>
<img src="@/assets/img/news-noData.png" alt />
<span>暂无加油包</span>
</div>
</van-tab>
<van-tab title="基础套餐">
<div class="base-package" v-if="basePackageList.length > 0">
<div
class="base-item"
v-for="(item, index) in basePackageList"
:key="index"
>
<div class="base-item-content">
<!-- <div class="title">
<p>{{item.packagesName}}</p>
</div>-->
<div class="remark">
<p>每月200分钟通话时长,1G流量</p>
</div>
<div class="details">
<p>
<span
class="orange large"
>¥{{(item.packagesPrice/(item.packageIssue === 0 ? 1: item.packageIssue)).toFixed(0)}}</span>元/月,
</p>
<p class="total">
<span>合计</span>
<span class="orange price">{{item.packagesPrice}}元</span>
</p>
</div>
<div class="radios-con">
<div class="pay-type">
<p>支付方式:</p>
</div>
<van-radio-group
v-model="radio"
direction="horizontal"
@change="onRaidoChange"
>
<van-radio name="1">
<template #default>
<div class="radio-con">
<span>微信</span>
<img src="../../assets/wx-pay.png" />
</div>
</template>
</van-radio>
<van-radio name="2">
<template #default>
<div class="radio-con">
<span>支付宝</span>
<img src="../../assets/alipay.png" />
</div>
</template>
</van-radio>
<van-radio name="3">
<template #default>
<div class="radio-con">
<span>12期花呗</span>
<img src="../../assets/antpay.png" />
</div>
</template>
</van-radio>
</van-radio-group>
</div>
<div class="package-buy">
<div class="buy-btn" @click="onBuyBase(item)">
<p>套餐订购</p>
</div>
</div>
</div>
</div>
</div>
<div class="data-null" v-else>
<img src="@/assets/img/news-noData.png" alt />
<span>暂无基础套餐</span>
</div>
</van-tab>
</van-tabs>
</div>
</div>
</template>

<script>
import APICore from "@/api/core";
import APIWx from "@/api/wx";
import AppId from "@/config/appId";
import { APIPay } from "@/api/pay";
let wx = require("weixin-js-sdk"); // TODO 再封装,可拦截错误提示等操作
export default {
name:'',
data(){
return {
basePackageList: [], //基础套餐
refuelPackageList: [], //加油包
outTradeNo: "", //订单号
price: "", //价格,
isShowNoData: false, //是否显示无套餐内容, 默认false
radio: '1', //支付方式单选按钮默认值
payProductId: null, //套餐id
packageIssue: null, //套餐分期
payType: '1', //支付方式 1 微信, 2 支付宝,支付宝又分为花呗和全额支付,全额支付分期数传0 或者1 ,花呗则传 3 6 12
active: 0, //tabs默认选择的下标
}
},
methods: {
// 获取core token
getAuth() {
let manufactorId = "5bf13062-a41e-4d00-ba14-1101aad12650";
APICore.getAuth({ manufactorId: manufactorId }).then(res => {
this.$store.commit("gatewayToken", res.data.data);
});
},
// 获取微信授权
getWxAutograph(){
let that = this;
return new Promise((resolve, reject) => {
APIWx.createJSSDK({
sUrl: window.location.href.split("#")[0],
userId: '',
appId: AppId
})
.then(res => {
let item = res.data.data;
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: item.appId, // 必填,公众号的唯一标识
timestamp: item.timeStamp, // 必填,生成签名的时间戳
nonceStr: item.nonceStr, // 必填,生成签名的随机串
signature: item.signature, // 必填,签名
jsApiList: ["chooseWXPay"] // 必填,需要使用的JS接口列表
});

wx.ready(() => {
resolve(true);
});
})
.catch(err => {
reject(false);
console.log(err);
});
});
},
// 获取套餐列表数据
getDevicePayPackage() {
this.$toast.loading({
message: "加载中",
duration: 1500
});
APICore.devicePayPackage(this.$route.query.imei)
.then(res => {
console.log("data", res.data);
if (res.data.code === 106 || res.data.code === 104) {
// token过期
this.getAuth();
setTimeout(() => {
this.getDevicePayPackage();
}, 1500);
} else if (res.data.code === 0 && res.data.data === null) {
this.isShowNoData = true;
} else {
if(res.data.data === null) {
this.isShowNoData = false;
} else {
let data = res.data.data.packagesList;
// 处理获取套餐的逻辑
// 筛选 基础套餐,producModelId 1 是基础套餐;2 是加油包
this.basePackageList = data.filter(item => {
return item.producModelId === 1
});
this.refuelPackageList = data.filter(item => {
return item.producModelId === 2
});
}
this.$toast.success({
message: "加载完成",
duration: 1500
});
}
})
.catch(error => {
this.$dialog.confirm({
title: "获取套餐数据失败",
message: error.message,
showCancelButton: false,
});
})
.finally(() => {
setTimeout(() => {
this.$toast.clear();
}, 1500);
});
},
// 购买加油包
onBuyRefuel(data){
console.log("加油包", data);
this.price = data.packagesPrice;
this.wxPay(data,1);
},
// 购买基础套餐
onBuyBase(data) {
console.log("基础包", data);
this.price = data.packagesPrice;
let payTypeToPackAgeId = data.payTypeList;
if (this.payType === '2') {
// 全额
this.payProductId = payTypeToPackAgeId.filter(item => {
return item.payType === '2'
})[0].productId;
this.packageIssue = 0;
console.log("this.payProductId", this.payProductId);
this.aliPay(data);
} else if (this.payType === '3') {
// 分期
this.payProductId = payTypeToPackAgeId.filter(item => {
return item.payType === '3'
})[0].productId;
this.packageIssue = 12;
this.payType = '2';
console.log("this.payProductId2", this.payProductId);
this.aliPay(data);
} else {
// 微信
let openId = this.$store.getters.openId;
this.payProductId = payTypeToPackAgeId.filter(item => {
return item.payType === '1'
})[0].productId;
this.packageIssue = 0;
console.log("this.payProductId3", this.payProductId);
if(openId === null || openId === 'null') {
this.$dialog.confirm({
message: '获取OpenId失败,请您重新进入',
showCancelButton: false,
})
} else {
this.wxPay(data);
}
}
},
// 支付类型切换
onRaidoChange(value) {
console.log("选择的支付类型是", value);
this.payType = value;
},
// 微信支付
wxPay(data, packageType) {
let that = this;
const orderData = data;
let reqBody = {
openId: this.$store.getters.openId, //openId
imei: that.$route.query.imei, //imei
productId: orderData.packagesId, //套餐id
packageName:
orderData.productModel + "," + orderData.packagesName, //套餐名字
packagePayType: '1', //支付类型, 默认微信
packageIssue: orderData.packageIssue, //分期
packagePrice: orderData.packagesPrice * 100
};
// 1.获取微信预下单Id
APICore.payLiveBaseDevice(reqBody)
.then(res => {
if (res.data.code === 104 || res.data.code === 106) {
this.getAuth();
setTimeout(() => {
this.wxPay(orderData);
}, 1000);
}
let wxData = res.data.data;
let outTradeNo = wxData.out_trade_no;
that.outTradeNo = wxData.out_trade_no;
//this.checkWxPayResult(outTradeNo);
//this.closeTime();
// 调起微信支付收银台
wx.chooseWXPay({
timestamp: wxData.timeStamp, // 支付签名时间戳,注意微信 jssdk 中的所有使用 timestamp 字段均为小写。但最新版的支付后台生成签名使用的 timeStamp 字段名需大写其中的 S 字符
nonceStr: wxData.nonceStr, // 支付签名随机串,不长于 32 位
package: wxData.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
signType: wxData.signType, // 微信支付V3的传入 RSA ,微信支付V2的传入格式与V2统一下单的签名格式保持一致
paySign: wxData.paySign, // 支付签名
success: function(res) {
console.log("微信支付成功::", res);
if(packageType === 1) {
// 加油包不用跳转,直接提示支付成功
that.$toast.success({
message: '支付成功'
});
} else {
// 套餐订购,跳转查询页面
that.$router.replace({
name: "payResult",
query: {
outTradeNo: that.outTradeNo,
price: that.price,
rechargeUrl: data.rechargeUrl,
iccid: that.$route.query.iccid,
isAdmin: that.$route.query.isAdmin || false,
serialNo: that.$route.query.imei,
issue: that.packageIssue
}
});
}
},
fail: err => {
console.log("支付出错了::", err);
that.$dialog.confirm({
title: "支付失败",
message: "出错了,请您联系管理员"
});
},
cancel: function(err) {
// 用户取消支付
that.$dialog.confirm({
message: "您取消了支付"
});
}
});
})
.catch(error => {
console.log("error", error);
})
},
// 跳转到支付宝花呗外部链接
aliPay(data) {
console.log("选择了支付宝::", data);
this.$toast.loading({
message: "加载中"
});
let orderData = data;
let that = this;
let reqBody = {
openId: this.$store.getters.openId, //openId
imei: that.$route.query.imei, //imei
productId: this.payProductId, //套餐id
packageName: /* data.productModel + ',' + */data.packagesName, //套餐名字
packagePayType: Number(this.payType), //支付类型
packageIssue: this.packageIssue, //分期
packagePrice: process.env.NODE_ENV === "production" ? data.packagesPrice * 100 : 1 //总金额单位为分,测试环境写死
};
this.$toast.clear();
APICore.payLiveBaseDevice(reqBody)
.then(res => {
if (res.data.code === 104 || res.data.code === 106) {
this.getAuth();
setTimeout(() => {
this.aliPay(orderData);
}, 1000);
}
let alipayData = res.data.data.xmlStrMap;
that.outTradeNo = alipayData.outTradeNo;
let alipayForm = decodeURI(alipayData.payXmlStr);
that.$store.commit("isFromWx", true);
let alipayUserId = process.env.NODE_ENV === "production" ? 42 : 18;
this.$router.replace({
name: "payResult",
query: {
rechargeUrl:
data.rechargeUrl ||
`https://id.ssjlai.com/frontend/#/alipay`,
outTradeNo: that.outTradeNo,
price: that.price,
alipayForm: alipayForm,
iccid: that.$route.query.iccid,
isAdmin: that.$route.query.isAdmin || false,
serialNo: that.$route.query.imei,
alipayUserId: alipayUserId,
productId: this.payProductId
}
});
})
.catch(error => {
console.log("error", error);
this.$dialog.confirm({
message: `${error.message}`,
showCancelButton: false
})
})
.finally(() => {
this.$toast.clear();
});
},
},
created() {
/* this.getAuth(); */
this.getWxAutograph();
// 套餐列表
this.getDevicePayPackage();
},
}
</script>
<style lang="scss">
.package-buy-container {
.van-tabs {
min-height: 100vh;
background: #fafafa;
&.blue {
background: #1890ff !important;
}
.van-tabs__wrap {
height: 50px;
width: 100%;
.van-tabs__nav {
.van-tab {
@include center();
padding: 0;
span {
color: #333333;
font-size: 16px;
padding: 4px;
}
&.van-tab--active {
span {
color: #1890ff;
font-weight: 500;
font-size: 16px;
}
}
}
}
}
}
}
</style>
<style scoped lang="scss">
.package-buy-container {
height: 100vh;
overflow: hidden;
.package-container {
height: calc(100vh - 88px);
background: #fafafa;
.refuel-package {
height: calc(100vh - 88px);
padding: 10px 20px;
overflow: scroll;
.refuel-item {
padding: 10px;
margin-bottom: 20px;
background-color: #fff;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
border-left: 3px solid #1890ff;
box-shadow: rgba(60, 64, 67, 0.3) 0px 1px 2px 0px,
rgba(60, 64, 67, 0.15) 0px 2px 6px 2px;
p,
span {
font-size: 16px;
}
.title {
text-align: left;
padding-top: 10px;
font-weight: 500;
}
.tips {
margin-top: 10px;
p {
font-size: 14px;
}
}
.bottom {
padding-top: 20px;
display: flex;
justify-content: space-between;
align-items: center;
span {
font-size: 20px;
color: #fca842;
font-weight: bold;
.price-span {
margin-left: 5px;
font-size: 14px;
}
}
.btn-button {
height: 35px;
width: 100px;
@include center();
background-color: #fca842;
border-radius: 17px;
p {
font-size: 14px;
color: #fff;
}
}
}
}
}
.base-package {
height: calc(100vh - 88px);
position: relative;

.base-item {
margin: 10px;
z-index: 999;
box-shadow: rgba(14, 30, 37, 0.12) 0 3px 5px 0,
rgba(14, 30, 37, 0.32) 0 2px 16px 0;
padding: 15px 10px;
background-color: #fff;
/* border-radius: 5px; */
.title {
display: flex;
justify-content: flex-start;
p {
font-size: 16px;
font-weight: bold;
}
}
.details {
display: flex;
justify-content: flex-start;
align-items: center;
p {
height: 40px;
@include center();
font-size: 14px;
padding: 5px 0 5px 10px;
}
.total {
font-size: 16px;
padding: 0;
}
.orange {
color: orange;
}
.large {
font-size: 26px;
margin: 0 2px;
}
.price {
font-size: 16px;
}
/* .buy-btn {
height: 30px;
width: 100px;
display: flex;
justify-content: center;
align-items: center;
background: orange;
border-radius: 45px;
p {
font-size: 16px;
padding: 0;
color: red;
}
} */
}
.remark {
display: flex;
justify-content: flex-start;
p {
font-size: 14px;
padding: 5px 10px;
/* font-weight: bold; */
}
}
.package-buy {
@include center();
padding: 5px 8px;
.buy-btn {
height: 40px;
width: 200px;
padding: 0 5px;
display: flex;
justify-content: center;
align-items: center;
background: orange;
border-radius: 20px;
p {
font-size: 16px;
padding: 0;
color: white;
}
}
}
.radios-con {
/* padding: 20px 10px; */
/* @include center(); */
/* align-items: center; */
padding: 10px 0 10px 10px;
font-size: 14px;
/* box-shadow: rgba(14, 30, 37, 0.12) 0 3px 5px 0,
rgba(14, 30, 37, 0.32) 0 2px 16px 0; */
img {
height: 20px;
width: 20px;
margin: 2px;
}
.pay-type {
text-align: left;
p {
font-size: 14px;
padding: 0 0 10px 0;
}
}

.radio-con {
@include center();
}
.van-cell-text {
display: flex;
justify-content: flex-start;
align-items: center;
span {
font-size: 14px;
padding: 0 5px;
}
}
}
}
.content {
font-size: 14px;
}
}
.data-null {
height: calc(100vh - 88px);
@include center();
flex-direction: column;
span {
font-size: 14px;
}
}
}
}
</style>

正在加载...
取消
保存