This commit is contained in:
全栈小学生 2025-01-03 18:01:15 +08:00
parent 4e3dc148c4
commit b680807856
36 changed files with 1005 additions and 194 deletions

View File

@ -77,12 +77,6 @@
const configStore = useConfigStore()
try {
uni.hideTabBar() // tabbar
} catch (e) {
}
let loginConfig = uni.getStorageSync('login_config')
if (!loginConfig) {
loginConfig = deepClone(configStore.login)

View File

@ -0,0 +1,7 @@
import request from '@/utils/request'
/**
*
*/
export function getFriendspayInfo(tradeType : string, tradeId : number) {
return request.get(`pay/friendspay/info/${tradeType}/${tradeId}`, {}, { showErrorMessage: true })
}

View File

@ -1,153 +1,160 @@
import request from '@/utils/request'
export function getMemberInfo() {
return request.get('member/member')
return request.get('member/member')
}
/**
*
*/
export function getPointList(data : AnyObject) {
return request.get('member/account/point', data)
export function getPointList(data: AnyObject) {
return request.get('member/account/point', data)
}
/**
*
*/
export function getPointType(account_type : string) {
return request.get(`member/account/fromtype/${account_type}`)
export function getPointType(account_type: string) {
return request.get(`member/account/fromtype/${ account_type }`)
}
/**
*
*/
export function getBalanceList(data : AnyObject) {
return request.get('member/account/balance', data)
export function getBalanceList(data: AnyObject) {
return request.get('member/account/balance', data)
}
/**
* ,
*/
export function getBalanceListAll(data : AnyObject) {
return request.get('member/account/balance_list', data)
export function getBalanceListAll(data: AnyObject) {
return request.get('member/account/balance_list', data)
}
/**
*
*/
export function getMoneyList(data : AnyObject) {
return request.get('member/account/money', data)
export function getMoneyList(data: AnyObject) {
return request.get('member/account/money', data)
}
/**
*
*/
export function modifyMember(data : AnyObject) {
return request.put(`member/modify/${data.field}`, data, { showErrorMessage: true })
export function modifyMember(data: AnyObject) {
return request.put(`member/modify/${ data.field }`, data, { showErrorMessage: true })
}
/**
*
*/
export function bindMobile(data : AnyObject) {
if(uni.getStorageSync('pid')){
data.pid = uni.getStorageSync('pid');
}
return request.put('member/mobile', data, { showErrorMessage: true })
export function bindMobile(data: AnyObject) {
if (uni.getStorageSync('pid')) {
data.pid = uni.getStorageSync('pid');
}
return request.put('member/mobile', data, { showErrorMessage: true })
}
/**
*
*/
export function cashOutTransferType() {
return request.get('member/cash_out/transfertype')
return request.get('member/cash_out/transfertype')
}
/**
*
*/
export function cashOutConfig() {
return request.get('member/cash_out/config')
return request.get('member/cash_out/config')
}
/**
*
*/
export function cashOutApply(data : AnyObject) {
return request.post('member/cash_out/apply', data, { showSuccessMessage: true, showErrorMessage: true })
export function cashOutApply(data: AnyObject) {
return request.post('member/cash_out/apply', data, { showSuccessMessage: true, showErrorMessage: true })
}
/**
*
*/
export function getCashoutAccountInfo(data : AnyObject) {
return request.get(`member/cashout_account/${data.account_id}`, {})
export function getCashoutAccountInfo(data: AnyObject) {
return request.get(`member/cashout_account/${ data.account_id }`, {})
}
/**
*
*/
export function getFirstCashoutAccountInfo(data : AnyObject) {
return request.get('member/cashout_account/firstinfo', data)
export function getFirstCashoutAccountInfo(data: AnyObject) {
return request.get('member/cashout_account/firstinfo', data)
}
/**
*
*/
export function getCashoutAccountList(data : AnyObject) {
return request.get(`member/cashout_account`, data)
export function getCashoutAccountList(data: AnyObject) {
return request.get(`member/cashout_account`, data)
}
/**
*
*/
export function getCashOutList(data : AnyObject) {
return request.get(`member/cash_out`, data)
export function getCashOutList(data: AnyObject) {
return request.get(`member/cash_out`, data)
}
/**
*
*/
export function getCashOutDetail(id : number) {
return request.get(`member/cash_out/${id}`)
export function getCashOutDetail(id: number) {
return request.get(`member/cash_out/${ id }`)
}
/**
*
*/
export function addCashoutAccount(data : AnyObject) {
return request.post('member/cashout_account', data, { showSuccessMessage: true, showErrorMessage: true })
export function addCashoutAccount(data: AnyObject) {
return request.post('member/cashout_account', data, { showSuccessMessage: true, showErrorMessage: true })
}
/**
*
*/
export function editCashoutAccount(data : AnyObject) {
return request.put(`member/cashout_account/${data.account_id}`, data, { showSuccessMessage: true, showErrorMessage: true })
export function editCashoutAccount(data: AnyObject) {
return request.put(`member/cashout_account/${ data.account_id }`, data, {
showSuccessMessage: true,
showErrorMessage: true
})
}
/**
*
*/
export function deleteCashoutAccount(accountId: number) {
return request.delete(`member/cashout_account/${accountId}`, { showSuccessMessage: true, showErrorMessage: true })
return request.delete(`member/cashout_account/${ accountId }`, { showSuccessMessage: true, showErrorMessage: true })
}
/**
*
*/
export function getMemberCommission(data : AnyObject) {
return request.get(`member/account/commission`,data)
export function getMemberCommission(data: AnyObject) {
return request.get(`member/account/commission`, data)
}
/**
*
*/
export function getCommissionList(data : AnyObject) {
return request.get(`member/account/commission`, data)
export function getCommissionList(data: AnyObject) {
return request.get(`member/account/commission`, data)
}
/**
*
*/
export function getAccountType(params: Record<string, any>) {
return request.get(`member/account/fromtype/${params.account_type}`)
return request.get(`member/account/fromtype/${ params.account_type }`)
}
/**
@ -156,7 +163,7 @@ export function getAccountType(params: Record<string, any>) {
* @returns
*/
export function getAddressList(params: Record<string, any>) {
return request.get(`member/address`, params)
return request.get(`member/address`, params)
}
/**
@ -165,7 +172,7 @@ export function getAddressList(params: Record<string, any>) {
* @returns
*/
export function getAddressInfo(id: number) {
return request.get(`member/address/${id}`);
return request.get(`member/address/${ id }`);
}
/**
@ -174,7 +181,7 @@ export function getAddressInfo(id: number) {
* @returns
*/
export function addAddress(params: Record<string, any>) {
return request.post('member/address', params, { showErrorMessage: true, showSuccessMessage: true })
return request.post('member/address', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
@ -183,7 +190,7 @@ export function addAddress(params: Record<string, any>) {
* @returns
*/
export function editAddress(params: Record<string, any>) {
return request.put(`member/address/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true })
return request.put(`member/address/${ params.id }`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
@ -192,41 +199,42 @@ export function editAddress(params: Record<string, any>) {
* @returns
*/
export function deleteAddress(id: number) {
return request.delete(`member/address/${id}`, { showErrorMessage: true, showSuccessMessage: true })
return request.delete(`member/address/${ id }`, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
*/
export function getMemberLevel() {
return request.get(`member/level`);
return request.get(`member/level`);
}
/**
*
*/
export function getTaskGrowth() {
return request.get(`task/growth`);
return request.get(`task/growth`);
}
/**
*
*/
export function getSignInfo(data : AnyObject) {
return request.get(`member/sign/info/${data.year}/${data.month}`, {})
export function getSignInfo(data: AnyObject) {
return request.get(`member/sign/info/${ data.year }/${ data.month }`, {})
}
/**
*
*/
export function getDayPack(data : AnyObject) {
return request.get(`member/sign/award/${data.year}/${data.month}/${data.day}`)
export function getDayPack(data: AnyObject) {
return request.get(`member/sign/award/${ data.year }/${ data.month }/${ data.day }`)
}
/**
*
*/
export function getSignConfig() {
return request.get(`member/sign/config`)
return request.get(`member/sign/config`)
}
/**
@ -234,26 +242,26 @@ export function getSignConfig() {
* @returns
*/
export function setSign() {
return request.post('member/sign')
return request.post('member/sign')
}
/**
*
*/
export function getMemberAccountPointcount() {
return request.get(`member/account/pointcount`)
return request.get(`member/account/pointcount`)
}
/**
*
*/
export function getTaskPoint() {
return request.get(`task/point`)
return request.get(`task/point`)
}
/**
*
*/
export function rechargeConfig() {
return request.get('recharge/config')
}
return request.get('recharge/config')
}

View File

@ -10,6 +10,6 @@ export function pay(data : AnyObject) {
/**
*
*/
export function getPayInfo(tradeType : string, tradeId : number) {
return request.get(`pay/info/${tradeType}/${tradeId}`, {}, { showErrorMessage: true })
export function getPayInfo(tradeType : string, tradeId : number, params: Record<string, any>) {
return request.get(`pay/info/${tradeType}/${tradeId}`, params, { showErrorMessage: true })
}

View File

@ -90,8 +90,8 @@
<swiper-item class="swiper-item" v-for="(item,index) in diyComponent.swiper.list" :key="item.id" :style="swiperWarpCss">
<view @click="diyStore.toRedirect(item.link)">
<view class="item" :style="{height: imgHeight}">
<image v-if="item.imageUrl" :src="img(item.imageUrl)" mode="scaleToFill" :style="swiperWarpCss" :class="['w-full h-full',{'swiper-animation': swiperIndex != index}]" :show-menu-by-longpress="true"/>
<image v-else :src="img('static/resource/images/diy/figure.png')" :style="swiperWarpCss" mode="scaleToFill" :class="['w-full h-full',{'swiper-animation': swiperIndex != index}]" :show-menu-by-longpress="true"/>
<image v-if="item.imageUrl" :src="img(item.imageUrl)" mode="scaleToFill" :style="swiperWarpCss" :class="['w-full h-full',{'swiper-animation': (swiperIndex != index && diyComponent.swiper.indicatorStyle != 'style-3')}]" :show-menu-by-longpress="true"/>
<image v-else :src="img('static/resource/images/diy/figure.png')" :style="swiperWarpCss" mode="scaleToFill" :class="['w-full h-full',{'swiper-animation': (swiperIndex != index && diyComponent.swiper.indicatorStyle != 'style-3')}]" :show-menu-by-longpress="true"/>
</view>
</view>
</swiper-item>

View File

@ -3,6 +3,7 @@
"usernameRegisterTip":"输入账号密码注册",
"mobileRegisterTip":"输入手机号验证码注册",
"usernamePlaceholder": "请输入账号",
"usernameTips":"账号不能是纯数字",
"passwordPlaceholder": "请输入密码",
"confirmPasswordPlaceholder": "请再次确认密码",
"confirmPasswordError": "两次输入的密码不一致",

View File

@ -0,0 +1,11 @@
{
"payMoney":"实付金额",
"help":"帮",
"pay":"付款",
"helpPayInfo":"帮付订单信息",
"common": "共",
"goods":"种商品",
"finish":"该订单已完成",
"close":"该订单已关闭",
"payGenerously":"找朋友帮忙付"
}

View File

@ -0,0 +1,9 @@
{
"payMoney": "实付金额",
"friendPayOrderInfo": "帮付订单信息",
"common": "共",
"goods": "种商品",
"finish": "该订单已完成",
"close": "该订单已关闭",
"friendPay": "找朋友帮忙付"
}

View File

@ -1,15 +1,12 @@
{
"balanceInfo": "我的余额",
"recharge": "充值",
"cashOut":"提现",
"balanceDetail": "余额明细",
"accountBalance":"账户余额 (元)",
"balance":"余额 (元)",
"money":"可提现余额 (元)",
"availableBalance": "可用余额",
"rechargeAmountError": "充值金额错误",
"clickRecharge": "立即充值",
"rechargeAmountPlaceholder": "请输入充值金额",
"yuan":"元",
"rechargeRecord":"充值记录"
}
"balanceInfo": "我的余额",
"recharge": "充值",
"cashOut": "提现",
"balanceDetail": "余额明细",
"accountBalance": "账户余额 (元)",
"balance": "余额 (元)",
"money": "可提现余额 (元)",
"availableBalance": "可用余额",
"yuan": "元",
"rechargeRecord": "充值记录"
}

View File

@ -8,5 +8,5 @@
"commissionDetail": "佣金记录",
"emptyTip": "暂无提现记录",
"commissemptyTip": "暂无佣金记录",
"rechargeType":"充值方式:"
}
"rechargeType":"提现方式:"
}

View File

@ -1,15 +1,12 @@
{
"recharge": "充值",
"cashOut":"提现",
"transferMoney":"提现",
"commissionDetail": "佣金明细",
"accountCommission":"当前佣金(元)",
"commission":"累计佣金(元)",
"money":"提现中佣金(元)",
"availableCommission": "可用佣金",
"rechargeAmountError": "充值金额错误",
"clickRecharge": "立即充值",
"rechargeAmountPlaceholder": "请输入充值金额",
"yuan":"元",
"commissionInfo": "我的佣金"
}
"recharge": "充值",
"cashOut": "提现",
"transferMoney": "提现",
"commissionDetail": "佣金明细",
"accountCommission": "当前佣金(元)",
"commission": "累计佣金(元)",
"money": "提现中佣金(元)",
"availableCommission": "可用佣金",
"yuan": "元",
"commissionInfo": "我的佣金"
}

View File

@ -1,13 +1,10 @@
{
"recharge": "充值",
"cashOut":"提现",
"balanceDetail": "余额明细",
"accountBalance":"账户余额(元)",
"balance":"余额(元)",
"money":"可提现余额(元)",
"availableBalance": "可用余额",
"rechargeAmountError": "充值金额错误",
"clickRecharge": "立即充值",
"rechargeAmountPlaceholder": "请输入充值金额",
"yuan":"元"
}
"recharge": "充值",
"cashOut": "提现",
"balanceDetail": "余额明细",
"accountBalance": "账户余额(元)",
"balance": "余额(元)",
"money": "可提现余额(元)",
"availableBalance": "可用余额",
"yuan": "元"
}

View File

@ -69,11 +69,11 @@
<button class="w-[630rpx] h-[88rpx] !mx-[0] !bg-[#fff] !border-[var(--primary-color)] border-solid border-[2rpx] text-[26rpx] rounded-[44rpx] leading-[84rpx] !text-[var(--primary-color)]" @click="redirect({ url: '/app/pages/auth/login',param:{type:'username'}})">{{t('accountLogin')}}</button>
</view>
<view v-if="loginConfig.agreement_show" class="w-full flex items-center justify-center mt-[28rpx]">
<view class="flex items-center justify-center mt-[28rpx] py-[10rpx]" @click.stop="agreeChange">
<view class="flex items-center justify-center mt-[28rpx] py-[14rpx] px-[50rpx]" @click.stop="agreeChange">
<u-checkbox-group @change="agreeChange">
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="26rpx" :customStyle="{ 'marginTop': '5rpx !important' }" />
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="30rpx" />
</u-checkbox-group>
<view class="text-[24rpx] text-[var(--text-color-light6)] flex items-center flex-wrap">
<view class="text-[24rpx] text-[var(--text-color-light6)] flex items-center flex-wrap leading-[30rpx]">
<text>{{ t('agreeTips') }}</text>
<text @click.stop="redirect({ url: '/app/pages/auth/agreement?key=privacy' })" class="text-primary">{{t('privacyAgreement')}}</text>
<text>{{ t('and') }}</text>
@ -85,7 +85,7 @@
<view class="footer w-full" v-if="loginConfig.is_mobile && loginConfig.is_username">
<view class="text-[26rpx] leading-[36rpx] text-[333] text-center mb-[30rpx] font-400">{{t('otherLogin')}}</view>
<view class="flex justify-center">
<view class="h-[80rpx] w-[80rpx] text-center leading-[78rpx] border-[2rpx] text-primary rounded-[50%] border-solid border-[#ddd] nc-iconfont nc-icon-a-wodeV6xx-36 text-[46rpx] overflow-hidden" @click="redirect({ url: '/app/pages/auth/login',param:{type:'username'}})"></view>
<view class="h-[80rpx] w-[80rpx] text-center leading-[78rpx] border-[2rpx] text-[#FF7100] rounded-[50%] border-solid border-[#ddd] nc-iconfont nc-icon-wodeV6mm3 text-[46rpx] overflow-hidden" @click="redirect({ url: '/app/pages/auth/login',param:{type:'username'}})"></view>
</view>
<view class="text-[24rpx] leading-[36rpx] text-[var(--text-color-light9)] text-center font-400 mt-[30rpx]">{{t('accountLogin')}}</view>
</view>
@ -93,6 +93,25 @@
</view>
</view>
</view>
<uni-popup ref="popupRef" type="dialog">
<view class="bg-[#fff] flex flex-col justify-between w-[600rpx] min-h-[280rpx] rounded-[var(--rounded-big)] box-border px-[35rpx] pt-[35rpx] pb-[8rpx] relative">
<view class="flex justify-center">
<text class="text-[33rpx] font-700"> 用户协议及隐私保护</text>
</view>
<view class="flex items-center mb-[20rpx] mt-[20rpx] py-[20rpx]" @click.stop="agreeChange">
<view class="text-[26rpx] text-[var(--text-color-light6)] flex items-center flex-wrap">
<text>{{ t('agreeTips') }}</text>
<text @click.stop="redirect({ url: '/app/pages/auth/agreement?key=privacy' })" class="text-primary">{{t('privacyAgreement')}}</text>
<text>{{ t('and') }}</text>
<text @click.stop="redirect({ url: '/app/pages/auth/agreement?key=service' })" class="text-primary">{{t('userAgreement')}}</text>
</view>
</view>
<view class="">
<view class="w-[100%] flex justify-center bg-[var(--primary-color)] h-[70rpx] leading-[70rpx] text-[#fff] text-[26rpx] border-[0] font-500 rounded-[50rpx]" @click="dialogConfirm">同意并登录</view>
<view class="w-[100%] flex justify-center h-[70rpx] leading-[70rpx] text-[#999] text-[24rpx] border-[0] font-500 rounded-[50rpx]" @click="dialogClose">不同意</view>
</view>
</view>
</uni-popup>
</view>
</template>
@ -143,6 +162,16 @@
return !configStore.login.is_auth_register;
});
const loginLoading = ref(false)
const popupRef = ref()
const dialogClose =()=>{
popupRef.value.close();
}
const dialogConfirm =()=>{
isAgree.value=true
popupRef.value.close();
oneClickLogin()
}
onLoad(async ()=> {
await systemStore.getSiteInfoFn()
@ -203,7 +232,8 @@
//
const checkWxPrivacy = ()=> {
if (!isAgree.value && configStore.login.agreement_show) {
uni.showToast({ title: t('isAgreeTips'), icon: 'none' })
popupRef.value.open();
// uni.showToast({ title: t('isAgreeTips'), icon: 'none' })
return true;
}
return false;

View File

@ -17,7 +17,13 @@
</view>
<view class="h-[88rpx] flex w-full items-center px-[30rpx] rounded-[var(--goods-rounded-mid)] box-border bg-[#F6F6F6] mt-[40rpx]">
<u-form-item label="" prop="password" :border-bottom="false">
<u-input v-model="formData.password" border="none" type="password" maxlength="40" :placeholder="t('passwordPlaceholder')" autocomplete="new-password" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]"/>
<u-input v-model="formData.password" border="none" :password="isPassword" maxlength="40" :placeholder="t('passwordPlaceholder')" autocomplete="new-password" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]">
<template #suffix>
<view class="" @click="changePassword" v-if="formData.password">
<u-icon :name="isPassword?'eye-off':'eye-fill'" color="#b9b9b9" size="20"></u-icon>
</view>
</template>
</u-input>
</u-form-item>
</view>
</template>
@ -41,11 +47,11 @@
</u-form>
<view v-if="type == 'username'" class="text-right text-[24rpx] text-[var(--text-color-light9)] leading-[34rpx] mt-[20rpx]" @click="redirect({ url: '/app/pages/auth/resetpwd' })">{{t('resetpwd')}}</view>
<view :class="{'mt-[160rpx]':type != 'username','mt-[106rpx]':type == 'username'}">
<view v-if="configStore.login.agreement_show" class="flex items-center mb-[20rpx] py-[10rpx]" @click.stop="agreeChange">
<view v-if="configStore.login.agreement_show" class="flex items-center mb-[20rpx] py-[14rpx]" @click.stop="agreeChange">
<u-checkbox-group @change="agreeChange">
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="24rpx" :customStyle="{ 'marginTop': '4rpx' }"/>
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="30rpx"/>
</u-checkbox-group>
<view class="text-[24rpx] text-[var(--text-color-light6)] flex items-center flex-wrap">
<view class="text-[24rpx] text-[var(--text-color-light6)] flex items-center flex-wrap leading-[30rpx]">
<text>{{ t('agreeTips') }}</text>
<text @click.stop="redirect({ url: '/app/pages/auth/agreement?key=privacy' })" class="text-primary">{{t('privacyAgreement')}}</text>
<text>{{ t('and') }}</text>
@ -64,6 +70,25 @@
</view>
</view>
</view>
<uni-popup ref="popupRef" type="dialog">
<view class="bg-[#fff] flex flex-col justify-between w-[600rpx] min-h-[280rpx] rounded-[var(--rounded-big)] box-border px-[35rpx] pt-[35rpx] pb-[8rpx] relative">
<view class="flex justify-center">
<text class="text-[33rpx] font-700"> 用户协议及隐私保护</text>
</view>
<view class="flex items-center mb-[20rpx] mt-[20rpx] py-[20rpx]" @click.stop="agreeChange">
<view class="text-[26rpx] text-[var(--text-color-light6)] flex items-center flex-wrap">
<text>{{ t('agreeTips') }}</text>
<text @click.stop="redirect({ url: '/app/pages/auth/agreement?key=privacy' })" class="text-primary">{{t('privacyAgreement')}}</text>
<text>{{ t('and') }}</text>
<text @click.stop="redirect({ url: '/app/pages/auth/agreement?key=service' })" class="text-primary">{{t('userAgreement')}}</text>
</view>
</view>
<view class="">
<view class="w-[100%] flex justify-center bg-[var(--primary-color)] h-[70rpx] leading-[70rpx] text-[#fff] text-[26rpx] border-[0] font-500 rounded-[50rpx]" @click="dialogConfirm">同意并登录</view>
<view class="w-[100%] flex justify-center h-[70rpx] leading-[70rpx] text-[#999] text-[24rpx] border-[0] font-500 rounded-[50rpx]" @click="dialogClose">不同意</view>
</view>
</view>
</uni-popup>
<view class="footer w-full" v-if="isShowQuickLogin">
<view class="text-[26rpx] leading-[36rpx] text-[#333] text-center mb-[30rpx] font-400">{{t('oneClicklogin')}}</view>
<view class="flex justify-center">
@ -73,7 +98,7 @@
</view>
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { ref, reactive, computed, onMounted,nextTick } from 'vue'
import { usernameLogin, mobileLogin } from '@/app/api/auth'
import useMemberStore from '@/stores/member'
import useConfigStore from '@/stores/config'
@ -101,7 +126,19 @@
const type = ref('')
const isAgree = ref(false)
const isShowQuickLogin = ref(false) //
const popupRef = ref()
const isPassword = ref(true)
const changePassword =()=>{
isPassword.value = !isPassword.value
}
const dialogClose =()=>{
popupRef.value.close();
}
const dialogConfirm =()=>{
isAgree.value=true
popupRef.value.close();
handleLogin()
}
onLoad(async (option: any)=> {
await configStore.getLoginConfig()
if (!getToken() && !configStore.login.is_username && !configStore.login.is_mobile) {
@ -155,7 +192,6 @@
}
}
// #endif
})
const formData = reactive({
@ -227,7 +263,8 @@
const handleLogin = () => {
formRef.value.validate().then(() => {
if (configStore.login.agreement_show && !isAgree.value) {
uni.showToast({ title: t('isAgreeTips'), icon: 'none' });
popupRef.value.open();
// uni.showToast({ title: t('isAgreeTips'), icon: 'none' });
return false;
}

View File

@ -17,12 +17,24 @@
</view>
<view class="h-[88rpx] flex w-full items-center px-[30rpx] rounded-[var(--goods-rounded-mid)] box-border bg-[#F6F6F6] mt-[40rpx]">
<u-form-item label="" prop="password" :border-bottom="false">
<u-input v-model="formData.password" border="none" type="password" maxlength="40" :placeholder="t('passwordPlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]"/>
<u-input v-model="formData.password" border="none" :password="isPassword" maxlength="40" :placeholder="t('passwordPlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]">
<template #suffix>
<view class="" @click="changePassword" v-if="formData.password">
<u-icon :name="isPassword?'eye-off':'eye-fill'" color="#b9b9b9" size="20"></u-icon>
</view>
</template>
</u-input>
</u-form-item>
</view>
<view class="h-[88rpx] flex w-full items-center px-[30rpx] rounded-[var(--goods-rounded-mid)] box-border bg-[#F6F6F6] mt-[40rpx]">
<u-form-item label="" prop="confirm_password" :border-bottom="false">
<u-input v-model="formData.confirm_password" border="none" type="password" maxlength="40" :placeholder="t('confirmPasswordPlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]"/>
<u-input v-model="formData.confirm_password" border="none" :password="isConfirmPassword" maxlength="40" :placeholder="t('confirmPasswordPlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]">
<template #suffix>
<view class="" @click="changeConfirmPassword" v-if="formData.confirm_password">
<u-icon :name="isConfirmPassword?'eye-off':'eye-fill'" color="#b9b9b9" size="20"></u-icon>
</view>
</template>
</u-input>
</u-form-item>
</view>
</template>
@ -56,11 +68,11 @@
</template>
</u-form>
<view class="mt-[160rpx]">
<view v-if="configStore.login.agreement_show" class="flex items-center mb-[20rpx] py-[10rpx]" @click.stop="agreeChange">
<view v-if="configStore.login.agreement_show" class="flex items-center mb-[20rpx] py-[14rpx]" @click.stop="agreeChange">
<u-checkbox-group @change="agreeChange">
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="24rpx" :customStyle="{ 'marginTop': '4rpx' }" />
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="30rpx" />
</u-checkbox-group>
<view class="text-[24rpx] text-[var(--text-color-light6)] flex items-center flex-wrap">
<view class="text-[24rpx] text-[var(--text-color-light6)] flex items-center flex-wrap leading-[30rpx]">
<text>{{ t('agreeTips') }}</text>
<text @click.stop="redirect({ url: '/app/pages/auth/agreement?key=privacy' })" class="text-primary">{{t('privacyAgreement')}}</text>
<text>{{ t('and') }}</text>
@ -77,6 +89,25 @@
</view>
</view>
</view>
<uni-popup ref="popupRef" type="dialog">
<view class="bg-[#fff] flex flex-col justify-between w-[600rpx] min-h-[280rpx] rounded-[var(--rounded-big)] box-border px-[35rpx] pt-[35rpx] pb-[8rpx] relative">
<view class="flex justify-center">
<text class="text-[33rpx] font-700"> 用户协议及隐私保护</text>
</view>
<view class="flex items-center mb-[20rpx] mt-[20rpx] py-[20rpx]" @click.stop="agreeChange">
<view class="text-[26rpx] text-[var(--text-color-light6)] flex items-center flex-wrap">
<text>{{ t('agreeTips') }}</text>
<text @click.stop="redirect({ url: '/app/pages/auth/agreement?key=privacy' })" class="text-primary">{{t('privacyAgreement')}}</text>
<text>{{ t('and') }}</text>
<text @click.stop="redirect({ url: '/app/pages/auth/agreement?key=service' })" class="text-primary">{{t('userAgreement')}}</text>
</view>
</view>
<view class="">
<view class="w-[100%] flex justify-center bg-[var(--primary-color)] h-[70rpx] leading-[70rpx] text-[#fff] text-[26rpx] border-[0] font-500 rounded-[50rpx]" @click="dialogConfirm">同意并注册</view>
<view class="w-[100%] flex justify-center h-[70rpx] leading-[70rpx] text-[#999] text-[24rpx] border-[0] font-500 rounded-[50rpx]" @click="dialogClose">不同意</view>
</view>
</view>
</uni-popup>
</view>
</template>
@ -114,14 +145,31 @@
captcha_key: '',
captcha_code: ''
})
const popupRef = ref()
const dialogClose =()=>{
popupRef.value.close();
}
const dialogConfirm =()=>{
isAgree.value=true
popupRef.value.close();
handleRegister()
}
const real_name_input = ref(true);
onMounted(() => {
//
setTimeout(()=>{
real_name_input.value = false;
},800)
},800)
});
const isPassword = ref(true)
const isConfirmPassword = ref(true)
const changePassword =()=>{
isPassword.value = !isPassword.value
}
const changeConfirmPassword =()=>{
isConfirmPassword.value = !isConfirmPassword.value
}
const memberStore = useMemberStore()
const configStore = useConfigStore()
@ -164,12 +212,21 @@
const rules = computed(()=>{
return {
'username': {
type: 'string',
required: type.value == 'username',
message: t('usernamePlaceholder'),
trigger: ['blur', 'change'],
},
'username': [
{
type: 'string',
required: type.value == 'username',
message: t('usernamePlaceholder'),
trigger: ['blur', 'change'],
},
{
validator(rule: any, value: any){
return !uni.$u.test.number(value)
},
message: t('usernameTips'),
trigger: ['change','blur'],
}
],
'password': {
type: 'string',
required: type.value == 'username',
@ -229,7 +286,7 @@
const handleRegister = () => {
formRef.value.validate().then(() => {
if (configStore.login.agreement_show && !isAgree.value) {
uni.showToast({ title: t('isAgreeTips'), icon: 'none' });
popupRef.value.open();
return false;
}
if (loading.value) return

View File

@ -25,12 +25,24 @@
</view>
<view class="h-[88rpx] flex w-full items-center px-[30rpx] rounded-[var(--goods-rounded-mid)] box-border bg-[#F6F6F6] mt-[40rpx]">
<u-form-item label="" prop="password" :border-bottom="false">
<u-input v-model="formData.password" border="none" type="password" maxlength="40" :placeholder="t('passwordPlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]"/>
<u-input v-model="formData.password" border="none" :password="isPassword" maxlength="40" :placeholder="t('passwordPlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]">
<template #suffix>
<view class="" @click="changePassword" v-if="formData.password">
<u-icon :name="isPassword?'eye-off':'eye-fill'" color="#b9b9b9" size="20"></u-icon>
</view>
</template>
</u-input>
</u-form-item>
</view>
<view class="h-[88rpx] flex w-full items-center px-[30rpx] rounded-[var(--goods-rounded-mid)] box-border bg-[#F6F6F6] mt-[40rpx]">
<u-form-item label="" prop="confirm_password" :border-bottom="false">
<u-input v-model="formData.confirm_password" border="none" type="password" maxlength="40" :placeholder="t('confirmPasswordPlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]"/>
<u-input v-model="formData.confirm_password" border="none" :password="isConfirmPassword" maxlength="40" :placeholder="t('confirmPasswordPlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]">
<template #suffix>
<view class="" @click="changeConfirmPassword" v-if="formData.confirm_password">
<u-icon :name="isConfirmPassword?'eye-off':'eye-fill'" color="#b9b9b9" size="20"></u-icon>
</view>
</template>
</u-input>
</u-form-item>
</view>
</u-form>
@ -78,6 +90,15 @@
const loading = ref(false)
const formRef: any = ref(null)
const isPassword = ref(true)
const isConfirmPassword = ref(true)
const changePassword =()=>{
isPassword.value = !isPassword.value
}
const changeConfirmPassword =()=>{
isConfirmPassword.value = !isConfirmPassword.value
}
const rules = {
'password': {

View File

@ -0,0 +1,39 @@
<template>
<view @touchmove.prevent.stop>
<u-popup :show="messagePopup" @close="closeFn" mode="center" round="var(--rounded-big)">
<view class="w-[570rpx] px-[32rpx] popup-common center" v-if="Object.keys(configInfo).length">
<view class="title">{{ configInfo.pay_explain_title }}</view>
<scroll-view :scroll-y="true" class="px-[30rpx] box-border max-h-[260rpx]" v-if="configInfo.pay_explain_content">
<block v-for="(item) in configInfo.pay_explain_content.split('\n')">
<view class="text-[28rpx] leading-[40rpx] mb-[20rpx]">{{ item }}</view>
</block>
</scroll-view>
<view class="btn-wrap !pt-[40rpx]">
<button class="primary-btn-bg w-[480rpx] h-[70rpx] text-[26rpx] leading-[70rpx] rounded-[35rpx] !text-[#fff] font-500" @click="closeFn">我知道了</button>
</view>
</view>
</u-popup>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const messagePopup = ref(false)
const configInfo = ref<any>({})
const closeFn = () =>{
messagePopup.value = false
}
const open = (data: any) => {
configInfo.value = data
messagePopup.value = true;
}
defineExpose({
open
})
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,217 @@
<template>
<view :style="themeColor()">
<view class="bg-[var(--page-bg-color)] min-h-screen overflow-hidden" v-if="Object.keys(friendsInfo).length && !loading">
<view :style="{background: 'url(' + img('static/resource/images/app/friendpay_money.png') + ') left bottom / cover no-repeat'}" class="pb-[194rpx] overflow-hidden">
<!-- #ifdef MP-WEIXIN -->
<view class="sticky top-0 left-0 right-0 z-100">
<top-tabbar :data="topTabbarData" :scrollBool="topTabarObj.getScrollBool()" />
</view>
<!-- #endif -->
<view class="mt-[20rpx] flex flex-col items-center">
<u-avatar :src="img(friendsInfo.member.headimg)" size="50" leftIcon="none" :default-url="img('static/resource/images/default_headimg.png')" />
<view class="flex items-center mt-[20rpx] text-[#fff] text-[26rpx] leading-[36rpx]">
<text class="font-bold mr-[10rpx] max-w-[250rpx] truncate">{{ friendsInfo.member.nickname }}</text>
<text>请您帮忙付款~</text>
</view>
<view class="message bg-[#fe0708] relative max-w-[520rpx] px-[20rpx] py-[12rpx] rounded-[12rpx] border-solid border-[1rpx] border-color text-[24rpx] text-[#fff] leading-[30rpx] box-border text-center mt-[20rpx] mx-[114rpx]" v-if="friendsInfo.config.pay_leave_message">{{ friendsInfo.config.pay_leave_message }}</view>
</view>
</view>
<view class="-mt-[154rpx] card-template sidebar-margin mb-[var(--top-m)]">
<view class="text-[24rpx] text-center mb-[10rpx]">{{ t('payMoney') }}</view>
<view class="text-center mb-[50rpx]">
<text class="text-[32rpx] font-500 price-font text-[#FF4142]"></text>
<text class="text-[56rpx] font-bold price-font text-[#FF4142]">{{ parseFloat(friendsInfo.money).toFixed(2).split('.')[0] }}</text>
<text class="text-[32rpx] font-500 price-font text-[#FF4142]">.{{ parseFloat(friendsInfo.money).toFixed(2).split('.')[1] }}</text>
</view>
<view class="px-[20rpx] box-border">
<button class="bg-[#FFB4B1] !text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500" hover-class="none" v-if="friendsInfo.status == 2 ">{{ t('finish') }}</button>
<button class="bg-[#FFB4B1] !text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500" hover-class="none" v-else-if="friendsInfo.status == -1">{{ t('close') }}</button>
<button class="primary-btn-bg !text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500" hover-class="none" v-else :loading="operateLoading" @click="save">{{ friendsInfo.config.pay_button_name ? friendsInfo.config.pay_button_name : t('payGenerously') }}</button>
</view>
<view class="mt-[20rpx] flex items-baseline justify-center text-[var(--text-color-light9)]" @click="redirect({url: '/app/pages/index/index'})">
<text class="text-[24rpx] mr-[6rpx]">返回首页</text>
</view>
</view>
<view class="card-template sidebar-margin mb-[var(--top-m)]" v-if="friendsInfo.config.pay_info_switch">
<template v-if="JSON.stringify(friendsInfo.trade_info) !== '[]' && friendsInfo.trade_info.item_list.length">
<view class="flex justify-between items-center mb-[30rpx]">
<view class="text-[30rpx] text-[#333] font-500">{{ t('helpPayInfo') }}</view>
<view class="flex-shrink-0" @click="handleMessage" v-if="friendsInfo.config.pay_explain_switch">
<text class="mr-[8rpx] text-[24rpx]">{{ friendsInfo.config.pay_explain_title }}</text>
<text class="nc-iconfont nc-icon-jichuxinxiV6xx text-[26rpx]"></text>
</view>
</view>
<view class="border-0 border-solid border-b-[1rpx] border-[#f6f6f6] mb-[20rpx]">
<view v-for="(item, index) in friendsInfo.trade_info.item_list" class="flex justify-between" :class="{' mb-[34rpx]': (index + 1) != friendsInfo.trade_info.length }">
<view class="w-[170rpx] h-[170rpx] rounded-[var(--goods-rounded-big)] overflow-hidden flex-shrink-0">
<u--image class="overflow-hidden" radius="var(--goods-rounded-big)" width="170rpx" height="170rpx" :src="img(item.item_image ? item.item_image : '')" model="aspectFill">
<template #error>
<image class="w-[170rpx] h-[170rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill" />
</template>
</u--image>
</view>
<view class="ml-[20rpx] flex flex-1 flex-col justify-between">
<view>
<view class="text-[28rpx] using-hidden leading-[40rpx] text-[#333]">{{ item.item_name }}</view>
<view class="text-[24rpx] mt-[14rpx] text-[var(--text-color-light9)] using-hidden leading-[28rpx]" v-if="item.item_sub_name ">{{ item.item_sub_name }}</view>
</view>
<view class="flex justify-between items-baseline">
<view class="price-font text-[#FF4142]">
<text class="text-[24rpx]"></text>
<text class="text-[40rpx] font-500">{{ parseFloat(item.item_price).toFixed(2).split('.')[0] }}</text>
<text class="text-[24rpx] font-500">.{{ parseFloat(item.item_price).toFixed(2).split('.')[1] }}</text>
</view>
<text class="text-right text-[26rpx]">x{{ item.item_num }}</text>
</view>
</view>
</view>
</view>
<view class="text-[26rpx] text-right">{{ friendsInfo.trade_info.item_total }}</view>
</template>
<template v-else>
<view class="text-[28rpx] leading-[40rpx] text-[#333]">{{ friendsInfo.body }}</view>
</template>
</view>
</view>
<!-- 帮付说明 -->
<message ref="messageRef"></message>
<!-- 支付 -->
<pay ref="payRef" />
<loading-page :loading="loading"></loading-page>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { t } from '@/locale'
import { img, redirect, getToken,handleOnloadParams,goback } from '@/utils/common';
import { onLoad, onShow,onHide,onUnload } from '@dcloudio/uni-app'
import { topTabar } from '@/utils/topTabbar';
import { getFriendspayInfo } from '@/app/api/friendspay'
import Message from '@/app/pages/friendspay/components/message.vue'
import { useLogin } from '@/hooks/useLogin'
import { onPageScroll } from '@dcloudio/uni-app';
/********* 自定义头部 - start ***********/
const topTabarObj = topTabar()
let topTabbarData = topTabarObj.setTopTabbarParam({ title: '' })
/********* 自定义头部 - end ***********/
const loading = ref<boolean>(true);
const tradeId = ref<number>(0);
const tradeType = ref<string>('');
const friendsInfo = ref<any>({})
const operateLoading = ref(false)
const firstCall = ref<boolean>(true)
const timeOut: any = ref(null)
onLoad((option: any) =>{
// #ifdef MP-WEIXIN
//
option = handleOnloadParams(option);
// #endif
tradeId.value = option.id || 0;
tradeType.value = option.type || '';
})
onShow(()=>{
if(tradeId.value && tradeType.value){
getFriendspayInfoFn(tradeType.value, tradeId.value)
}
})
onHide(()=>{
if(timeOut.value) {
clearTimeout(timeOut.value);
timeOut.value = null;
}
})
onUnload(()=>{
if(timeOut.value) {
clearTimeout(timeOut.value);
timeOut.value = null;
}
})
const getFriendspayInfoFn = (tradeType : string, tradeId : number) => {
if (firstCall.value) { //
loading.value = true;
firstCall.value = false; // false
}
getFriendspayInfo(tradeType, tradeId).then((res: any) => {
friendsInfo.value = res.data
uni.setNavigationBarTitle({
title: friendsInfo.value.config.pay_page_name
})
topTabbarData = topTabarObj.setTopTabbarParam({ title: friendsInfo.value.config.pay_page_name })
loading.value = false
if( friendsInfo.value.status != 2 && friendsInfo.value.status != 1 && friendsInfo.value.status != -1){
// 3
timeOut.value = setTimeout(() => {
getFriendspayInfoFn(tradeType, tradeId)
}, 1000 * 3)
}else{
clearTimeout(timeOut.value);
timeOut.value = null;
}
}).catch(()=>{
if(timeOut.value) {
clearTimeout(timeOut.value);
timeOut.value = null;
}
loading.value = false
let parameter = {
title: '未找到帮付订单信息',
url: '/app/pages/index/index',
mode: 'reLaunch'
};
goback(parameter)
})
}
//
const messageRef = ref<any>(null);
const handleMessage = () => {
messageRef.value.open(friendsInfo.value.config)
}
const payRef = ref()
const save = () =>{
if(getToken()){
payRef.value?.open(friendsInfo.value.trade_type, friendsInfo.value.trade_id, '/app/pages/index/index', 'friendspay')
} else {
useLogin().setLoginBack({
url: '/app/pages/friendspay/money',
param: { id: friendsInfo.value.trade_id, type: friendsInfo.value.trade_type }
})
}
}
</script>
<style lang="scss" scoped>
.border-color{
border-color: rgba(255, 255, 255, 0.7);
}
.message{
&::after{
content: '';
width: 16rpx;
height: 16rpx;
background-color: #fe0708;
border: solid 1rpx transparent;
border-top-color: #fff;
border-left-color: #fff;
border-top-left-radius:4rpx;
position: absolute;
left: 50%;
top: 0;
transform: translateX(-50%) translateY(-50%) rotate(45deg);
}
}
</style>

View File

@ -0,0 +1,261 @@
<template>
<view :style="themeColor()">
<view class="bg-[var(--page-bg-color)] min-h-screen overflow-hidden" v-if="Object.keys(friendsInfo).length && !loading">
<view :style="{background: 'url(' + img('static/resource/images/app/friendpay_bg.png') + ') left bottom /100% no-repeat'}" class="pb-[168rpx] overflow-hidden">
<!-- #ifdef MP-WEIXIN -->
<view class="sticky top-0 left-0 right-0 z-100">
<top-tabbar :data="topTabbarData" :scrollBool="topTabarObj.getScrollBool()" />
</view>
<!-- #endif -->
<view class="mt-[20rpx] flex flex-col items-center">
<u-avatar :src="img(friendsInfo.member.headimg)" size="50" leftIcon="none" :default-url="img('static/resource/images/default_headimg.png')" />
<view class="flex items-center mt-[20rpx] text-[#fff] text-[26rpx] leading-[36rpx]">
<text class="font-bold mr-[10rpx] max-w-[250rpx] truncate">{{ friendsInfo.member.nickname }}</text>
<text>发起了订单帮付请求~</text>
</view>
</view>
</view>
<view class="mt-[-128rpx] card-template sidebar-margin mb-[var(--top-m)]">
<view class="text-[24rpx] text-center text-[#333] mb-[10rpx]">{{ t('payMoney') }}</view>
<view class="text-center mb-[50rpx]">
<text class="text-[32rpx] font-500 price-font text-[#FF4142]"></text>
<text class="text-[56rpx] font-bold price-font text-[#FF4142]">{{ parseFloat(friendsInfo.money).toFixed(2).split('.')[0] }}</text>
<text class="text-[32rpx] font-500 price-font text-[#FF4142]">.{{ parseFloat(friendsInfo.money).toFixed(2).split('.')[1] }}</text>
</view>
<view class="px-[20rpx] box-border">
<button class="bg-[#FFB4B1] !text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500" hover-class="none" v-if="friendsInfo.status == 2">{{ t('finish') }}</button>
<button class="bg-[#FFB4B1] !text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500" hover-class="none" v-else-if="friendsInfo.status == -1">{{ t('close') }}</button>
<button class="primary-btn-bg !text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500" hover-class="none" v-else :loading="operateLoading" @click="openShareFn">{{ friendsInfo.config.pay_type_name ? friendsInfo.config.pay_type_name : t('friendPay') }}</button>
</view>
<view class="mt-[20rpx] flex items-baseline justify-center text-[var(--text-color-light9)]" v-if="friendsInfo.status == 2 && JSON.stringify(friendsInfo.trade_info) !== '[]' && friendsInfo.trade_info.detail_url" @click="redirect({url: friendsInfo.trade_info.detail_url })">
<text class="text-[24rpx] mr-[6rpx]">查看订单</text>
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx]"></text>
</view>
</view>
<view class="card-template sidebar-margin mb-[var(--top-m)]">
<view class="flex justify-between items-center mb-[30rpx]">
<view class="text-[30rpx] text-[#333] font-500">{{ t('friendPayOrderInfo') }}</view>
<view class="text-[#666] leading-[1]" @click="handleMessage" v-if="friendsInfo.config.pay_explain_switch">
<text class="mr-[8rpx] text-[24rpx]">{{ friendsInfo.config.pay_explain_title }}</text>
<text class="nc-iconfont nc-icon-jichuxinxiV6xx text-[26rpx]"></text>
</view>
</view>
<template v-if="JSON.stringify(friendsInfo.trade_info) !== '[]'">
<template v-if="friendsInfo.trade_info.item_list.length">
<view class="border-0 border-solid border-b-[1rpx] border-[#f6f6f6] mb-[20rpx]">
<view v-for="(item, index) in friendsInfo.trade_info.item_list" class="flex justify-between mb-[30rpx]">
<view class="w-[170rpx] h-[170rpx] rounded-[var(--goods-rounded-big)] overflow-hidden flex-shrink-0">
<u--image class="overflow-hidden" radius="var(--goods-rounded-big)" width="170rpx" height="170rpx" :src="img(item.item_image ? item.item_image : '')" model="aspectFill">
<template #error>
<image class="w-[170rpx] h-[170rpx] rounded-[var(--goods-rounded-big)] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill" />
</template>
</u--image>
</view>
<view class="ml-[20rpx] flex flex-1 flex-col justify-between">
<view>
<view class="text-[28rpx] using-hidden leading-[40rpx] text-[#333]">{{ item.item_name }}</view>
<view class="text-[24rpx] mt-[14rpx] text-[var(--text-color-light9)] using-hidden leading-[28rpx]" v-if="item.item_sub_name"> {{ item.item_sub_name }} </view>
</view>
<view class="flex justify-between items-baseline">
<view class="price-font text-[#FF4142]">
<text class="text-[24rpx]"></text>
<text class="text-[40rpx] font-500">{{ parseFloat(item.item_price).toFixed(2).split('.')[0] }}</text>
<text class="text-[24rpx] font-500">.{{ parseFloat(item.item_price).toFixed(2).split('.')[1] }}</text>
</view>
<text class="text-right text-[26rpx]">x{{ item.item_num }}</text>
</view>
</view>
</view>
</view>
<view class="text-[26rpx] text-right">{{ friendsInfo.trade_info.item_total }}</view>
</template>
</template>
<template v-else>
<view class="text-[28rpx] leading-[40rpx] text-[#333]">{{ friendsInfo.body }}</view>
</template>
</view>
<share-poster ref="sharePosterRef" posterType="friendspay" :posterId="friendsInfo.poster_id" :posterParam="posterParam" :copyUrl="copyUrl" :copyUrlParam="copyUrlParam" />
<!-- 帮付说明 -->
<message ref="messageRef"></message>
</view>
<loading-page :loading="loading"></loading-page>
</view>
</template>
<script lang="ts" setup>
import { ref, computed, nextTick } from 'vue';
import { t } from '@/locale'
import { img, redirect, goback} from '@/utils/common';
import { onLoad, onShow, onHide, onUnload } from '@dcloudio/uni-app'
import { getFriendspayInfo } from '@/app/api/friendspay'
import { useShare }from '@/hooks/useShare'
import useMemberStore from '@/stores/member'
import { topTabar } from '@/utils/topTabbar';
import sharePoster from '@/components/share-poster/share-poster.vue'
import Message from '@/app/pages/friendspay/components/message.vue'
import { onPageScroll } from '@dcloudio/uni-app';
/********* 自定义头部 - start ***********/
const topTabarObj = topTabar()
let topTabbarData = topTabarObj.setTopTabbarParam({ title: '' })
/********* 自定义头部 - end ***********/
const loading = ref<boolean>(true);
const operateLoading = ref(false)
const tradeId = ref<number>(0);
const tradeType = ref<string>('');
const friendsInfo = ref<any>({})
const firstCall = ref<boolean>(true)
const timeOut: any = ref(null)
//
const{setShare} = useShare()
//
const memberStore = useMemberStore()
const userInfo = computed(() => memberStore.info)
onLoad((option: any) =>{
tradeId.value = option.id || 0;
tradeType.value = option.type || '';
})
onShow(()=>{
if(tradeId.value && tradeType.value){
getFriendspayInfoFn(tradeType.value, tradeId.value)
}
})
onHide(()=>{
if(timeOut.value) {
clearTimeout(timeOut.value);
timeOut.value = null;
}
})
onUnload(()=>{
if(timeOut.value) {
clearTimeout(timeOut.value);
timeOut.value = null;
}
})
const getFriendspayInfoFn = (tradeType : string, tradeId : number) => {
if (firstCall.value) { //
loading.value = true;
firstCall.value = false; // false
}
getFriendspayInfo(tradeType, tradeId).then((res: any) => {
friendsInfo.value = res.data
loading.value = false
uni.setNavigationBarTitle({
title: friendsInfo.value.config.pay_page_name
})
topTabbarData = topTabarObj.setTopTabbarParam({ title: friendsInfo.value.config.pay_page_name })
// - start
let link = '';
// #ifdef H5
let pathName = location.pathname;
let packageArr: any = ['/app/', '/addon/'];
for (let i = 0; i < packageArr.length; i++) {
if (pathName.indexOf(packageArr[i]) != -1) {
pathName = pathName.substr(0, pathName.indexOf(packageArr[i]));
}
}
link = location.origin + pathName + `/app/pages/friendspay/money?id=${friendsInfo.value.trade_id}&type=${friendsInfo.value.trade_type}`;
// #endif
let share: any = {
desc: friendsInfo.value.config.pay_leave_message,
path: `/app/pages/friendspay/money?id=${friendsInfo.value.trade_id}&type=${friendsInfo.value.trade_type}`,
link
}
if(friendsInfo.value.member){
let name = friendsInfo.value.member.nickname
name = name.length > 15 ? name = name.substring(0, 15) + '...' : name
share.title = `${name}希望你帮他付${friendsInfo.value.money}`
}
if(JSON.stringify(friendsInfo.value.trade_info) !== '[]' && friendsInfo.value.trade_info.item_list.length){
share.url = friendsInfo.value.trade_info.item_list[0].item_image
}
setShare({
wechat: {
...share
},
weapp: {
...share
}
});
// - end
copyUrlFn();
nextTick(() => {
setTimeout(() => {
if(sharePosterRef.value) {
posterParam.id = friendsInfo.value.trade_id;
posterParam.type = friendsInfo.value.trade_type;
if (userInfo.value && userInfo.value.member_id) posterParam.member_id = userInfo.value.member_id;
sharePosterRef.value.loadPoster();
}
}, 400)
})
if( friendsInfo.value.status != 2 && friendsInfo.value.status != 1 && friendsInfo.value.status != -1){
// 3
timeOut.value = setTimeout(() => {
getFriendspayInfoFn(tradeType, tradeId)
}, 1000 * 3)
}else{
clearTimeout(timeOut.value);
timeOut.value = null;
}
}).catch((err: any) => {
if(timeOut.value) {
clearTimeout(timeOut.value);
timeOut.value = null;
}
loading.value = false
let parameter = {
title: '未找到帮付订单信息',
url: '/app/pages/index/index',
mode: 'reLaunch'
};
goback(parameter)
});
}
//
const messageRef = ref<any>(null);
const handleMessage = () => {
messageRef.value.open(friendsInfo.value.config)
}
/************* 分享海报-start **************/
const sharePosterRef: any = ref(null);
const copyUrl = ref('/app/pages/friendspay/money')
const copyUrlParam = ref('');
let posterParam: any = {};
//
const copyUrlFn = ()=>{
copyUrlParam.value = '?id='+ friendsInfo.value.trade_id;
copyUrlParam.value += '&type=' + friendsInfo.value.trade_type;
}
const openShareFn = ()=>{
posterParam.id = friendsInfo.value.trade_id;
posterParam.type = friendsInfo.value.trade_type;
if (userInfo.value && userInfo.value.member_id) posterParam.member_id = userInfo.value.member_id;
sharePosterRef.value.openShare()
}
/************* 分享海报-end **************/
</script>
<style lang="scss" scoped>
</style>

View File

@ -36,6 +36,8 @@
import diyGroup from '@/addon/components/diy/group/index.vue'
import fixedGroup from '@/addon/components/fixed/group/index.vue'
uni.hideTabBar() // tabbar
const diy = useDiy({
name: 'DIY_INDEX'
})
@ -67,7 +69,7 @@
//
diy.onHide();
//
diy.onUnload();
@ -92,4 +94,4 @@
}
/* #endif */
}
</style>
</style>

View File

@ -36,6 +36,8 @@
import fixedGroup from '@/addon/components/fixed/group/index.vue'
import useMemberStore from '@/stores/member'
uni.hideTabBar() // tabbar
//
const memberStore = useMemberStore()
const userInfo = computed(() => memberStore.info)
@ -74,7 +76,7 @@
//
diy.onHide();
//
diy.onUnload();
@ -99,4 +101,4 @@
}
/* #endif */
}
</style>
</style>

View File

@ -178,13 +178,13 @@
const changeOperationType = (type: string) => {
// #ifdef H5
// if (type == 'sweepCode' && !isWeixinBrowser()) {
// uni.showToast({
// title: 'H5',
// icon: 'none'
// });
// return;
// }
if (type == 'sweepCode' && !isWeixinBrowser()) {
uni.showToast({
title: 'H5端不支持扫码核销',
icon: 'none'
});
return;
}
// #endif
operationType.value = type;
}

View File

@ -1,6 +1,6 @@
<template>
<u-popup :show="show" @close="show = false" mode="center" :round="10" :closeable="true" :safeAreaInsetBottom="false" zIndex="10086">
<view @touchmove.prevent.stop class="max-w-[550rpx] w-[550rpx] box-border">
<view @touchmove.prevent.stop class="max-w-[600rpx] w-[600rpx] box-border">
<view class="text-center py-[var(--pad-top-m)] text-[32rpx] font-500 leading-[46rpx]">{{t('bindMobile')}}</view>
<view class="px-[var(--pad-sidebar-m)] pb-[var(--pad-top-m)]">
<u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef">
@ -18,7 +18,7 @@
</view>
<view v-if="config.agreement_show" class="flex items-center mt-[30rpx] pl-[10rpx] py-[10rpx]" @click.stop="agreeChange">
<u-checkbox-group @change="agreeChange">
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="24rpx" :customStyle="{ 'marginTop': '4rpx' }"/>
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="28rpx"/>
</u-checkbox-group>
<view class="text-[24rpx] text-[var(--text-color-light6)] flex items-center flex-wrap">
<text>{{ t('agreeTips') }}</text>

View File

@ -1,6 +1,6 @@
<template>
<u-popup :show="show" :round="10" @close="handleClose" :closeable="true" bgColor="#fff" zIndex="10081" :closeOnClickOverlay="false">
<view class="flex flex-col h-[75vh] popup-common" v-if="payInfo" @touchmove.prevent.stop>
<view class="flex flex-col h-[65vh] popup-common" v-if="payInfo" @touchmove.prevent.stop>
<view class="head">
<view class="title">
{{ t('pay.payTitle') }}
@ -58,6 +58,17 @@
uni.showToast({ title: t('pay.notHavePayType'), icon: 'none' })
return
}
if(type.value == 'friendspay'){
redirect({
url: '/app/pages/friendspay/share',
param: {
id: payInfo.value?.trade_id,
type: payInfo.value?.trade_type,
},
mode: 'redirectTo'
})
return false
}
if (loading.value) return
loading.value = true
@ -160,14 +171,21 @@
}
})
const repeat = ref(false)
const open = (tradeType : string, tradeId : number, payReturn: string = '') => {
const open = (tradeType : string, tradeId : number, payReturn: string = '', scene: string = '') => {
if (repeat.value) return
repeat.value = true
//
uni.setStorageSync('payReturn', encodeURIComponent(payReturn))
getPayInfo(tradeType, tradeId).then((res: any) => {
//
const obj: any = {}
if(scene){
obj.scene = scene
}
getPayInfo(tradeType, tradeId, obj).then((res: any) => {
let { data } = res
payInfo.value = data
@ -188,11 +206,12 @@
})
}
const emits = defineEmits(['close','confirm'])
const toPayResult = ()=> {
emits('confirm')
redirect({ url: '/app/pages/pay/result', param: { trade_type: payInfo.value?.trade_type, trade_id: payInfo.value?.trade_id }, mode: 'redirectTo' })
}
const emits = defineEmits(['close'])
const handleClose = () => {
uni.removeStorageSync('paymenting')

View File

@ -17,7 +17,7 @@
</view>
<view class="share-box">
<button class="share-btn" :plain="true" @click="saveGoodsPoster()">
<button class="share-btn" :plain="true" @click="savePoster()">
<view class="text-[#07c160] iconfont iconpengyouquan"></view>
<text>保存海报</text>
</button>
@ -105,7 +105,7 @@ const copyUrl = () => {
const openShare = ()=>{
sharePopupShow.value = true
goodsPosterShowFn();
loadPoster();
}
//
@ -113,33 +113,39 @@ const isPosterAnimation = ref(false)
const isPosterImg = ref(false)
//
const poster = ref('');
const goodsPosterShowFn = () => {
isPosterAnimation.value = true;
isPosterImg.value = false;
let obj = {
id: props.posterId,
type: props.posterType,
param: props.posterParam
}
let startTime = Date.parse(new Date());
getPoster(obj).then((res:any) => {
poster.value = res.data && img(res.data) || '';
const loadPoster = () => {
if(poster.value){
//
isPosterAnimation.value = false;
isPosterImg.value = true;
}else {
isPosterAnimation.value = true;
isPosterImg.value = false;
let obj = {
id: props.posterId,
type: props.posterType,
param: props.posterParam
}
let startTime = Date.parse(new Date());
getPoster(obj).then((res: any) => {
poster.value = res.data && img(res.data) || '';
let endTime = Date.parse(new Date());
let time = endTime-startTime;
let periodTime = 2200;
if(time < periodTime){
setTimeout(()=>{
let endTime = Date.parse(new Date());
let time = endTime - startTime;
let periodTime = 2200;
if (time < periodTime) {
setTimeout(() => {
isPosterAnimation.value = false;
isPosterImg.value = true;
}, (periodTime - time))
} else {
isPosterAnimation.value = false;
isPosterImg.value = true;
},(periodTime-time))
}else{
isPosterAnimation.value = false;
isPosterImg.value = true;
}
}).catch(() => {
sharePopupClose();
})
}
}).catch(() => {
sharePopupClose();
})
}
}
const show = ref(false);
@ -149,7 +155,7 @@ const closeDialog = ()=> {
// #ifdef MP || APP-PLUS
//
const saveGoodsPoster = () => {
const savePoster = () => {
let url = img(poster.value);
uni.downloadFile({
url: url,
@ -205,12 +211,12 @@ const sharePopupClose = ()=>{
sharePopupShow.value = false;
isPosterAnimation.value = false;
isPosterImg.value = false;
console.log('sharePopupClose 取消分享');
emits('close');
}
defineExpose({
openShare
openShare,
loadPoster
})
</script>
<style lang="scss" scoped>

View File

@ -41,7 +41,7 @@
</view>
<!-- 解决fixed定位后导航栏塌陷的问题 -->
<view v-if="props.isFill" class="u-navbar-placeholder" :style="{ width: '100%', paddingTop: placeholderHeight + 'px' }"></view>
<view v-if="isFill" class="u-navbar-placeholder" :style="{ width: '100%', paddingTop: placeholderHeight + 'px' }"></view>
</view>
</template>
@ -88,9 +88,22 @@ const props = defineProps({
default: true
}
})
// -
const isFill = computed(() => {
let bool = true;
if(imageAdsSameScreen.value) {
bool = false;
}else {
bool = props.isFill;
}
return bool;
});
const data = computed(() => {
return props.data;
});
const topStatusBarData = computed(() => {
if(props.data && props.data.topStatusBar)
return props.data.topStatusBar;
@ -243,6 +256,7 @@ const navbarPlaceholderHeight = () => {
locationVal.onLoad();
locationVal.init();
/************** 定位-end ****************/
let imageAdsSameScreen = ref(false);
onMounted(() => {
navbarPlaceholderHeight();
if (pages.length > 1) {
@ -253,6 +267,9 @@ onMounted(() => {
}
//
locationVal.refresh();
//
imageAdsSameScreen.value = uni.getStorageSync('imageAdsSameScreen') || false;
});
// onShow

View File

@ -233,7 +233,30 @@ export function useLogin() {
// 如果当前在登录中间页,那么要跳转到首页
if (url.indexOf('app/pages/auth/index') != -1) {
url = url.replace('app/pages/auth/index', 'app/pages/index/index')
let loginBack = uni.getStorageSync('loginBack');
if (loginBack) {
url = url.replace('app/pages/auth/index', loginBack.url.substr(1))
if (loginBack.param) {
if (url.indexOf('?') != -1) {
for (let key in loginBack.param) {
url += `&${ key }=${ loginBack.param[key] }`;
}
} else {
let count = 0;
for (let key in loginBack.param) {
if (count == 0) {
url += `?${ key }=${ loginBack.param[key] }`;
} else {
url += `&${ key }=${ loginBack.param[key] }`;
}
count++;
}
}
}
} else {
url = url.replace('app/pages/auth/index', 'app/pages/index/index')
}
} else {
let query: any = urlDeconstruction(location.href).query
query.code && (delete query.code)

View File

@ -93,6 +93,7 @@ export const useShare = () => {
route: '/' + currRoute(),
params: JSON.stringify(currShareRoute().params)
}).then((res: any) => {
let data = res.data;
// #ifdef H5
@ -132,6 +133,7 @@ export const useShare = () => {
...options
}
})
}
// 小程序分享,分享到朋友圈

View File

@ -36,6 +36,8 @@
"pages.verify.verify": "核销",
"pages.verify.detail": "核销详情",
"pages.verify.record": "核销记录",
"pages.friendspay.share": "找朋友帮忙付",
"pages.friendspay.money":"",
"pages.webview.index": "",
"tourism.pages.way.list": "线路列表",
"tourism.pages.way.detail": "线路详情",

View File

@ -34,7 +34,7 @@
"bind": "绑定",
"binding": "绑定中",
"bindMobile": "绑定手机号",
"agreeTips": "阅读并同意",
"agreeTips": "我已阅读并同意",
"pleaseAgree": "请勾选已阅读并同意",
"weixinUserAuth": "一键绑定",
"mobileQuickLogin": "手机号快捷登录",

View File

@ -298,6 +298,25 @@
"style": {
"navigationBarTitleText": "%pages.weapp.order_shipping%"
}
},
{
"path": "app/pages/friendspay/share",
"style": {
// #ifndef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.friendspay.share%"
},
"needLogin": true
},
{
"path": "app/pages/friendspay/money",
"style": {
// #ifndef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.friendspay.money%"
}
}
],
"subPackages": [

View File

@ -474,4 +474,13 @@ button[type='primary'],uni-button[type='primary']{
.mescroll-upwarp{
opacity: 0;
}
/******************** mescroll state **********************/
/******************** mescroll end **********************/
/******************** u-switch state **********************/
// 解决u-switch在小程序上点击会出现高亮的情况
/* #ifdef MP */
.u-switch{
cursor: inherit !important;
}
/* #endif */
/******************** u-switch end **********************/

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "nc-iconfont"; /* Project id 4567203 */
src: url('//at.alicdn.com/t/c/font_4567203_unxj5bqsj6o.woff2?t=1732704100572') format('woff2'),
url('//at.alicdn.com/t/c/font_4567203_unxj5bqsj6o.woff?t=1732704100572') format('woff'),
url('//at.alicdn.com/t/c/font_4567203_unxj5bqsj6o.ttf?t=1732704100572') format('truetype');
src: url('//at.alicdn.com/t/c/font_4567203_8cgr9qgefz9.woff2?t=1734663182190') format('woff2'),
url('//at.alicdn.com/t/c/font_4567203_8cgr9qgefz9.woff?t=1734663182190') format('woff'),
url('//at.alicdn.com/t/c/font_4567203_8cgr9qgefz9.ttf?t=1734663182190') format('truetype');
}
.nc-iconfont {
@ -13,6 +13,22 @@
-moz-osx-font-smoothing: grayscale;
}
.nc-icon-daifujineV6xx:before {
content: "\e83b";
}
.nc-icon-daifuliuyanV6xx:before {
content: "\e83a";
}
.nc-icon-jichuxinxiV6xx:before {
content: "\e838";
}
.nc-icon-dianpuzhandianV6xx:before {
content: "\e836";
}
.nc-icon-gouwucheV6xx6:before {
content: "\e835";
}
@ -117,6 +133,10 @@
content: "\e7b8";
}
.nc-icon-wodeV6mm3:before {
content: "\e7b7";
}
.nc-icon-a-shaixuan-36V6xx-36:before {
content: "\e7b3";
}

View File

@ -106,6 +106,8 @@ const loadShare = () => {
'addon/shop_giftcard/pages/detail',
'addon/shop_giftcard/pages/give',
'app/pages/index/diy',
'app/pages/friendspay/share',
'app/pages/friendspay/money'
]
if (currRoute()) {
if (!shareWhiteList.includes(currRoute() || '')) setShare()

View File

@ -28,6 +28,11 @@ export default {
state.currRoute = route
})
let loginBack = uni.getStorageSync('loginBack');
if (loginBack && loginBack.url == '/' + route) {
this.query = loginBack.param
}
redirectInterceptor({
path: route,
query: this.query

View File

@ -64,7 +64,7 @@ class Wechat {
});
})
}
/**
*
* @param {Object} callback