first commit

This commit is contained in:
PC-202306242200\Administrator
2026-03-31 10:53:43 +08:00
commit f529129c93
770 changed files with 86065 additions and 0 deletions

View File

@@ -0,0 +1,213 @@
<template>
<view class="p30 piles">
<z-paging ref="paging" v-model="dataList" use-page-scroll @query="queryList">
<view class="piles_card">
<view class="piles_card_title">充电桩汇总</view>
<view class="piles_card_view">
<view>
<text>{{ count.installCount || 0 }}</text>
<text>已安装</text>
</view>
<view>
<text>{{ count.installNotCount || 0 }}</text>
<text>未安装数量</text>
</view>
<view>
<text>0</text>
<text>团队</text>
</view>
</view>
</view>
<up-subsection :list="list" keyName="name" :current="current" @change="upChange"></up-subsection>
<view class="order_view" v-for="i in dataList" :key="i">
<view class="piles_list" v-if="current == 0">
<view class="piles_list_title">安装电站{{ i.stationName || '-' }}</view>
<view class="piles_list_view">
<view>设备ID</view>
<view>{{ i.id }}</view>
</view>
<view class="piles_list_view">
<view>设备功率</view>
<view>{{ i.deviceType }}KW</view>
</view>
<view class="piles_list_view" v-if="i.purposeType">
<view>设备类型</view>
<view>{{ i.purposeType == 1 ? '商用运维版' : i.purposeType == 2 ? '商用合作版' : i.purposeType == 3 ? '家用专业版' : '' }}</view>
</view>
<view class="piles_list_view">地址{{ i.stationAddress || '-' }}</view>
<!-- <view class="piles_list_view">
<view>电费费用</view>
<view>
<text>1.00</text>
/
</view>
</view>
<view class="piles_list_view">
<view>昨日收益</view>
<view>
<text>100.00 </text>
</view>
</view> -->
<view class="piles_list_view">
<view>下单时间</view>
<view>{{ timeFormat(new Date(i.createTime).getTime(), 'yyyy-mm-dd hh:MM') }}</view>
</view>
</view>
<view class="piles_list" v-if="current == 1">
<view class="piles_list_view">
<view>设备ID</view>
<view>{{ i.id }}</view>
</view>
<view class="piles_list_view">
<view>设备功率</view>
<view>{{ i.deviceType }}KW</view>
</view>
<view class="piles_list_view" v-if="i.purposeType">
<view>设备类型</view>
<view>{{ i.purposeType == 1 ? '商用运维版' : i.purposeType == 2 ? '商用合作版' : i.purposeType == 3 ? '家用专业版' : '' }}</view>
</view>
<view class="piles_list_view">
<view>下单时间</view>
<view>{{ timeFormat(new Date(i.createTime).getTime(), 'yyyy-mm-dd hh:MM') }}</view>
</view>
</view>
</view>
</z-paging>
</view>
</template>
<script setup>
// import { getDeviceInfo, getDeviceCount } from '@/api/api.js';
import { reactive, ref } from 'vue';
import { onPullDownRefresh, onPageScroll, onReachBottom, onLoad } from '@dcloudio/uni-app';
import { timeFormat } from '@/uni_modules/uview-plus';
const paging = ref(null);
let dataList = ref([]);
let dataFrom = reactive({
deviceStatus: 1
});
let count = ref({});
onLoad(async () => {
count.value = await getDeviceCount();
});
let isPagingRefNotFound = () => {
return !paging.value;
};
onPullDownRefresh(() => {
if (isPagingRefNotFound()) return;
paging.value.reload().catch(() => {});
});
onPageScroll((e) => {
if (isPagingRefNotFound()) return;
paging.value.updatePageScrollTop(e.scrollTop);
e.scrollTop < 10 && paging.value.doChatRecordLoadMore();
});
onReachBottom(() => {
if (isPagingRefNotFound()) return;
paging.value.pageReachBottom();
});
const queryList = (pageNo, pageSize) => {
const params = {
current: pageNo,
pageSize: pageSize,
...dataFrom
};
getDeviceInfo(params)
.then((res) => {
paging.value.complete(res.records);
})
.catch((res) => {
paging.value.complete(false);
});
};
const list = ref([
{
name: '已安装',
id: 1
},
{
name: '待安装',
id: 0
}
]);
const current = ref(0);
const upChange = (e) => {
current.value = e;
dataFrom.deviceStatus = list.value[e].id;
paging.value.reload();
};
</script>
<style scoped lang="scss">
.piles {
&_card {
width: 690rpx;
height: 192rpx;
background: linear-gradient(179deg, #4874e5 0%, #3864d6 100%);
border-radius: 8rpx 8rpx 0rpx 0rpx;
padding: 30rpx;
&_title {
font-weight: bold;
font-size: 28rpx;
color: #ffffff;
margin-bottom: 20rpx;
}
&_view {
padding: 0 150rpx;
flex-direction: column;
@include flex($space: space-between);
view {
@include flex($direction: column, $space: space-between);
text:nth-child(1) {
font-weight: bold;
font-size: 32rpx;
color: #ffffff;
margin-bottom: 15rpx;
}
text:nth-child(2) {
font-size: 26rpx;
color: #ffffff;
}
}
}
}
&_list {
padding: 25rpx;
width: 690rpx;
background: #ffffff;
border-radius: 16rpx 16rpx 16rpx 16rpx;
margin-top: 30rpx;
&_title {
font-weight: bold;
font-size: 28rpx;
color: #232323;
}
&_view {
@include flex;
color: #555555;
font-size: 28rpx;
margin-top: 15rpx;
view:nth-child(2) {
font-weight: bold;
font-size: 28rpx;
color: #232323;
}
text {
color: #ff2727;
}
}
}
}
</style>

View File

@@ -0,0 +1,152 @@
<template>
<view class="login">
<view class="orderdetail_header p30">
<view :style="{ height: statusBarHeight }"></view>
<view style="height: 44px; display: flex; align-items: center">
<up-icon name="arrow-left" bold color="#000" @click="back"></up-icon>
</view>
</view>
<image class="login_bei" src="/static/logoB.png"></image>
<statusBar />
<view class="login_logo">
<image class="login_logo_img" src="/static/logo.png"></image>
<view class="login_logo_tit">欢迎来到投资者平台</view>
</view>
<view style="margin-top: 150rpx">
<view style="margin-bottom: 30rpx">
<up-input fontSize="30rpx" v-model="dataFrom.userName" placeholder="请输入您的用户名" border="bottom" clearable></up-input>
</view>
<view style="margin-bottom: 30rpx">
<up-input fontSize="30rpx" v-model="dataFrom.passwd" type="password" placeholder="请输入您的密码" border="bottom" clearable></up-input>
</view>
<view style="margin-bottom: 30rpx">
<up-input fontSize="30rpx" v-model="dataFrom.confirmPasswd" type="password" placeholder="请再次输入您的密码" border="bottom" clearable></up-input>
</view>
<view style="margin-bottom: 30rpx">
<up-input fontSize="30rpx" v-model="dataFrom.phone" placeholder="请输入您的手机号" border="bottom" clearable></up-input>
</view>
<view style="margin-bottom: 30rpx; display: flex; align-items: center">
<up-input fontSize="30rpx" v-model="dataFrom.smsCode" placeholder="请输入验证码" border="bottom" clearable></up-input>
<up-code ref="uCode" @change="codeChange2" keep-running start-text="点我获取验证码"></up-code>
<text @click="getCode2" :text="tips" style="font-size: 28rpx; color: rgba(111, 162, 86, 1)">{{ tips }}</text>
</view>
</view>
<view style="display: flex; justify-content: center; margin-top: 80rpx">
<view class="login_btn" @click="submit">确认</view>
</view>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { findPassword, smsCode } from '@/api/api.js';
const statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px';
let tips = ref('');
let uCode = ref(null);
let dataFrom = reactive({
userName: '',
passwd: '',
phone: '',
smsCode: '',
confirmPasswd:""
});
let toLogin = () => {
uni.navigateBack();
};
let codeChange2 = (text) => {
tips.value = text;
};
let getCode2 = () => {
if (!dataFrom.phone) return uni.showToast({ title: '请输入手机号', icon: 'none' });
if (uCode.value.canGetCode) {
// 模拟向后端请求验证码
uni.showLoading({
title: '正在获取验证码'
});
smsCode({
phone: dataFrom.phone
}).then((res) => {
uni.hideLoading();
uni.$u.toast('验证码已发送');
uCode.value.start();
});
} else {
uni.$u.toast('倒计时结束后再发送');
}
};
let submit = async () => {
if (!dataFrom.userName) return uni.showToast({ title: '请输入用户名', icon: 'none' });
if (!dataFrom.phone) return uni.showToast({ title: '请输入手机号', icon: 'none' });
if (dataFrom.phone.length != 11) return uni.showToast({ title: '请输入正确的手机号', icon: 'none' });
if (!dataFrom.smsCode) return uni.showToast({ title: '请输入验证码', icon: 'none' });
if (!dataFrom.passwd) return uni.showToast({ title: '请输入密码', icon: 'none' });
if (!dataFrom.confirmPasswd) return uni.showToast({ title: '请再次输入密码', icon: 'none' });
if (dataFrom.passwd != dataFrom.confirmPasswd) return uni.showToast({ title: '两次密码输入不一致', icon: 'none' });
let _res = await findPassword(dataFrom);
uni.showToast({ title: '修改成功', icon: 'none' });
setTimeout(() => {
uni.navigateBack();
}, 200);
};
let back = () => {
uni.navigateBack();
};
</script>
<style scoped lang="scss">
.login {
padding: 0 60rpx;
&_bei {
position: fixed;
right: -120rpx;
top: -206rpx;
width: 728rpx;
height: 728rpx;
}
&_logo {
margin-top: 150rpx;
&_img {
width: 280rpx;
height: 200rpx;
// background: #e6e6e6;
// box-shadow: 0rpx 0rpx 110rpx 2rpx rgba(115, 192, 76, 0.19);
border-radius: 28rpx 28rpx 28rpx 28rpx;
margin-bottom: 20rpx;
}
&_tit {
font-weight: bold;
font-size: 44rpx;
color: #232323;
}
}
&_btn {
width: 474rpx;
height: 78rpx;
background: rgba(111, 162, 86, 1);
border-radius: 54rpx 54rpx 54rpx 54rpx;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 30rpx;
color: #ffffff;
}
}
.orderdetail_header {
width: 750rpx;
position: fixed;
left: 0;
top: 0;
z-index: 99;
}
</style>

View File

@@ -0,0 +1,160 @@
<template>
<view class="login">
<view class="orderdetail_header p30">
<view :style="{ height: statusBarHeight }"></view>
<view style="height: 44px; display: flex; align-items: center">
<up-icon name="arrow-left" bold color="#000" @click="back"></up-icon>
</view>
</view>
<image class="login_bei" src="/static/logoB.png"></image>
<statusBar />
<view class="login_logo">
<image class="login_logo_img" src="/static/logo.png"></image>
<view class="login_logo_tit">欢迎来到投资者平台</view>
</view>
<view style="margin-top: 150rpx">
<view style="margin-bottom: 30rpx">
<up-input fontSize="30rpx" v-model="dataFrom.phone" placeholder="请输入您的手机号" border="bottom" clearable></up-input>
</view>
<view style="margin-bottom: 30rpx; display: flex; align-items: center">
<up-input fontSize="30rpx" v-model="dataFrom.smsCode" placeholder="请输入验证码" border="bottom" clearable></up-input>
<up-code ref="uCode" @change="codeChange2" keep-running start-text="点我获取验证码"></up-code>
<text @click="getCode2" :text="tips" style="font-size: 28rpx; color: rgba(111, 162, 86, 1)">{{ tips }}</text>
</view>
</view>
<view style="display: flex; justify-content: center; margin-top: 80rpx">
<view class="login_btn" @click="submit">确认</view>
</view>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { findUserName, smsCode } from '@/api/api.js';
const statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px';
let tips = ref('');
let uCode = ref(null);
let dataFrom = reactive({
phone: '',
smsCode: '',
});
let toLogin = () => {
uni.navigateBack();
};
let codeChange2 = (text) => {
tips.value = text;
};
let getCode2 = () => {
if (!dataFrom.phone) return uni.showToast({ title: '请输入手机号', icon: 'none' });
if (uCode.value.canGetCode) {
// 模拟向后端请求验证码
uni.showLoading({
title: '正在获取验证码'
});
smsCode({
phone: dataFrom.phone
}).then((res) => {
uni.hideLoading();
uni.$u.toast('验证码已发送');
uCode.value.start();
});
} else {
uni.$u.toast('倒计时结束后再发送');
}
};
let submit = async () => {
if (!dataFrom.phone) return uni.showToast({ title: '请输入手机号', icon: 'none' });
if (dataFrom.phone.length != 11) return uni.showToast({ title: '请输入正确的手机号', icon: 'none' });
if (!dataFrom.smsCode) return uni.showToast({ title: '请输入验证码', icon: 'none' });
let _res = await findUserName(dataFrom);
if (_res.userNames.length == 0) {
uni.showModal({
title: '提示',
content: '该手机号还未注册',
showCancel: false,
confirmText: "我知道了"
})
} else {
uni.showModal({
title: '已找回的用户名',
content: _res.userNames.join(','),
showCancel: false,
confirmText: "确认",
success: () => {
uni.setClipboardData({
data: _res.userNames.join(','), //要被复制的内容
success: () => { //复制成功的回调函数
uni.showToast({ //提示
title: '已复制用户名'
})
setTimeout(() => {
uni.navigateBack()
}, 1500)
}
});
}
})
}
};
let back = () => {
uni.navigateBack();
};
</script>
<style scoped lang="scss">
.login {
padding: 0 60rpx;
&_bei {
position: fixed;
right: -120rpx;
top: -206rpx;
width: 728rpx;
height: 728rpx;
}
&_logo {
margin-top: 150rpx;
&_img {
width: 280rpx;
height: 200rpx;
// background: #e6e6e6;
// box-shadow: 0rpx 0rpx 110rpx 2rpx rgba(115, 192, 76, 0.19);
border-radius: 28rpx 28rpx 28rpx 28rpx;
margin-bottom: 20rpx;
}
&_tit {
font-weight: bold;
font-size: 44rpx;
color: #232323;
}
}
&_btn {
width: 474rpx;
height: 78rpx;
background: rgba(111, 162, 86, 1);
border-radius: 54rpx 54rpx 54rpx 54rpx;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 30rpx;
color: #ffffff;
}
}
.orderdetail_header {
width: 750rpx;
position: fixed;
left: 0;
top: 0;
z-index: 99;
}
</style>

178
pageInvest/login/login.vue Normal file
View File

@@ -0,0 +1,178 @@
<template>
<view class="login">
<view class="orderdetail_header p30">
<view :style="{ height: statusBarHeight }"></view>
<view style="height: 44px; display: flex; align-items: center">
<up-icon name="arrow-left" bold color="#000" @click="back"></up-icon>
</view>
</view>
<image class="login_bei" src="/static/logoB.png"></image>
<statusBar />
<view class="login_logo">
<image class="login_logo_img" src="/static/logo.png"></image>
<view class="login_logo_tit">欢迎来到投资者平台</view>
</view>
<view style="margin-top: 150rpx">
<view style="margin-bottom: 50rpx">
<up-input fontSize="30rpx" v-model="dataFrom.userName" placeholder="请输入您的用户名" border="bottom" clearable></up-input>
</view>
<view>
<up-input fontSize="30rpx" v-model="dataFrom.passwd" type="password" placeholder="请输入您的密码" border="bottom" clearable></up-input>
</view>
<!-- <view style="display: flex; align-items: center">
<up-input fontSize="30rpx" v-model="dataFrom.captcha" placeholder="请输入验证码" border="bottom" clearable></up-input>
<image @click="getCaptcha" :src="captchaImg" style="width: 154rpx; height: 66rpx"></image>
</view> -->
</view>
<view style="font-size: 28rpx; color: #666; margin-top: 20rpx; display: flex; align-items: center; justify-content: space-between">
<view>
忘记账号
<text style="color: rgba(111, 162, 86, 1)" @click="getBackAccout">找回用户名</text>
</view>
<view>
<text style="color: rgba(111, 162, 86, 1)" @click="toGetBack">忘记密码</text>
</view>
</view>
<view style="display: flex; justify-content: center; margin-top: 80rpx">
<view class="login_btn" @click="login">登录</view>
</view>
<view style="display: flex; justify-content: center; margin-top: 40rpx; opacity: 0.5">
<view class="login_btn" @click="toRegister">还没有账号立即注册</view>
</view>
<!-- <view style="display: flex; justify-content: center; margin-top: 20rpx;font-size: 26rpx;">
登录即表示接受
<navigator url="/pages/agreement/agreement?id=9" style="color: rgba(111, 162, 86, 1);">隐私政策</navigator>
<navigator url="/pages/agreement/agreement?10" style="color: rgba(111, 162, 86, 1);">用户注册服务协议</navigator>
</view> -->
</view>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { loginByPassword, saveOpenIdByWxCode } from '@/api/api.js';
import { onLoad } from '@dcloudio/uni-app';
import store from '@/store/index.js';
const statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px';
let captchaImg = ref('');
let dataFrom = reactive({
userName: '',
passwd: '',
uuid: '',
captcha: ''
});
// onLoad(async () => {
// getCaptcha();
// });
let back = () => {
uni.navigateBack();
};
let getCaptcha = async () => {
let { captcha, uuid } = await captchaApi();
dataFrom.uuid = uuid;
captchaImg.value = 'data:image/png;base64,' + captcha;
};
let toRegister = () => {
uni.navigateTo({
url: '/pageInvest/login/register'
});
};
let getBackAccout = () => {
uni.navigateTo({
url: '/pageInvest/login/getBackAccout'
});
};
let toGetBack = () => {
uni.navigateTo({
url: '/pageInvest/login/getBack'
});
};
let login = async () => {
try {
const { code } = await uni.login();
let _res = await loginByPassword(dataFrom);
// uni.setStorageSync('tokenInvest', _res.token);
// uni.setStorageSync('userInvest', _res);
uni.setStorageSync('token', _res.token);
uni.setStorageSync('user', _res);
uni.setStorageSync('isInvest', true);
store.commit('setToken', _res.token);
// #ifdef MP-WEIXIN
let saveOpenId = await saveOpenIdByWxCode({ loginCode: code });
// #endif
// #ifdef MP-ALIPAY
let saveOpenId = await saveOpenIdByZfbCode({ loginCode: code });
// #endif
uni.showToast({ title: '登录成功', icon: 'none' });
setTimeout(() => {
uni.reLaunch({
url: '/pages/home/home'
});
// uni.navigateBack();
}, 200);
} catch (err) {
// getCaptcha();
}
};
</script>
<style scoped lang="scss">
.login {
padding: 0 60rpx;
&_bei {
position: fixed;
right: -120rpx;
top: -206rpx;
width: 728rpx;
height: 728rpx;
}
&_logo {
margin-top: 150rpx;
&_img {
width: 280rpx;
height: 200rpx;
// background: #e6e6e6;
// box-shadow: 0rpx 0rpx 110rpx 2rpx rgba(115, 192, 76, 0.19);
border-radius: 28rpx 28rpx 28rpx 28rpx;
margin-bottom: 20rpx;
}
&_tit {
font-weight: bold;
font-size: 44rpx;
color: #232323;
}
}
&_btn {
width: 474rpx;
height: 78rpx;
background: rgba(111, 162, 86, 1);
border-radius: 54rpx 54rpx 54rpx 54rpx;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 30rpx;
color: #ffffff;
}
}
.orderdetail_header {
width: 750rpx;
position: fixed;
left: 0;
top: 0;
z-index: 99;
}
</style>

View File

@@ -0,0 +1,192 @@
<template>
<view class="login">
<view class="orderdetail_header p30">
<view :style="{ height: statusBarHeight }"></view>
<view style="height: 44px; display: flex; align-items: center">
<up-icon name="arrow-left" bold color="#000" @click="back"></up-icon>
</view>
</view>
<image class="login_bei" src="/static/logoB.png"></image>
<view style="padding: 0 60rpx">
<statusBar />
<view class="login_logo">
<image class="login_logo_img" src="/static/logo.png"></image>
<view class="login_logo_tit">欢迎来到投资者平台</view>
</view>
<view style="margin-top: 100rpx">
<view>
<up-input fontSize="30rpx" v-model="dataFrom.userName" placeholder="请输入您的用户名" border="bottom" clearable></up-input>
</view>
<view style="font-size: 26rpx; color: #ff9900; margin: 10rpx 0 10rpx; padding-left: 9px">用户名由字母或数字组成长度6-32</view>
<view style="margin-bottom: 30rpx">
<up-input fontSize="30rpx" v-model="dataFrom.phone" placeholder="请输入您的手机号" border="bottom" clearable></up-input>
</view>
<view style="margin-bottom: 30rpx; display: flex; align-items: center">
<up-input fontSize="30rpx" v-model="dataFrom.smsCode" placeholder="请输入验证码" border="bottom" clearable></up-input>
<up-code ref="uCode" @change="codeChange2" keep-running start-text="点我获取验证码"></up-code>
<text @click="getCode2" :text="tips" style="font-size: 28rpx; color: rgba(111, 162, 86, 1)">{{ tips }}</text>
</view>
<view style="margin-bottom: 30rpx">
<up-input fontSize="30rpx" v-model="dataFrom.shareCode" placeholder="请输入您的邀请码" border="bottom" clearable></up-input>
</view>
<view>
<up-input fontSize="30rpx" v-model="dataFrom.passwd" type="password" placeholder="请输入您的密码" border="bottom" clearable></up-input>
</view>
<view style="font-size: 26rpx; color: #ff9900; margin: 10rpx 0 10rpx; padding-left: 9px">密码必须包含字母数字长度8-32</view>
<view style="margin-bottom: 30rpx">
<up-input fontSize="30rpx" v-model="dataFrom.confirmPasswd" type="password" placeholder="请再次输入您的密码" border="bottom" clearable></up-input>
</view>
</view>
<view style="font-size: 28rpx; color: #666; margin-top: 20rpx">
已有账号
<text style="color: rgba(111, 162, 86, 1)" @click="toLogin">立即登录</text>
</view>
<view style="display: flex; justify-content: center; margin-top: 80rpx">
<view class="login_btn" @click="submit">注册</view>
</view>
</view>
<view style="display: flex; flex-wrap: wrap; justify-content: center; margin-top: 20rpx; font-size: 26rpx; align-items: center">
<up-checkbox @change="changeChex" :customStyle="{ marginRight: '15rpx', marginBotton: 0 }"></up-checkbox>
已阅读并同意
<navigator url="/pages/agreement/agreement?id=9" style="color: rgba(111, 162, 86, 1)">用户注册服务协议</navigator>
<navigator url="/pages/agreement/agreement?id=10" style="color: rgba(111, 162, 86, 1)">隐私政策</navigator>
</view>
<view style="height: 150rpx"></view>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { registerApi, smsCode } from '@/api/api.js';
import { onLoad } from '@dcloudio/uni-app';
const statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px';
let tips = ref('');
let uCode = ref(null);
let passwd = ref('');
let dataFrom = reactive({
userName: '',
passwd: '',
shareCode: '',
phone: '',
platform: 1,
smsCode: '',
confirmPasswd: ''
});
let xieyi = ref(false);
onLoad(() => {
const invite_code = uni.getStorageSync('invite_code');
if (invite_code) {
dataFrom.shareCode = invite_code;
}
});
let changeChex = (e) => {
xieyi.value = e;
};
let toLogin = () => {
uni.navigateBack();
};
let codeChange2 = (text) => {
tips.value = text;
};
let getCode2 = () => {
if (!dataFrom.phone) return uni.showToast({ title: '请输入手机号', icon: 'none' });
if (uCode.value.canGetCode) {
// 模拟向后端请求验证码
uni.showLoading({
title: '正在获取验证码'
});
smsCode({
phone: dataFrom.phone
}).then((res) => {
uni.hideLoading();
uni.$u.toast('验证码已发送');
uCode.value.start();
});
} else {
uni.$u.toast('倒计时结束后再发送');
}
};
let submit = async () => {
if (!xieyi.value) return uni.showToast({ title: '请先阅读并勾选隐私政策和用户注册服务协议', icon: 'none' });
if (!dataFrom.userName) return uni.showToast({ title: '请输入用户名', icon: 'none' });
if (!dataFrom.phone) return uni.showToast({ title: '请输入手机号', icon: 'none' });
if (dataFrom.phone.length != 11) return uni.showToast({ title: '请输入正确的手机号', icon: 'none' });
if (!dataFrom.smsCode) return uni.showToast({ title: '请输入验证码', icon: 'none' });
if (!dataFrom.shareCode) return uni.showToast({ title: '请输入邀请码', icon: 'none' });
if (!dataFrom.passwd) return uni.showToast({ title: '请输入密码', icon: 'none' });
if (!dataFrom.confirmPasswd) return uni.showToast({ title: '请再次输入密码', icon: 'none' });
if (dataFrom.passwd != dataFrom.confirmPasswd) return uni.showToast({ title: '两次密码输入不一致', icon: 'none' });
let _res = await registerApi(dataFrom);
uni.showToast({ title: '注册成功', icon: 'none' });
setTimeout(() => {
uni.navigateBack();
}, 200);
};
let back = () => {
uni.navigateBack();
};
</script>
<style scoped lang="scss">
.login {
&_bei {
position: fixed;
right: -120rpx;
top: -206rpx;
width: 728rpx;
height: 728rpx;
}
&_logo {
margin-top: 150rpx;
&_img {
width: 280rpx;
height: 200rpx;
// background: #e6e6e6;
// box-shadow: 0rpx 0rpx 110rpx 2rpx rgba(115, 192, 76, 0.19);
border-radius: 28rpx 28rpx 28rpx 28rpx;
margin-bottom: 20rpx;
}
&_tit {
font-weight: bold;
font-size: 44rpx;
color: #232323;
}
}
&_btn {
width: 474rpx;
height: 78rpx;
background: rgba(111, 162, 86, 1);
border-radius: 54rpx 54rpx 54rpx 54rpx;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 30rpx;
color: #ffffff;
}
}
.orderdetail_header {
width: 750rpx;
position: fixed;
left: 0;
top: 0;
z-index: 99;
}
</style>

View File

@@ -0,0 +1,121 @@
<template>
<view style="padding: 30rpx">
<view>
<view style="font-size: 30rpx; color: #949494">当前增值收益 {{ user.money2 }}</view>
<view style="height: 20rpx"></view>
<up-input :customStyle="{ backgroundColor: '#ffffff' }" type="number" placeholder="请输入充值金额" border="surround" v-model="form.money"></up-input>
<view style="font-size: 30rpx; color: #949494; margin-top: 16rpx;">最小充值金额为{{ rechargeConfig.min_money }}</view>
</view>
<view style="height: 30rpx"></view>
<view style="background-color: #fff; padding: 30rpx; border-radius: 10rpx">
<view style="font-size: 28rpx;#606266">支付方式</view>
<view style="height: 20rpx"></view>
<up-radio-group v-model="form.pay_type" iconPlacement="right" :borderBottom="true" placement="column">
<up-radio :name="1">
<view class="up-flex up-flex-y-center" style="display: flex; align-items: center">
<up-icon name="/static/icon/weixin.png" imgMode="widthFix" size="50rpx" />
<view style="width: 20rpx"></view>
<view>
<view style="font-size: 30rpx">微信支付</view>
<view style="font-size: 28rpx; color: #909399">微信快捷支付</view>
</view>
</view>
</up-radio>
</up-radio-group>
</view>
<view style="height: 100rpx"></view>
<up-button type="primary" @click="getRecharge">立即支付</up-button>
<view style="height: 100rpx"></view>
</view>
</template>
<script setup>
import { rechargeAllinPay, getAppConfig } from '@/api/api.js';
import { ref, reactive } from 'vue';
import { onShow, onLoad } from '@dcloudio/uni-app';
import { userHook } from '@/hooks/userInfo.js';
const { user } = userHook();
const form = reactive({
money: '',
pay_type: 1
});
let rechargeConfig = ref();
onLoad(() => {
getAppConfig().then((res) => {
console.log(res);
const walletConfig = res?.find(item => item.configKey === "shop_recharge")
const configValue = walletConfig ? walletConfig.configValue : {}
rechargeConfig.value = JSON.parse(configValue);
});
});
onShow(async () => {
let options = uni.getEnterOptionsSync();
const shop_order_pay_show = uni.getStorageSync('shop_order_pay_show');
let appId = 'wxef277996acc166c3';
if (options.scene == '1038' && options.referrerInfo.appId == appId && shop_order_pay_show == 1) {
uni.setStorageSync('shop_order_pay_show', 0);
// 代表从收银台小程序返回
let extraData = options.referrerInfo.extraData;
if (!extraData) {
// "当前通过物理按键返回,未接收到返参,建议自行查询交易结果";
uni.showModal({
title: '提示',
content: '未检测到支付结果',
success: (res) => {
if (res.confirm) {
}
}
});
} else {
if (extraData.code == 'success') {
// "支付成功";
uni.showToast({
title: '支付成功',
icon: 'none'
});
uni.navigateBack();
} else if (extraData.code == 'cancel') {
// "支付已取消";
uni.showToast({
title: '支付已取消',
icon: 'none'
});
} else {
// "支付失败:" + extraData.errmsg;
uni.showToast({
title: '支付失败:' + extraData.errmsg,
icon: 'none'
});
}
}
}
});
const getRecharge = () => {
rechargeAllinPay(form).then((res) => {
uni.openEmbeddedMiniProgram({
appId: res.appid,
extraData: res.extraData,
success(res) {
// 打开成功
uni.setStorageSync('shop_order_pay_show', 1);
}
});
});
};
</script>
<style lang="scss">
.xkl-no {
background-color: #f1f1f1;
}
.xkl-cur {
background-color: #2cce7f;
color: #ffffff;
}
</style>

190
pageInvest/money/wallet.vue Normal file
View File

@@ -0,0 +1,190 @@
<template>
<view class="wallet p30">
<z-paging ref="paging" v-model="dataList" use-page-scroll @query="queryList">
<view class="wallet_pall">
<view>
<view class="wallet_pall_header">
基础收益
<!-- <view @click="navTo(`/pages/mine/transferBalance`, true)">收益转入</view> -->
</view>
<view class="wallet_pall_ye">
<view>{{ user.money || '0.00' }}</view>
<!-- <view style="margin-top: 10rpx" @click="navTo(`/pages/mine/topUp`, true)">充值</view> -->
</view>
</view>
<view>
<view class="wallet_pall_header">增值收益</view>
<view class="wallet_pall_ye">
<view>{{ user.money2 || '0.00' }}</view>
</view>
</view>
</view>
<view class="mt30" style="padding: 15rpx 30rpx; display: flex; align-items: center; background: #6fa256; border-radius: 0 0 16rpx 16rpx">
<view @click="navTo(`/pageInvest/money/recharge`, true)" style="width: 330rpx; text-align: center; color: #fff">充值</view>
<view @click="navTo(`/pageInvest/money/withdraw`, true)" style="width: 330rpx; text-align: center; color: #fff">提现</view>
</view>
<view class="mt30">
<uni-section title="明细" type="line" titleFontSize="32rpx"></uni-section>
</view>
<view class="mt30 wallet_list" v-for="(item, index) in dataList" :key="index">
<view class="wallet_list_left">
<view>{{ moneyJson.find((val) => val.id == item.type).name }}</view>
<view>{{ item.created_at }}</view>
</view>
<view class="wallet_list_right">{{ item.money }}</view>
</view>
</z-paging>
</view>
</template>
<script setup>
import { reactive, ref } from 'vue';
import { onPullDownRefresh, onPageScroll, onReachBottom, onLoad, onShow } from '@dcloudio/uni-app';
import { timeFormat } from '@/uni_modules/uview-plus';
import { extractRecordList } from '@/api/api.js';
import moneyJson from '@/common/money.json';
import { userHook } from '@/hooks/userInfo.js';
const { user } = userHook();
import { useNav } from '@/hooks/useNav.js';
const { nav, navTo } = useNav();
let getInfo = ref({});
const paging = ref(null);
let dataList = ref([]);
let num = ref(1);
let isPagingRefNotFound = () => {
return !paging.value;
};
onShow(async () => {
if (num.value != 1) {
paging.value.reload();
}
num.value++;
});
onPullDownRefresh(() => {
if (isPagingRefNotFound()) return;
paging.value.reload().catch(() => {});
});
onPageScroll((e) => {
if (isPagingRefNotFound()) return;
paging.value.updatePageScrollTop(e.scrollTop);
e.scrollTop < 10 && paging.value.doChatRecordLoadMore();
});
onReachBottom(() => {
if (isPagingRefNotFound()) return;
paging.value.pageReachBottom();
});
const queryList = (pageNo, pageSize) => {
const params = {
current: pageNo,
pageSize: pageSize
};
extractRecordList(params)
.then((res) => {
paging.value.complete(res);
})
.catch((res) => {
paging.value.complete(false);
});
};
</script>
<style scoped lang="scss">
.wallet_pall {
background: #6fa256;
// border-radius: 16rpx 16rpx 16rpx 16rpx;
height: 272rpx;
// background: linear-gradient(179deg, #4874e5 0%, #3864d6 100%);
border-radius: 16rpx 16rpx 0 0;
padding: 40rpx;
padding-bottom: 0;
border-bottom: 1rpx solid rgba(153, 153, 153, 0.6);
display: flex;
align-items: center;
justify-content: space-between;
&_header {
font-weight: bold;
font-size: 26rpx;
color: #ffffff;
display: flex;
align-items: center;
justify-content: space-between;
view {
width: 128rpx;
height: 58rpx;
background: #ffffff;
border-radius: 32rpx 32rpx 32rpx 32rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 26rpx;
color: #6fa256;
}
}
&_ye {
display: flex;
align-items: center;
justify-content: space-between;
height: 100%;
view:nth-child(1) {
font-weight: bold;
font-size: 68rpx;
color: #ffffff;
}
view:nth-child(2) {
width: 128rpx;
height: 58rpx;
background: #ffffff;
border-radius: 32rpx 32rpx 32rpx 32rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 26rpx;
color: #6fa256;
}
}
}
.wallet_list {
width: 690rpx;
height: 120rpx;
background: #ffffff;
border-radius: 8rpx 8rpx 8rpx 8rpx;
padding: 15rpx 30rpx;
@include flex($space: space-between);
&_left {
view:nth-child(1) {
font-weight: bold;
font-size: 28rpx;
color: #232323;
margin-bottom: 10rpx;
}
view:nth-child(2) {
font-size: 24rpx;
color: #232323;
}
}
&_right {
font-weight: bold;
font-size: 28rpx;
color: #ff2727;
}
}
.mt30 {
margin-bottom: 30rpx;
}
</style>

View File

@@ -0,0 +1,267 @@
<template>
<view class="withdraw p30">
<!-- #ifdef MP-ALIPAY -->
<view style="height: 30rpx"></view>
<!-- #endif -->
<view class="withdraw_k" @click="toNav">
<view class="withdraw_k_tit">提现到</view>
<view class="withdraw_k_input">请选择银行卡</view>
<image class="withdraw_k_img" src="/static/icon/xia.png"></image>
</view>
<view v-if="bank">
<view style="background-color: #ffffff; border-radius: 12rpx; padding: 20rpx; margin-bottom: 20rpx">
<view class="u-flex u-flex-y-center" style="font-size: 28rpx">
<view>
<u-tag :text="bank.role == 1 ? '个人' : '企业'" size="mini" :type="bank.role == 1 ? 'success' : 'error'" plain plainFill></u-tag>
</view>
<view style="width: 30rpx"></view>
<view style="font-size: 26rpx">{{ bank.realname }}</view>
<view style="width: 30rpx"></view>
<view style="font-size: 26rpx">{{ bank.mobile || '' }}</view>
</view>
<view style="height: 20rpx"></view>
<view style="color: #232323">
<!-- <view style="font-size: 28rpx">开户行{{ bank.bankName }}</view>
<view style="height: 10rpx"></view> -->
<view style="font-size: 28rpx" v-if="bank.role == 2">开户行{{ bank.subname }}</view>
<view style="height: 10rpx"></view>
<view style="font-size: 28rpx">银行卡号{{ bank.num }}</view>
<view style="height: 10rpx"></view>
<!-- <view style="font-size: 28rpx" v-if="bank.type == 2">纳税人识别号{{ bank.taxNo ? maskCardNumber(bank.taxNo) : '' }}</view>
<view style="height: 10rpx"></view> -->
</view>
</view>
</view>
<view class="withdraw_mon">
<view class="withdraw_mon_tit">提现金额</view>
<view class="withdraw_mon_input">
<view class="withdraw_mon_input_fu"></view>
<view>
<up-input fontSize="36rpx" placeholder="请输入金额" :border="false" v-model="dataFrom.money"></up-input>
</view>
<view class="withdraw_mon_input_note" @click="dataFrom.money = getInfo.money">全部提现</view>
</view>
<view>
<up-input :border="false" disabled v-model="getInfo.mobile"></up-input>
</view>
<view class="withdraw_mon_input">
<up-input placeholder="请输入验证码" :border="false" v-model="dataFrom.smsCode"></up-input>
<view style="width: 250rpx">
<up-code ref="uCode" @change="codeChange2" keep-running start-text="点我获取验证码"></up-code>
<up-button @click="getCode" color="#4874e5">{{ tips }}</up-button>
</view>
</view>
<view class="withdraw_mon_note">当前基础收益{{ getInfo.money }}</view>
<view class="withdraw_mon_note">最低提现金额为{{ appConfig.chargeMinAmount }}</view>
<view class="withdraw_mon_note">私户每100.00元提现手续费为{{ appConfig.free }}%</view>
</view>
<view class="withdraw_note">
<view class="withdraw_note_tit" style="font-weight: bold; font-size: 26rpx">提现规则</view>
<!-- <view class="withdraw_note_s">1.现在本软件填写提现账户</view> -->
<!-- <view class="withdraw_note_s">2.然后扫描二维码填写相应的提现账户</view> -->
<view class="withdraw_note_s">1.每月1号1121号可提现到账时间T+(1-3)</view>
<view class="withdraw_note_s">2.提现年龄是18-65</view>
<view class="withdraw_note_s">3.提现银行卡是常用的一类银行否则会有限额</view>
<view class="withdraw_note_s">4.一月不能超{{ appConfig.monthQuota }}如遇超出 提现后管理人员会联系您</view>
<view class="withdraw_note_s">5.提现次数不限公户无限额无手续费</view>
<!-- <view class="withdraw_note_s" style="flex-direction: column; display: flex; align-items: center">
<up-image width="350rpx" height="350rpx" src="https://xingdong-app.oss-cn-beijing.aliyuncs.com/hongjiesuan-xingdong.png" mode="widthFix"></up-image>
<view style="height: 10rpx"></view>
<view>长按保存二维码</view>
</view> -->
</view>
<view style="height: 50rpx"></view>
<view style="display: flex; justify-content: center; margin-top: 80rpx">
<view class="affirm_btn" @click="payOrder">立即提现</view>
</view>
<view style="height: 50rpx"></view>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { userInfoIsInvest, smsCode, getAppConfig, pointsExtract } from '@/api/api.js';
import { onLoad, onShow } from '@dcloudio/uni-app';
let value = ref();
let getInfo = ref({});
let appConfig = ref([]);
let tips = ref('');
let uCode = ref(null);
let dataFrom = reactive({
money: '',
smsCode: '',
accountId: ''
});
let bank = ref();
onLoad(async () => {
let _res = await userInfoIsInvest();
getInfo.value = _res;
const configData = await getAppConfig();
const walletConfig = configData?.find(item => item.configKey === "APP_WALLET")
const configValue = walletConfig ? walletConfig.configValue : {}
appConfig.value = JSON.parse(configValue);
uni.$on('bank', (e) => {
bank.value = e;
dataFrom.accountId = e.id;
console.log(e);
});
});
let toNav = () => {
uni.navigateTo({
url: '/pages/bank/bank?type=xz'
});
};
let codeChange2 = (text) => {
tips.value = text;
};
let getCode = () => {
console.log(123456);
if (!getInfo.value.mobile) return uni.showToast({ title: '请输入手机号', icon: 'none' });
if (uCode.value.canGetCode) {
// 模拟向后端请求验证码
uni.showLoading({
title: '正在获取验证码'
});
smsCode({
phone: getInfo.value.mobile
}).then((res) => {
uni.hideLoading();
uni.$u.toast('验证码已发送');
uCode.value.start();
});
} else {
uni.$u.toast('倒计时结束后再发送');
}
};
function maskCardNumber(cardNumber) {
if (!cardNumber || typeof cardNumber !== 'string') {
throw new Error('Invalid card number');
}
const sanitizedNumber = cardNumber.replace(/\D/g, '');
if (sanitizedNumber.length < 4) {
throw new Error('Card number is too short');
}
const lastFourDigits = sanitizedNumber.slice(-4);
const maskedNumber = '*'.repeat(sanitizedNumber.length - 4) + lastFourDigits;
return maskedNumber;
}
let payOrder = async () => {
console.log(getInfo.value.money, 'getInfo.value.money');
console.log(dataFrom.money, 'dataFrom.money');
if (Number(getInfo.value.money) < Number(dataFrom.money)) return uni.showToast({ title: '可提现金额不足', icon: 'none' });
if (!dataFrom.accountId) return uni.showToast({ title: '请先选择提现银行卡', icon: 'none' });
if (!dataFrom.money) return uni.showToast({ title: '请输入提现金额', icon: 'none' });
if (!dataFrom.smsCode) return uni.showToast({ title: '请输入验证码', icon: 'none' });
let _res = await pointsExtract(dataFrom);
uni.showModal({
title: '提示',
content: '提交成功',
showCancel: false,
success() {
uni.navigateBack();
}
});
};
</script>
<style scoped lang="scss">
.withdraw {
&_k {
width: 100%;
height: 74rpx;
padding: 0 20rpx;
background: #ffffff;
border-radius: 8rpx 8rpx 8rpx 8rpx;
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 30rpx;
&_tit {
font-weight: bold;
font-size: 24rpx;
color: #232323;
margin-right: 100rpx;
}
&_input {
flex: 1;
text-align: right;
font-size: 28rpx;
}
&_img {
width: 44rpx;
height: 44rpx;
}
}
&_mon {
padding: 20rpx;
background: #ffffff;
border-radius: 8rpx 8rpx 8rpx 8rpx;
&_tit {
font-weight: bold;
font-size: 24rpx;
color: #232323;
}
&_input {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 2rpx solid #cccccc;
padding: 15rpx 0;
margin-bottom: 20rpx;
&_fu {
font-weight: bold;
font-size: 66rpx;
color: #232323;
}
&_note {
font-weight: bold;
font-size: 24rpx;
color: #ff7777;
}
}
&_note {
font-weight: 400;
font-size: 24rpx;
color: #232323;
margin-bottom: 10rpx;
}
}
&_note {
margin-top: 30rpx;
padding: 0 15rpx;
view {
margin-bottom: 15rpx;
font-weight: 400;
font-size: 26rpx;
color: #232323;
line-height: 40rpx;
}
}
}
.affirm_btn {
width: 650rpx;
height: 78rpx;
background: #4874e5;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 24rpx;
color: #ffffff;
}
</style>

246
pageInvest/shop/affirm.vue Normal file
View File

@@ -0,0 +1,246 @@
<template>
<view class="p30">
<view style="height: 20rpx"></view>
<view style="background-color: #ffffff; padding: 20rpx; border-radius: 10rpx; font-size: 30rpx; display: flex">
<image style="width: 220rpx; height: 220rpx; border-radius: 16rpx" :src="shop.cover" mode="aspectFill"></image>
<view style="padding: 20rpx">
<view style="color: #232323">{{ shop.name }}</view>
<view style="height: 20rpx"></view>
<view>
<text>单价</text>
<text style="color: crimson">{{ shop.currentPrice }}</text>
</view>
<view style="height: 20rpx"></view>
<view>
<text>总价</text>
<text style="color: crimson">{{ shop.currentPrice * dataFrom.num }}</text>
</view>
</view>
</view>
<view style="height: 20rpx"></view>
<view style="background-color: #ffffff; padding: 20rpx; border-radius: 10rpx; font-size: 30rpx; display: flex; align-items: center; justify-content: space-between">
<view class="u-flex">
<view>购买数量</view>
<view style="width: 10rpx"></view>
</view>
<view><up-number-box v-model="dataFrom.num" inputWidth="100rpx" @change="changenum"></up-number-box></view>
</view>
<!-- <view
@click="toAddress"
v-if="shop.purposeType != 1"
style="
background-color: #ffffff;
padding: 20rpx;
border-radius: 10rpx;
font-size: 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 30rpx;
"
>
<view class="u-flex" v-if="!addData">
<view>请先选择收货地址</view>
</view>
<view class="address-a" v-else @click="toAddress">
<view class="top">
<view class="top-a">
<view>{{ addData.realName }}</view>
<view>{{ addData.phone }}</view>
</view>
<view class="top-b">{{ addData.province }} {{ addData.city }} {{ addData.district }} {{ addData.detail }}</view>
</view>
</view>
</view> -->
<!-- <view
style="background-color: #ffffff; padding: 20rpx; border-radius: 10rpx; font-size: 30rpx; margin-top: 30rpx"
v-if="shop.purposeType == 2 || (shop.purposeType == 3 && shop.salePrice == 2980)"
>
<view style="font-weight: 700">温馨提示{{ shop.purposeType == 2 ? `${shop.itemType == 7 ? '20' : shop.itemType == 20 ? '5' : ''}台包安装` : '' }}</view>
<view style="height: 20rpx"></view>
<view>套包安装内容仅限50米实际电缆小于50米的以实际安装必要长度为准差值米数不以任何形式赠送或返还;超出50米的超出部分按100元/米补足超出的费用</view>
</view> -->
<view style="background-color: #ffffff; padding: 20rpx; border-radius: 10rpx; font-size: 30rpx; margin-top: 30rpx">
<view style="font-weight: 700">购买须知</view>
<view style="height: 20rpx"></view>
<view style="color: #dd6161">付款成功后立即生效并投入生产安装不支持退款退货</view>
<view style="height: 20rpx"></view>
<view style="display: flex; align-items: center; justify-content: space-between">
<view style="display: flex">
<view>阅读并同意:</view>
<navigator url="/pages/protocol/buy?id=14" style="color: dodgerblue" open-type="navigate">
<text>充电桩购销合同</text>
</navigator>
</view>
<view>
<up-text v-if="policy.is_buy == 1" text="已同意" type="primary"></up-text>
<up-text v-else text="未同意" type="error"></up-text>
</view>
</view>
<view style="height: 20rpx"></view>
<view style="display: flex; align-items: center; justify-content: space-between">
<view style="display: flex">
<view>阅读并同意:</view>
<navigator url="/pages/protocol/trusteeship?id=13" style="color: dodgerblue" open-type="navigate">
<text>充电桩托管协议</text>
</navigator>
</view>
<view>
<up-text v-if="policy.is_trusteeship == 1" text="已同意" type="primary"></up-text>
<up-text v-else text="未同意" type="error"></up-text>
</view>
</view>
</view>
<view style="display: flex; justify-content: center; margin-top: 80rpx">
<view class="affirm_btn" @click="add">确认订单</view>
</view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue';
import { addGoodsOrders } from '@/api/api.js';
import { shopInfo } from '@/api/api.js';
import { onLoad } from '@dcloudio/uni-app';
let dataFrom = ref({
num: 1
});
let shop = ref({});
let policy = ref({
is_trusteeship: 0,
is_buy: 0
});
let address = ref({});
let addData = ref(null);
let typeTrue = computed(() => {
var a = false;
if (
(shop.value.purposeType == 2 && dataFrom.value.num == 20 && shop.value.itemType == 7) ||
(shop.value.purposeType == 2 && dataFrom.value.num == 5 && shop.value.itemType == 20)
) {
a = true;
}
return a;
});
onLoad(async (options) => {
let _res = await shopInfo({
goodId: options.id
});
shop.value = _res;
uni.$on('buy', (e) => {
policy.value.is_buy = e;
});
uni.$on('trusteeship', (e) => {
policy.value.is_trusteeship = e;
});
uni.$on('address', (e) => {
addData.value = e;
address.value = {
takeName: e.realName,
takePhone: e.phone,
takeAddress: `${e.province}${e.city}${e.district}${e.detail}`
};
});
});
let changenum = (e) => {
console.log(e);
};
let toAddress = () => {
uni.navigateTo({
url: '/pages/address/list?type=1'
});
};
let add = async () => {
// if (!address.value.takeName && shop.value.purposeType != 1) return uni.showToast({ title: '请先选择收货地址', icon: 'none' });
if (!policy.value.is_buy) return uni.showToast({ title: '请阅读并同意《充电桩购销合同》', icon: 'none' });
if (!policy.value.is_trusteeship) return uni.showToast({ title: '请阅读并同意《充电桩托管协议》', icon: 'none' });
let _res = await addGoodsOrders({
num: dataFrom.value.num,
goodsId: shop.value.id
// ...address.value
});
uni.redirectTo({
url: `/pageInvest/shop/pay?id=${_res.id}&amount=${_res.payMoney}&type=1&num=${_res.num}&goodsId=${shop.value.id}`
});
};
</script>
<style scoped lang="scss">
.affirm_btn {
width: 650rpx;
height: 78rpx;
background: #4874e5;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 24rpx;
color: #ffffff;
}
.address-a {
.top {
padding: 40rpx;
.top-a {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 30rpx;
font-weight: bold;
color: #222222;
margin-bottom: 45rpx;
}
.top-b {
font-size: 30rpx;
font-weight: bold;
color: #999999;
}
}
.bottom {
padding: 35rpx;
display: flex;
align-items: center;
justify-content: space-between;
.bottom-che {
display: flex;
align-items: center;
image {
width: 32rpx;
height: 32rpx;
margin-right: 10rpx;
}
font-size: 24rpx;
font-weight: bold;
color: #222222;
}
.bottom-r {
font-size: 26rpx;
font-weight: bold;
color: #999999;
display: flex;
align-items: center;
}
}
}
</style>

139
pageInvest/shop/details.vue Normal file
View File

@@ -0,0 +1,139 @@
<template>
<view class="shop">
<!-- <view class="orderdetail_header p30">
<view :style="{ height: statusBarHeight }"></view>
<view style="height: 44px; display: flex; align-items: center" @click="">
<up-icon name="arrow-left" bold color="#000" @click="back"></up-icon>
<view @click="back" style="margin-left: 25rpx; transition: all 0.5s">商品详情</view>
</view>
</view> -->
<up-swiper :list="[shop.cover]" height="759rpx"></up-swiper>
<view class="p30">
<view class="shop_info">
<view class="shop_info_mon"> {{ shop.currentPrice }}</view>
<view class="shop_info_tit">{{ shop.name }}</view>
<view class="shop_info_note">
库存{{ shop.stock }}
<view style="width: 50rpx"></view>
销量{{ shop.sales }}
</view>
</view>
</view>
<view style="margin: 30rpx 0; font-size: 30rpx; color: #333; text-align: center">详情介绍</view>
<image style="width: 100%" mode="widthFix" :src="item" v-for="(item, index) in shop.detail.split(',')" :key="index"></image>
<view style="height: 150rpx"></view>
<view class="shop_btn">
<!-- <view>
<view>首页</view>
</view>
<view>
<view>客服</view>
</view> -->
<view class="shop_btn_btn" @click="navTo(`/pageInvest/shop/affirm?id=${shop.id}`)">立即下单</view>
</view>
</view>
</template>
<script setup>
import { ref, reactive, computed } from 'vue';
import { useNav } from '@/hooks/useNav.js';
import { shopInfo } from '@/api/api.js';
let shop = ref({});
const { nav, navTo } = useNav();
const headerBg = ref(false);
const statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px';
import { onLoad, onPageScroll } from '@dcloudio/uni-app';
const list3 = ref(['/static/图层 979.png']);
onLoad(async (options) => {
console.log(options);
let _res = await shopInfo({
goodId: options.id
});
shop.value = _res;
});
const back = () => {
uni.navigateBack();
};
onPageScroll((e) => {
if (e.scrollTop > uni.getSystemInfoSync().statusBarHeight + 44) {
headerBg.value = true;
} else {
headerBg.value = false;
}
});
</script>
<style>
page {
background: #f7f7f7;
}
</style>
<style scoped lang="scss">
.orderdetail_header {
width: 750rpx;
transition: all 0.5s;
}
.shop_btn {
position: fixed;
bottom: 0;
left: 0;
padding: 20rpx 60rpx 30rpx;
width: 750rpx;
height: 120rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #fff;
image {
width: 40rpx;
height: 40rpx;
margin-right: 30rpx;
}
&_btn {
width: 496rpx;
// height: 64rpx;
padding: 15rpx;
border-radius: 8rpx 8rpx 8rpx 8rpx;
border: 2rpx solid #002ea4;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 28rpx;
color: #002ea4;
}
}
.shop_info {
padding: 30rpx;
background-color: #fff;
border-radius: 8rpx;
margin-top: 30rpx;
&_mon {
font-weight: bold;
font-size: 44rpx;
color: #ff1a1a;
}
&_tit {
font-weight: bold;
font-size: 34rpx;
color: #232323;
margin-bottom: 15rpx;
}
&_note {
display: flex;
align-items: center;
font-weight: 400;
font-size: 30rpx;
color: #666666;
}
}
</style>

214
pageInvest/shop/order.vue Normal file
View File

@@ -0,0 +1,214 @@
<template>
<view class="order">
<z-paging ref="paging" v-model="dataList" use-page-scroll @query="queryList">
<up-dropdown>
<!-- <up-dropdown-item @change="upChange" v-model="dataFrom.sourceType" title="商品类型" :options="options1"></up-dropdown-item> -->
<up-dropdown-item @change="upChange" v-model="dataFrom.businessPayType" title="支付类型" :options="options2"></up-dropdown-item>
<up-dropdown-item @change="upChange" v-model="dataFrom.status" title="状态" :options="options3"></up-dropdown-item>
</up-dropdown>
<view class="p30">
<view class="order_view" v-for="i in dataList" :key="i" @click="navTo(`/pages/order/details?id=${i.id}`)">
<view class="order_view_dd">
<view>
<text style="font-weight: 500">订单号</text>
:{{ i.orderNo }}
</view>
<view>
<up-tag size="mini" v-if="i.status == 0" text="待支付" plain></up-tag>
<up-tag size="mini" v-if="i.status == -1" text="已取消" type="warning" plain></up-tag>
<up-tag size="mini" v-if="i.status == 1" text="支付成功" type="success" plain></up-tag>
<up-tag size="mini" v-if="i.status == -2" text="退款" type="error" plain></up-tag>
</view>
</view>
<view class="order_view_info">
<image class="order_view_info_img" :src="JSON.parse(i.picture)[0]" mode="aspectFit"></image>
<view class="order_view_info_right">
<view class="order_view_info_right_tit">
<view style="display: flex; align-items: center">
<up-tag size="mini" :text="i.sourceType == 1 ? '商品' : '套餐'" bgColor="#4874e5" borderColor="#4874e5"></up-tag>
<view style="margin-left: 15rpx">
{{ i.goodName }}
</view>
</view>
</view>
<view class="order_view_info_right_num" style="display: flex; align-items: center; justify-content: space-between">数量:{{ i.num }}</view>
<view class="order_view_info_right_mon">
订单金额:
<text style="color: crimson">{{ i.amount }}</text>
</view>
</view>
</view>
<view
style="
display: flex;
align-items: center;
justify-content: space-between;
border-top: 1rpx solid rgba(153, 153, 153, 0.5);
margin-top: 15rpx;
padding-top: 15rpx;
"
>
<view style="font-size: 28rpx">{{ timeFormat(new Date(i.createTime).getTime(), 'yyyy-mm-dd hh:MM') }}</view>
<view>
<up-tag size="mini" v-if="i.orderPlatform == 3" text="支付宝" plain></up-tag>
<up-tag size="mini" v-if="i.orderPlatform == 2" text="微信" type="success" plain></up-tag>
<up-tag size="mini" v-if="i.orderPlatform == 1" text="钱包" type="warning" plain></up-tag>
</view>
</view>
</view>
</view>
</z-paging>
</view>
</template>
<script setup>
import { reactive, ref } from 'vue';
import { useNav } from '@/hooks/useNav.js';
import { onPullDownRefresh, onPageScroll, onReachBottom } from '@dcloudio/uni-app';
import { orderPage } from '@/api/api.js';
import { timeFormat } from '@/uni_modules/uview-plus';
const { navTo } = useNav();
const paging = ref(null);
let dataList = ref([]);
let dataFrom = reactive({
status: '',
businessPayType: '',
sourceType: ''
});
let options1 = ref([
{
label: '商品',
value: 1
},
{
label: '套餐',
value: 2
}
]);
let options2 = ref([
{
label: '微信',
value: 1
},
{
label: '支付宝',
value: 2
},
{
label: '钱包',
value: 3
}
]);
let options3 = ref([
{
label: '待支付',
value: 0
},
{
label: '支付成功',
value: 1
},
{
label: '取消',
value: -1
},
{
label: '退款',
value: -2
}
]);
let isPagingRefNotFound = () => {
return !paging.value;
};
onPullDownRefresh(() => {
if (isPagingRefNotFound()) return;
paging.value.reload().catch(() => {});
});
onPageScroll((e) => {
if (isPagingRefNotFound()) return;
paging.value.updatePageScrollTop(e.scrollTop);
e.scrollTop < 10 && paging.value.doChatRecordLoadMore();
});
onReachBottom(() => {
if (isPagingRefNotFound()) return;
paging.value.pageReachBottom();
});
const upChange = (e) => {
console.log(dataFrom);
paging.value.reload();
};
const queryList = (pageNo, pageSize) => {
let { id } = uni.getStorageSync('user');
const params = {
current: pageNo,
pageSize: pageSize,
...dataFrom
};
orderPage(params)
.then((res) => {
paging.value.complete(res.records);
})
.catch((res) => {
paging.value.complete(false);
});
};
</script>
<style scoped lang="scss">
.order {
&_view {
background: #ffffff;
border-radius: 16rpx;
padding: 25rpx;
margin-bottom: 30rpx;
&_info {
@include flex;
&_img {
width: 208rpx;
height: 208rpx;
margin-right: 15rpx;
border-radius: 10rpx;
}
&_right {
flex: 1;
font-size: 28rpx;
color: #232323;
&_tit {
@include flex($space: space-between);
margin-bottom: 15rpx;
}
&_num {
margin-bottom: 15rpx;
}
&_mon {
margin-bottom: 15rpx;
text {
color: #ff2e24;
}
}
&_time {
}
}
}
&_dd {
@include flex($space: space-between);
font-weight: bold;
font-size: 28rpx;
color: #232323;
margin-bottom: 15rpx;
}
}
}
</style>

184
pageInvest/shop/pay.vue Normal file
View File

@@ -0,0 +1,184 @@
<template>
<view>
<view style="height: 20rpx"></view>
<view style="background-color: #ffffff; border-radius: 10rpx; padding: 30rpx; text-align: center">
<view style="color: #fa3534">
<text style="font-size: 30rpx"></text>
<text style="font-size: 36rpx; font-weight: 700">{{ amount }}</text>
</view>
<view style="color: #909399; font-size: 28rpx">支付金额</view>
</view>
<view style="height: 20rpx"></view>
<view style="background-color: #fff; padding: 30rpx; border-radius: 10rpx">
<view style="font-size: 28rpx;#606266">支付方式</view>
<view style="height: 20rpx"></view>
<up-radio-group v-model="dataFrom.pay_type" iconPlacement="right" :borderBottom="true" placement="column">
<up-radio :name="3" label="123456">
<view style="display: flex; align-items: center">
<up-icon name="/static/icon/money.png" imgMode="widthFix" size="50rpx" />
<view style="width: 20rpx"></view>
<view>
<view style="font-size: 30rpx">余额支付</view>
<view style="font-size: 28rpx; color: #909399">当前余额{{ user.money2 || 0 }}</view>
</view>
</view>
</up-radio>
<up-radio :name="1">
<view style="display: flex; align-items: center">
<up-icon name="/static/icon/weixin.png" imgMode="widthFix" size="50rpx" />
<view style="width: 20rpx"></view>
<view>
<view style="font-size: 30rpx; display: flex; align-items: center">
微信支付
<!-- <view style="padding: 4rpx 15rpx; margin-left: 10rpx; border-radius: 25rpx; background-color: #e03737; font-size: 24rpx; color: #fff">
随机立减0.01-20
</view> -->
</view>
<view style="font-size: 28rpx; color: #909399">微信快捷支付</view>
</view>
</view>
</up-radio>
</up-radio-group>
</view>
<view style="height: 100rpx"></view>
<view style="display: flex; justify-content: center; margin-top: 80rpx">
<view class="affirm_btn" @click="payOrder">确认支付</view>
</view>
</view>
</template>
<script setup>
import { payAllinPay, handleSubmit, payMoney } from '@/api/api.js';
import { ref, reactive } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import { userHook } from '@/hooks/userInfo.js';
const { user } = userHook();
let orderId = ref('');
let amount = ref(0);
let money = ref(0);
let goodsId = ref(null);
let num = ref(0);
let type = ref(1);
onLoad(async (options) => {
orderId.value = options.id;
amount.value = options.amount;
type.value = options.type;
num.value = options.num;
goodsId.value = options.goodsId;
// let { points2 } = await userInfo({ id });
// money.value = points2;
});
onShow(async () => {
let options = uni.getEnterOptionsSync();
const shop_order_pay_show = uni.getStorageSync('shop_order_pay_show');
let appId = 'wxef277996acc166c3';
if (options.scene == '1038' && options.referrerInfo.appId == appId && shop_order_pay_show == 1) {
uni.setStorageSync('shop_order_pay_show', 0);
// 代表从收银台小程序返回
let extraData = options.referrerInfo.extraData;
if (!extraData) {
// "当前通过物理按键返回,未接收到返参,建议自行查询交易结果";
uni.showModal({
title:'提示',
content:'未检测到支付结果, 您可以查看订单',
confirmText:'查看订单',
success: (res) => {
if(res.confirm){
uni.reLaunch({
url:'/pages/home/home?tabBarShow=1'
})
}
}
})
} else {
if (extraData.code == 'success') {
// "支付成功";
uni.showToast({
title: '支付成功',
icon: 'none'
});
uni.reLaunch({
url:'/pages/home/home?tabBarShow=1'
})
} else if (extraData.code == 'cancel') {
// "支付已取消";
uni.showToast({
title: '支付已取消',
icon: 'none'
});
} else {
// "支付失败:" + extraData.errmsg;
uni.showToast({
title: '支付失败:' + extraData.errmsg,
icon: 'none'
});
}
}
}
});
let dataFrom = reactive({
pay_type: 3
});
let payOrder = async () => {
// let { username } = uni.getStorageSync('user');
// handleSubmit({
// num: num.value,
// goodsId: goodsId.value,
// userName: username
// }).then((res) => {
// uni.reLaunch({
// url: `/pages/home/home?tabBarShow=1`
// });
// });
// return;
let _res;
if (dataFrom.pay_type == 1 || dataFrom.pay_type == 2) {
payAllinPay({ orderId: orderId.value }).then((res) => {
uni.openEmbeddedMiniProgram({
appId: res.appid,
extraData: res.extraData,
success(res) {
// 打开成功
uni.setStorageSync('shop_order_pay_show', 1);
}
});
});
}
if (dataFrom.pay_type == 3) {
// _res = type.value == 1 ? await walletPaymentGoods({ id: orderId.value }) : await walletPaymentPackages({ id: orderId.value });
// uni.redirectTo({
// url: `/pages/order/success?id=${orderId.value}&amount=${_res.amount}&orderNo=${_res.orderNo ? _res.orderNo : ''}&createTime=${_res.createTime ? _res.createTime : ''}`
// });
payMoney({ orderId: orderId.value }).then((res) => {
uni.reLaunch({
url:'/pages/home/home?tabBarShow=1'
})
})
}
return;
// let _res = type.value == 1 ? await walletPaymentGoods({ id: orderId.value }) : await walletPaymentPackages({ id: orderId.value });
};
</script>
<style lang="scss">
.affirm_btn {
width: 650rpx;
height: 78rpx;
background: #4874e5;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 30rpx;
color: #ffffff;
}
</style>

234
pageInvest/shop/shop.vue Normal file
View File

@@ -0,0 +1,234 @@
<template>
<view class="u-wrap">
<view class="u-search-box">
<view class="u-search-inner">
<up-icon name="search" color="#909399" :size="28"></up-icon>
<text class="u-search-text">请输入您需要的商品名称</text>
</view>
</view>
<view class="u-menu-wrap">
<scroll-view scroll-y scroll-with-animation class="u-tab-view menu-scroll-view" :scroll-top="scrollTop">
<view
v-for="(item, index) in tabbar"
:key="index"
class="u-tab-item"
:class="[current == index ? 'u-tab-item-active' : '']"
:data-current="index"
@tap.stop="swichMenu(index)"
>
<text class="u-line-1">{{ item.name }}</text>
</view>
</scroll-view>
<block v-for="(item, index) in tabbar" :key="index">
<scroll-view scroll-y class="right-box" v-if="current == index">
<view class="page-view">
<view class="class-item">
<view class="item-title">
<text>{{ item.name }}</text>
</view>
<view class="item-container">
<view class="thumb-box" v-for="(item1, index1) in item.foods" :key="index1">
<image class="item-menu-image" :src="item1.cover" mode=""></image>
<view class="item-menu-name">{{ item1.name }}</view>
</view>
</view>
</view>
</view>
</scroll-view>
</block>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { goodsList, categoryList } from '@/api/api.js';
let tabbar = ref([]);
let scrollTop = ref(0);
let current = ref(0);
let menuHeight = ref(0);
let menuItemHeight = ref(0);
// [
// {
// name: '女装',
// foods: [
// {
// name: 'A字裙',
// key: 'A字裙',
// icon: 'https://cdn.uviewui.com/uview/common/classify/1/1.jpg',
// cat: 10
// }
// ]
// }
// ]
onLoad(() => {
categoryList().then((res) => {
tabbar.value = res.map((item, index) => {
return {
...item,
foods: []
};
});
goodsList({ categoryId: res[0].id }).then((res) => {
tabbar.value[0].foods = res;
});
});
});
async function swichMenu(index) {
if (index == current.value) return;
current.value = index;
goodsList({ categoryId: tabbar.value[index].id }).then((res) => {
tabbar.value[index].foods = res;
});
// 如果为0意味着尚未初始化
if (menuHeight.value == 0 || menuItemHeight.value == 0) {
await this.getElRect('menu-scroll-view', 'menuHeight');
await this.getElRect('u-tab-item', 'menuItemHeight');
}
// 将菜单菜单活动item垂直居中
this.scrollTop = index * menuItemHeight.value + menuItemHeight.value / 2 - menuHeight.value / 2;
}
function getElRect(elClass, dataVal) {
new Promise((resolve, reject) => {
const query = uni.createSelectorQuery().in(this);
query
.select('.' + elClass)
.fields({ size: true }, (res) => {
// 如果节点尚未生成res值为null循环调用执行
if (!res) {
setTimeout(() => {
this.getElRect(elClass);
}, 10);
return;
}
this[dataVal] = res.height;
})
.exec();
});
}
</script>
<style lang="scss" scoped>
.u-wrap {
height: calc(100vh);
/* #ifdef H5 */
height: calc(100vh - var(--window-top));
/* #endif */
display: flex;
flex-direction: column;
}
.u-search-box {
padding: 18rpx 30rpx;
}
.u-menu-wrap {
flex: 1;
display: flex;
overflow: hidden;
}
.u-search-inner {
background-color: rgb(234, 234, 234);
border-radius: 100rpx;
display: flex;
align-items: center;
padding: 10rpx 16rpx;
}
.u-search-text {
font-size: 26rpx;
color: $u-tips-color;
margin-left: 10rpx;
}
.u-tab-view {
width: 200rpx;
height: 100%;
}
.u-tab-item {
height: 80rpx;
background: #f6f6f6;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
font-size: 26rpx;
color: #444;
font-weight: 400;
line-height: 1;
}
.u-tab-item-active {
position: relative;
color: #000;
font-size: 30rpx;
font-weight: 600;
background: #fff;
}
.u-tab-item-active::before {
content: '';
position: absolute;
border-left: 4px solid rgba(111, 162, 86, 1);
height: 45rpx;
left: 0;
top: calc(50% - 22.5rpx);
}
.u-tab-view {
height: 100%;
}
.right-box {
background-color: rgb(250, 250, 250);
}
.page-view {
padding: 16rpx;
}
.class-item {
margin-bottom: 30rpx;
background-color: #fff;
padding: 16rpx;
border-radius: 8rpx;
}
.item-title {
font-size: 26rpx;
color: $u-main-color;
font-weight: bold;
}
.item-menu-name {
font-weight: normal;
font-size: 24rpx;
color: $u-main-color;
}
.item-container {
display: flex;
flex-wrap: wrap;
}
.thumb-box {
width: 33.333333%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
margin-top: 20rpx;
}
.item-menu-image {
width: 120rpx;
height: 120rpx;
}
</style>