feat: 更新

This commit is contained in:
dengtongyu committed 2023-04-19 18:03:28 +08:00
1 parent 835a93a6cd
commit 6501e61ffa
10 files changed
+319 -302

No files matched your search

+1
View File
@@ -13,6 +13,7 @@ declare module '@vue/runtime-core' {
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
VanButton: typeof import('vant/es')['Button']
VanDialog: typeof import('vant/es')['Dialog']
VanSearch: typeof import('vant/es')['Search']
}
}
+5 -1
View File
@@ -1,8 +1,12 @@
import { Button, Search } from "vant";
import { Button, Search, Dialog } from "vant";
import "vant/es/notify/style/index";
import "vant/es/toast/style/index";
import "vant/es/dialog/style/index";
const install = function (app: any) {
app.use(Button);
app.use(Search);
app.use(Dialog);
};
export {
+217 -17
View File
@@ -1,5 +1,6 @@
<script setup lang="ts" name="Home">
import { ref, onMounted, computed } from "vue";
import { ref, computed } from "vue";
import { showToast } from "vant";
import pinia from "../store/pinia";
import { pay } from "../store";
import { getQueryString } from "@/lib/util";
@@ -8,40 +9,128 @@ const payStore = pay(pinia);
const locateObj = getQueryString();
const { openId, data, channel } = locateObj;
payStore.openId = openId || "";
payStore.dataId = data || "";
payStore.channel = channel || "";
const searchKeyword = ref<string>("");
payStore.getChargeprod();
payStore.initParams({
openId,
data,
channel
});
const prizeList = computed(() => {
return payStore.prizeList;
});
onMounted(() => {
// init();
const selectItemIndex = computed(() => {
return payStore.selectItemIndex;
});
const selectItem = computed(() => {
return payStore.selectItem;
});
const selectHandler = (index: number) => {
payStore.setSelectIndex(index);
};
const regUser = /^\d{7}$/;
const regPhone = /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/;
const searchHandler = () => {
const keyword = searchKeyword.value;
// console.log(keyword, regUser.test(keyword), regPhone.test(keyword));
if (regUser.test(keyword) || regPhone.test(keyword)) {
payStore.getChargeUser(keyword);
}
};
const logo = new URL(
"@/assets/images/logo.png",
import.meta.url
).href;
const userInfo = computed(() => {
return payStore.receiveUserInfo;
});
const showUserInfo = computed(() => {
if (userInfo.value && userInfo.value.uid) return true;
return false;
});
const userInfoImage = computed(() => {
if (userInfo.value && userInfo.value.avatar) return userInfo.value.avatar;
return logo;
});
const userInfoNick = computed(() => {
if (userInfo.value && userInfo.value.nick) return userInfo.value.nick;
return "";
});
const userInfoErbanNo = computed(() => {
if (userInfo.value && userInfo.value.erbanNo) return userInfo.value.erbanNo;
return "";
});
const showDialog = ref(false);
const payHandler = () => {
const isPhone = regPhone.test(searchKeyword.value);
const isUserId = regUser.test(searchKeyword.value);
if(!isPhone && !isUserId) {
showToast("请输入正确的手机号或者用户ID");
return;
}
if (!showUserInfo.value) {
showToast("请搜索并确定需要充值的用户");
return;
}
showDialog.value = true;
};
const confirmHandler = () => {
const data:any = {};
const isPhone = regPhone.test(searchKeyword.value);
const isUserId = regUser.test(searchKeyword.value);
if(isPhone) data.phone = searchKeyword.value;
if(isUserId) data.erban_no = searchKeyword.value;
payStore.payRequest(data);
};
</script>
<template>
<div class="wechat-home">
<div class="wechat-home-search">
<div class="wechat-home-search wechat-middle">
<van-search
v-model="searchKeyword"
class="wechat-home-search-input"
placeholder="请输入手机号或者用户ID"
shape="round"
@input.stop="searchHandler"
/>
</div>
<div v-if="showUserInfo" class="wechat-home-user wechat-middle">
<div class="wechat-home-user-image"><img :src="userInfoImage"></div>
<div class="wechat-home-user-info">
<p class="wechat-home-user-info-line1">昵称:{{ userInfoNick }}</p>
<p class="wechat-home-user-info-line2">用户ID:{{ userInfoErbanNo }}</p>
</div>
</div>
<div class="wechat-home-prize">
<h3>选择充值金额</h3>
<h3 class="wechat-middle">选择充值金额</h3>
<div class="wechat-home-prize-list">
<div
v-for="item in prizeList"
v-for="(item, index) in prizeList"
:key="`prize-${item.channel}`"
class="prize-item"
:class="index === selectItemIndex ? 'prize-item-active' : ''"
@click="selectHandler(index)"
>
<p class="prize-item-line1">
<i></i>
@@ -52,16 +141,16 @@ onMounted(() => {
</div>
</div>
<div class="wechat-home-text1">
<div class="wechat-home-text1 wechat-middle">
<p>本平台禁止使用不合法信用卡和储蓄卡充值,一经发现封禁账号及设备,情节严重将报警处理!</p>
</div>
<div class="wechat-home-text2">
<div class="wechat-home-text2 wechat-middle">
<p>
本平台严厉打击刷单类诈骗行为,一旦发现我平台将追究其法律责任,同时保留追究损失的权利;我们呼吁用户如有收到以兼职赚钱为名义诱骗刷单的行为,请联系客服举报!情节严重者我们将交于警方处理,如执意配合刷单行为造成的损失我们平台概不负责!
</p>
</div>
<div class="wechat-home-btn">
<div class="wechat-home-btn wechat-middle">
<van-button
class="wechat-home-btn-sumb"
type="default"
@@ -69,17 +158,42 @@ onMounted(() => {
block
size="large"
color="rgba(255, 240, 51, 1)"
@click="payHandler"
>立即充值</van-button>
</div>
<van-dialog
v-model:show="showDialog"
title="充值提示"
show-cancel-button
theme="round-button"
confirm-button-color="#FFF033"
cancel-button-color="#F5F6FA"
class-name="wechat-dialog"
@confirm="confirmHandler"
>
<div class="wechat-dialog-content">
<div class="wechat-dialog-image">
<img :src="userInfoImage">
</div>
<div class="wechat-dialog-info">
向<span>{{ userInfoNick }}</span>(用户ID;{{ userInfoErbanNo }})充值{{ selectItem ? selectItem.money : "" }}元?
</div>
</div>
</van-dialog>
</div>
</template>
<style lang="less" scoped>
.wechat-middle {
padding: 0 15px;
}
.wechat-home {
height: 100%;
width: 100%;
overflow: auto;
padding: 0 15px;
// padding: 0 15px;
box-sizing: border-box;
&-search {
@@ -94,8 +208,46 @@ onMounted(() => {
}
}
&-user {
display: flex;
height: 78px;
background: #FAFAFA;
border-radius: 10px;
margin-top: 16px;
padding: 0 16px;
align-items: center;
&-image {
width: 46px;
height: 46px;
border-radius: 50%;
overflow: hidden;
&>img {
height: 100%;
width: 100%;
}
}
&-info {
padding-left: 16px;
&-line1 {
color: #333;
font-weight: bold;
font-size: 16px;
}
&-line2 {
color: #666;
font-size: 14px;
}
}
}
&-prize {
margin-top: 20px;
margin-top: 16px;
width: 100%;
&>h3 {
font-size: 18px;
@@ -107,8 +259,9 @@ onMounted(() => {
&-list {
display: flex;
justify-content: space-between;
// justify-content: space-between;
flex-wrap: wrap;
padding-left: 10px;
}
}
@@ -129,8 +282,10 @@ onMounted(() => {
color: #EC424D;
line-height: 20px;
}
&-btn {
margin-top: 20px;
&-sumb {
color: #222222 !important;
}
@@ -146,7 +301,7 @@ onMounted(() => {
display: flex;
flex-direction: column;
justify-content: center;
// margin: 10px;
margin: 5px;
&-line1 {
display: flex;
@@ -196,4 +351,49 @@ onMounted(() => {
color: #FFAC39;
}
}
:deep(.wechat-dialog) {
&-content {
display: flex;
justify-content: center;
align-items: center;
padding: 20px 16px;
}
&-image {
width: 46px;
height: 46px;
border-radius: 50%;
overflow: hidden;
flex-shrink: 0;
&>img {
height: 100%;
width: 100%;
}
}
&-info {
font-size: 14px;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 400;
color: #666666;
line-height: 20px;
padding-left: 10px;
max-width: 200px;
&>span {
color: #FFAC39;
font-weight: bold;
}
}
.van-dialog__confirm {
color: #222 !important;
}
.van-dialog__cancel {
color: #626166 !important;
}
}
</style>
-56
View File
@@ -1,56 +0,0 @@
<script setup lang="ts" name="Login">
import { useRoute, useRouter } from "vue-router";
import pinia from "../store/pinia";
import { baseInfo } from "../store";
const route = useRoute();
const router = useRouter();
const baseInfoStore = baseInfo(pinia);
const rediret: any = route.query.rediret;
baseInfoStore
.loginUserInfo()
.then((res: any) => {
const { errcode, errmsg } = res;
if (errcode === 401) return;
if (errcode === 0) {
router.replace(rediret);
}
else if (errcode === 400) {
router.replace({
path: "/noaccess",
query: {
from: rediret,
text: errmsg || "未能获取您的用户信息"
}
});
}
else {
router.replace({
path: "/500",
query: {
from: rediret,
text: errmsg || "服务器发生未知错误!"
}
});
}
})
.catch(() => {
router.replace({
path: "/failed",
query: {
from: rediret,
text: "出现意外错误!"
}
});
});
</script>
<template>
<div class="xtbg-loading"></div>
</template>
<style lang="less" scoped>
</style>
-75
View File
@@ -1,75 +0,0 @@
<script setup lang="ts" name="appH5">
</script>
<template>
<div class="h5">
<div class="h5-main">
<div class="h5-main-mask">
<div class="h5-main-mask-btnbox">
<van-button
class="h5-main-mask-btnbox-download"
round
color="#222222"
size="large"
block
>立即下载</van-button>
</div>
<div class="h5-main-mask-text">
<p>粤ICP备1000000000号-1 粤公网安备00000000000000</p>
</div>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.h5 {
width: 100%;
height: 100%;
&-main {
width: 100%;
height: 100%;
background-image: url(../assets/images/h5_bg.png);
background-size: cover;
background-repeat: no-repeat;
padding: 20px;
box-sizing: border-box;
&-mask {
width: 100%;
height: 222px;
background-image: url(../assets/images/h5_mask.png);
background-size: cover;
position: fixed;
left: 0;
bottom: 0;
&-btnbox {
width: 250px;
height: 55px;
margin-top: 80px;
margin-left: auto;
margin-right: auto;
&-download {
height: 100%;
}
}
&-text {
font-size: 12px;
font-family: PingFang SC;
font-weight: 500;
color: #666666;
line-height: 18px;
text-align: center;
margin-top: 36px;
}
}
}
}
</style>
-104
View File
@@ -1,104 +0,0 @@
<script setup lang="ts" name="appWeb">
</script>
<template>
<div class="web">
<div class="web-main">
<div class="web-main-middle">
<div class="web-main-middle-btnbox">
<a href="###" class="web-main-middle-btnbox-andriod"></a>
<a href="###" class="web-main-middle-btnbox-ios"></a>
</div>
</div>
</div>
<div class="web-footer">
<div class="web-footer-text">
<p>粤ICP备1000000000号-1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;粤公网安备00000000000000</p>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.web {
width: 100%;
height: 100%;
min-width: 1280px;
min-height: 940px;
&-main {
width: 100%;
height: 100%;
background-image: url(../assets/images/web_bg.png);
background-position: top center;
// background-size: 100%;
background-repeat: no-repeat;
padding: 20px;
box-sizing: border-box;
&-middle {
width: 1280px;
height: 100%;
margin: 0 auto;
overflow: hidden;
&-btnbox {
margin-top: 600px;
margin-left: 90px;
display: flex;
&>a {
display: block;
text-decoration: none;
width: 247px;
height: 72px;
background-repeat: no-repeat;
background-size: cover;
outline: none;
margin-right: 30px;
}
&-andriod {
background-image: url(../assets/images/download_andriod.png);
}
&-ios {
background-image: url(../assets/images/download_ios.png);
}
}
}
}
&-footer {
width: 100%;
height: 100px;
background-color: #222222;
position: fixed;
left: 0;
bottom: 0;
&-text {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
font-size: 16px;
font-family: PingFang SC;
font-weight: 500;
color: rgba(255, 255, 255, 0.8);
line-height: 36px;
text-align: center;
}
}
}
@media only screen and (min-height: 1000px) {
.web-footer {
height: calc(100vh - 940px);
}
}
</style>
-1
View File
@@ -1,7 +1,6 @@
const routes = [
{ path: "/", name: "root", redirect: "/home" },
{ path: "/home", name: "home", meta: { power: true }, component: () => import("../pages/Home.vue") },
// { path: "/loginfo", name: "loginfo", component: () => import("../pages/Login.vue") },
{ path: "/nonetwork:text?", name: "nonetwork", props: true, component: () => import("../pages/error/NoNetwork.vue") },
{ path: "/noaccess/:text?", name: "noaccess", props: true, component: () => import("../pages/error/NoAccess.vue") },
{ path: "/empty/:text?", name: "empty", props: true, component: () => import("../pages/error/NoData.vue") },
-30
View File
@@ -1,30 +0,0 @@
import { defineStore } from "pinia";
import { ref, computed } from "vue";
import { getUserInfo } from "../api";
const baseInfo = defineStore("baseInfo", () => {
const user = ref<any>({});
const loginUserInfo = () => {
return new Promise((resolve, reject) => {
getUserInfo({})
.then((res: any) => {
const { errcode, data } = res;
if (errcode === 0) {
const info = data.data;
user.value = info;
}
resolve(res);
})
.catch((err: any) => {
reject(err);
});
});
};
const userInfo = computed(() => {
return user;
});
return { loginUserInfo, userInfo };
});
export default baseInfo;
+88 -10
View File
@@ -1,7 +1,8 @@
import { ref, computed } from "vue";
import { defineStore } from "pinia";
import { showFailToast } from "vant";
import { chargeprodList, chargeUser } from "@/api/index";
import { showNotify, showToast } from "vant";
import { chargeprodList, chargeUser, submitPay } from "@/api/index";
import { onBridgeReady } from "@/wx/index";
const pay = defineStore("pay", () => {
@@ -9,6 +10,12 @@ const pay = defineStore("pay", () => {
const dataId = ref<any>("");
const channel = ref<any>("");
const initParams = (data:any) => {
openId.value = data.openId || "";
dataId.value = data.dataId || "";
channel.value = data.channel || "";
};
const payLsit = ref<Array<any>>([]);
const receiveUser = ref<any>({});
@@ -28,19 +35,36 @@ const pay = defineStore("pay", () => {
});
});
};
const selectItemIndex = ref(0);
const selectItem = computed(() => {
if (payLsit.value.length > 0) {
return payLsit.value[selectItemIndex.value];
}
else {
return null;
}
});
const setSelectIndex = (value: number) => {
selectItemIndex.value = value;
};
const getChargeUser = (erbanNo: string | number) => {
return new Promise((resolve, reject) => {
chargeUser({erbanNo: erbanNo})
chargeUser({ erbanNo: erbanNo })
.then((res: any) => {
const { code, data, message } = res;
if (code === 200) {
receiveUser.value = data;
}else if(code === 1404) {
showFailToast(message || "您输入的账号不存在");
} else if (code === 1404) {
showNotify({ type: "warning", message: "您输入的账号不存在" });
}
else{
showFailToast(message);
else {
showNotify({ type: "warning", message: message });
}
resolve(res);
})
@@ -50,12 +74,66 @@ const pay = defineStore("pay", () => {
});
};
const wxConfig = ref<any>({});
const payRequest = (data:any) => {
const params = Object.assign({
chargeProdId: selectItem.value.chargeProdId,
openId: openId.value,
app: "toupai",
data: dataId.value,
channel: channel.value
}, data);
return new Promise((resolve, reject) => {
submitPay(params)
.then((res: any) => {
const { code, data, message } = res;
if (code === 200) {
wxConfig.value = {
timeStamp: data.timestamp, //时间戳
nonceStr: data.nonce_str,
package: data.prepay_id,
paySign: data.sign,
appid: data.appid,
signType: data.sign_type
};
onBridgeReady(wxConfig.value);
resolve(res);
}
else if (code === 10108){
showToast("充值金额过大,需要进行身份认证");
} else if (code === 4002) {
showToast("该手机号未注册账号");
} else if (code === 1404) {
showToast("用户ID不存在");
} else if (code === 10960) {
showToast("功能暂未开放");
} else if (code === 1412) {
showToast("请输入用户ID进行充值");
} else if (code === 4005) {
showToast("订单超时,请重新进入页面操作!");
} else if (code === 7064) {
showToast("你的账号已被封禁,无法充值!");
} else {
showToast(message);
}
})
.catch((err: any) => {
reject(err);
});
});
};
const prizeList = computed(() => {
return payLsit.value;
});
return { openId, dataId, channel, getChargeprod, getChargeUser, prizeList };
const receiveUserInfo = computed(() => {
return receiveUser.value;
});
return { openId, dataId, channel, getChargeprod, getChargeUser, prizeList, receiveUserInfo, selectItem, selectItemIndex, setSelectIndex, payRequest, initParams };
});
export default pay;
+8 -8
View File
@@ -1,6 +1,4 @@
import { useRouter } from "vue-router";
const router = useRouter();
import { showDialog } from "vant";
const onBridgeReady = function (data: any) {
const { appid, timeStamp, nonceStr, signType, paySign } = data;
@@ -9,7 +7,7 @@ const onBridgeReady = function (data: any) {
"appId": appid,
"timeStamp": timeStamp,
"nonceStr": nonceStr,
"package": data,
"package": data.package,
"signType": signType,
"paySign": paySign
},
@@ -17,12 +15,14 @@ const onBridgeReady = function (data: any) {
if (res.err_msg === "get_brand_wcpay_request:ok") {// 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
window.location.reload();
} else if (res.err_msg === "get_brand_wcpay_request:fail") {
router.replace({
path: "/payfailed"
showDialog({
title: "充值提示",
message: "充值失败!请稍后重试!"
});
} else {
router.replace({
path: "/payfailed"
showDialog({
title: "充值提示",
message: "充值失败!"
});
}
}