更新uni-app

This commit is contained in:
全栈小学生 2023-05-20 18:12:41 +08:00
parent db93e399eb
commit 8a600afd4f
60 changed files with 2310 additions and 757 deletions

View File

@ -1,37 +1,40 @@
<script setup lang="ts">
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
import manifest from '@/manifest.json'
import { redirectInterceptor, launchInterceptor } from '@/utils/interceptor'
import { getToken, isWeixinBrowser } from '@/utils/common'
import { getToken, isWeixinBrowser, urlDeconstruction } from '@/utils/common'
import useMemberStore from '@/stores/member'
import useConfigStore from '@/stores/config'
import { useLogin } from '@/hooks/useLogin'
import { language } from '@/locale'
// #ifdef H5
if (import.meta.env.VITE_APP_DEBUG) { new window.VConsole() }
// #endif
onLaunch(async (data) => {
//
launchInterceptor()
//
redirectInterceptor()
// #ifdef H5
uni.getSystemInfoSync().platform == 'ios' && (uni.setStorageSync('initUrl', location.href))
// #endif
const configStore = useConfigStore()
configStore.getTabbarConfig()
await configStore.getLoginConfig()
// tabbar
uni.hideTabBar()
// #ifdef H5
uni.getSystemInfoSync().platform == 'ios' && (uni.setStorageSync('initUrl', location.href))
// #endif
//
if (getToken()) {
const memberStore = useMemberStore()
await memberStore.setToken(getToken())
}
if (!getToken()) {
const login = useLogin()
//
@ -40,10 +43,18 @@
// #endif
// #ifdef H5
if (isWeixinBrowser()) {
data.query.code ? login.authLogin(data.query.code) : login.getAuthCode()
data.query.code ? login.authLogin(data.query.code) : login.getAuthCode('snsapi_userinfo')
}
// #endif
}
//
// #ifdef H5
window.addEventListener("popstate", function(e) {
const path = '/' + location.pathname.replace(manifest.h5.router.base, '')
language.loadLocaleMessages(path, uni.getLocale())
}, false);
// #endif
})
onShow(() => {

View File

@ -61,4 +61,11 @@ export function weappLogin(data : AnyObject) {
*/
export function bind(data : AnyObject) {
return request.post('bind', data, { showErrorMessage: true })
}
/**
* 访
*/
export function memberLog(data : AnyObject) {
return request.post('member/log', data)
}

View File

@ -1,40 +1,145 @@
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)
return request.get('member/account/point', data)
}
/**
*
*
*/
export function getBalanceList(data : AnyObject) {
return request.get('member/account/balance', data)
return request.get('member/account/balance', data)
}
/**
*
*/
export function getMoneyList(data : AnyObject) {
return request.get('member/account/money', data)
}
/**
*
*/
export function updateMember(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 createRecharge(data : AnyObject) {
return request.post('order/recharge', data, { showErrorMessage: true })
return request.post('order/recharge', data, { showErrorMessage: true })
}
/**
*
*/
export function getRechargeList(data : AnyObject) {
return request.get('order/recharge', data, { showErrorMessage: true })
}
/**
*
*/
export function getRechargeDetail(id:number) {
return request.get(`order/recharge/${id}`, {}, { showErrorMessage: true })
}
/**
*
*/
export function bindMobile(data : AnyObject) {
return request.put('member/mobile', data, { showErrorMessage: true })
return request.put('member/mobile', data, { showErrorMessage: true })
}
/**
*
*/
export function cashOutTransferType() {
return request.get('member/cash_out/transfertype')
}
/**
*
*/
export function cashOutConfig() {
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 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 getCashoutAccountList(data : AnyObject) {
return request.get(`member/cashout_account`, 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 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 deleteCashoutAccount(accountId: number) {
return request.delete(`member/cashout_account/${accountId}`, { showSuccessMessage: true, showErrorMessage: true })
}
/**
*
*/
export function getCommissionList(data : AnyObject) {
return request.get(`member/account/commission`, data)
}

View File

@ -0,0 +1,20 @@
<template>
<view>
<!-- 扩展组件 -->
</view>
</template>
<script setup lang="ts">
//
import { computed } from 'vue';
import useDiyStore from '@/stores/diy';
const props = defineProps(['component', 'index']);
const diyStore = useDiyStore();
const diyComponent = computed(() => {
if (diyStore.mode == 'decorate') {
return diyStore.value[props.index];
} else {
return props.component;
}
})
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,24 @@
<template>
<view>
演示插件信息自定义组件
</view>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import useDiyStore from '@/stores/diy';
const props = defineProps(['component', 'index']);
const diyStore = useDiyStore();
const diyComponent = computed(() => {
if (diyStore.mode == 'decorate') {
return diyStore.value[props.index];
} else {
return props.component;
}
})
</script>
<style></style>

View File

@ -0,0 +1,24 @@
<template>
<view>
演示插件文本自定义组件
</view>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import useDiyStore from '@/stores/diy';
const props = defineProps(['component', 'index']);
const diyStore = useDiyStore();
const diyComponent = computed(() => {
if (diyStore.mode == 'decorate') {
return diyStore.value[props.index];
} else {
return props.component;
}
})
</script>
<style></style>

View File

@ -6,35 +6,41 @@
<!-- 标题 -->
<template v-if="component.componentName == 'Text'">
<diy-text :component="component" :index="index"></diy-text>
<diy-system-text :component="component" :index="index"></diy-system-text>
</template>
<!-- 图片广告 -->
<template v-if="component.componentName == 'ImageAds'">
<diy-image-ads :component="component" :index="index"></diy-image-ads>
<diy-system-image-ads :component="component" :index="index"></diy-system-image-ads>
</template>
<!-- 图文导航 -->
<template v-if="component.componentName == 'GraphicNav'">
<diy-graphic-nav :component="component" :index="index"></diy-graphic-nav>
<diy-system-graphic-nav :component="component" :index="index"></diy-system-graphic-nav>
</template>
<!-- 文章 -->
<template v-if="component.componentName == 'Article'">
<diy-article :component="component" :index="index"></diy-article>
<diy-system-article :component="component" :index="index"></diy-system-article>
</template>
<!-- 辅助空白 -->
<template v-if="component.componentName == 'HorzBlank'">
<diy-horz-blank :component="component" :index="index"></diy-horz-blank>
<diy-system-horz-blank :component="component" :index="index"></diy-system-horz-blank>
</template>
<!-- 会员信息 -->
<template v-if="component.componentName == 'MemberInfo'">
<diy-member-info :component="component" :index="index"></diy-member-info>
<diy-system-member-info :component="component" :index="index"></diy-system-member-info>
</template>
<!-- 自定义扩展组件 -->
<template v-if="systemComponent.indexOf(component.componentName) == -1">
<diy-comp-extend :component="component" :index="index"></diy-comp-extend>
</template>
</view>
<template v-if="diyStore.mode == ''">
<view class="pt-[20rpx]"></view>
<tabbar />
</template>
</view>
@ -43,7 +49,7 @@
<script lang="ts" setup>
import useDiyStore from '@/stores/diy';
import { onMounted, nextTick, computed } from 'vue';
import { onMounted, nextTick, computed, ref } from 'vue';
import Sortable from 'sortablejs';
import { range } from 'lodash-es';
@ -59,6 +65,9 @@
}
})
//
const systemComponent = ref(['Text', 'ImageAds', 'GraphicNav', 'Article', 'HorzBlank', 'MemberInfo'])
onMounted(() => {
// #ifdef H5
if (diyStore.mode == 'decorate') {

View File

@ -1,120 +0,0 @@
<template>
<view>
<!-- #ifdef MP-WEIXIN -->
<u-navbar :placeholder="true" bgColor="var(--primary-color)" titleStyle="color: #fff">
<template #left>
</template>
</u-navbar>
<!-- #endif -->
<view class="bg-primary" v-if="info">
<view class="flex p-[30rpx]">
<u-avatar :src="img(info.headimg)" size="60" leftIcon="none" @click="clickAvatar"></u-avatar>
<view class="flex-1 w-0 mx-[20rpx] flex justify-center flex-col">
<view class="text-white font-bold text-lg">{{ info.nickname }}</view>
<view></view>
</view>
<view class="flex items-center">
<app-link url="/pages/setting/index">
<text class="iconfont iconshezhi text-white text-lg ml-[10rpx]"></text>
</app-link>
</view>
</view>
<view class="flex m-[30rpx] mb-0 py-[30rpx] bg-white rounded-lg rounded-b-none">
<view class="flex-1 text-center">
<view class="font-bold">
<app-link url="/pages/member/point">{{ parseInt(info.point) }}</app-link>
</view>
<view class="text-sm mt-[10rpx]">
<app-link url="/pages/member/point">{{ t('point') }}</app-link>
</view>
</view>
<view class="flex-1 text-center">
<view class="font-bold">
<app-link url="/pages/member/balance">{{ moneyFormat(info.balance) }}</app-link>
</view>
<view class="text-sm mt-[10rpx]">
<app-link url="/pages/member/balance">{{ t('balance') }}</app-link>
</view>
</view>
</view>
<!-- #ifdef MP-WEIXIN -->
<information-filling ref="infoFill"></information-filling>
<!-- #endif -->
</view>
<view v-else class="flex p-[30rpx] bg-primary" @click="toLogin">
<u-avatar src="" size="60"></u-avatar>
<view class="flex-1 w-0 mx-[20rpx] flex justify-center flex-col">
<view class="text-white font-bold text-lg">{{ t('login') }}/{{ t('register') }}</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue'
import useMemberStore from '@/stores/member'
import { useLogin } from '@/hooks/useLogin'
import { img, isWeixinBrowser, redirect, urlDeconstruction, moneyFormat } from '@/utils/common'
import { t } from '@/locale'
import { wechatSync } from '@/api/system'
import useDiyStore from '@/stores/diy'
const props = defineProps(['component', 'index']);
const diyStore = useDiyStore();
const diyComponent = computed(() => {
if (diyStore.mode == 'decorate') {
return diyStore.value[props.index];
} else {
return props.component;
}
})
const memberStore = useMemberStore()
const { query } = urlDeconstruction(location.href)
if (query.code && isWeixinBrowser()) {
wechatSync({ code: query.code }).then(res => {
memberStore.getMemberInfo()
})
}
const info = computed(() => {
//
if (diyStore.mode == 'decorate') {
return {
headimg: '',
nickname: '昵称',
balance: 0,
point: 0
}
} else {
return memberStore.info;
}
})
const toLogin = () => {
useLogin().setLoginBack({ url: '/pages/member/index' })
}
const infoFill = ref(false)
const clickAvatar = () => {
// #ifdef MP-WEIXIN
infoFill.value.show = true
// #endif
// #ifdef H5
if (isWeixinBrowser()) {
useLogin().getAuthCode('snsapi_userinfo')
} else {
redirect({ url: '/pages/member/personal' })
}
// #endif
}
</script>
<style>
</style>

View File

@ -1,12 +1,12 @@
<template>
<view class="bg-white">
<view v-if="diyComponent.layout == 'vertical'" class="graphic-nav py-[20rpx] px-[30rpx] box-border relative">
<div v-if="diyComponent.navTitle"
<view class="bg-[#F5F6F8]">
<view v-if="diyComponent.layout == 'vertical'" class="graphic-nav px-[32rpx] bg-white rounded-[20rpx] box-border relative m-[30rpx]">
<!-- <div v-if="diyComponent.navTitle"
class="py-2 border-solid border-b border-t-0 border-l-0 border-r-0 border-gray-200">
{{diyComponent.navTitle}}
</div>
</div> -->
<view
class="graphic-nav-item flex items-center justify-between py-2 border-solid border-l-0 border-r-0 border-b-0 border-gray-200"
class="graphic-nav-item flex items-center justify-between py-2 border-gray-200"
v-for=" (item, index) in diyComponent.list" :key="item.id"
:class="[index == 0 ? 'border-t-0':'border-t']" @click="redirectTo(item.link)">

View File

@ -0,0 +1,174 @@
<template>
<view>
<!-- #ifdef MP-WEIXIN -->
<u-navbar :placeholder="true" bgColor="var(--primary-color)" titleStyle="color: #fff">
<template #left>
</template>
</u-navbar>
<!-- #endif -->
<view class="pt-[34rpx] member-info">
<view v-if="info" class="flex ml-[32rpx] mr-[52rpx] items-center relative">
<!-- clickAvatar 唤起获取微信 -->
<u-avatar :src="img(info.headimg)" size="60" leftIcon="none" @click="clickAvatar"></u-avatar>
<view class="ml-[22rpx]">
<view class="text-[#222222] truncate w-[430rpx] font-bold text-lg">{{ info.nickname }}</view>
<view class="text-[#696B70] text-[24rpx] mt-[10rpx]">{{ t('memberLanguage') }}</view>
</view>
<view class="set-icon flex items-center absolute right-0 top-2">
<app-link url="/pages/setting/index">
<text class="iconfont iconshezhi text-[#000] text-[1.6rem] ml-[10rpx]"></text>
</app-link>
</view>
</view>
<view v-else class="flex ml-[32rpx] mr-[52rpx] items-center relative" @click="toLogin">
<u-avatar src="" size="60"></u-avatar>
<view class="ml-[22rpx]">
<view class="text-[#222222] font-bold text-lg">{{ t('login') }}/{{ t('register') }}</view>
<view class="text-[#696B70] text-[24rpx] mt-[10rpx]">{{ t('memberLanguage') }}</view>
</view>
<view class="set-icon flex items-center absolute right-0 top-2">
<app-link url="/pages/setting/index">
<text class="iconfont iconshezhi text-[#000] text-[1.6rem] ml-[10rpx]"></text>
</app-link>
</view>
</view>
<view class="flex m-[30rpx] mb-0 py-[30rpx] ">
<view class="flex-1 text-center">
<view class="font-bold">
<app-link :url="(info ? '/pages/member/point' : '')">{{ parseInt(info?.point) || 0 }}</app-link>
</view>
<view class="text-sm mt-[10rpx]">
<app-link :url="(info ? '/pages/member/point' : '')">{{ t('point') }}</app-link>
</view>
</view>
<view class="flex-1 text-center">
<view class="font-bold">
<app-link :url="(info ? '/pages/member/balance' : '')">{{ money }}</app-link>
</view>
<view class="text-sm mt-[10rpx]">
<app-link :url="(info ? '/pages/member/balance' : '')">{{ t('balance') }}</app-link>
</view>
</view>
</view>
</view>
<view class="m-[32rpx] flex justify-between p-[32rpx] bg-white rounded-[20rpx]">
<app-link url="/pages/member/personal">
<view>
<view class="w-[60rpx] h-[60rpx] mx-auto">
<image class="w-[60rpx]" :src="img('static/resource/images/diy/m_info.jpg')" mode="widthFix" />
</view>
<view class="text-[24rpx] text-[#333] mt-[18rpx] text-center">{{ t('memberCenter') }}</view>
</view>
</app-link>
<app-link url="/pages/member/balance">
<view>
<view class="w-[60rpx] h-[60rpx] mx-auto">
<image class="w-[60rpx]" :src="img('static/resource/images/diy/m_balance.jpg')"
mode="widthFix" />
</view>
<view class="text-[24rpx] text-[#333] mt-[18rpx] text-center">{{ t('myBalance') }}</view>
</view>
</app-link>
<app-link url="/pages/member/point">
<view>
<view class="w-[60rpx] h-[60rpx] mx-auto">
<image class="w-[60rpx]" :src="img('static/resource/images/diy/m_point.jpg')" mode="widthFix" />
</view>
<view class="text-[24rpx] text-[#333] mt-[18rpx] text-center">{{ t('myPoint') }}</view>
</view>
</app-link>
<app-link>
<view @click="servicePopup = true">
<view class="w-[60rpx] h-[60rpx] mx-auto">
<image class="w-[60rpx]" :src="img('static/resource/images/diy/m_service.jpg')"
mode="widthFix" />
</view>
<view class="text-[24rpx] text-[#333] mt-[18rpx] text-center">{{ t('customerService') }}</view>
</view>
</app-link>
</view>
<!-- #ifdef MP-WEIXIN -->
<information-filling ref="infoFill"></information-filling>
<!-- #endif -->
</view>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue'
import useMemberStore from '@/stores/member'
import { useLogin } from '@/hooks/useLogin'
import { img, isWeixinBrowser, redirect, urlDeconstruction, moneyFormat } from '@/utils/common'
import { t } from '@/locale'
import { wechatSync } from '@/api/system'
import useDiyStore from '@/stores/diy'
const props = defineProps(['component', 'index']);
const diyStore = useDiyStore();
const diyComponent = computed(() => {
if (diyStore.mode == 'decorate') {
return diyStore.value[props.index];
} else {
return props.component;
}
})
const memberStore = useMemberStore()
const { query } = urlDeconstruction(location.href)
if (query.code && isWeixinBrowser()) {
wechatSync({ code: query.code }).then(res => {
memberStore.getMemberInfo()
})
}
const info = computed(() => {
//
if (diyStore.mode == 'decorate') {
return {
headimg: '',
nickname: '昵称',
balance: 0,
point: 0
}
} else {
return memberStore.info;
}
})
const money = computed(() => {
if (info.value) {
let m = parseFloat(info.value.balance) + parseFloat(info.value.money)
return moneyFormat(m.toString());
} else {
return 0;
}
})
const toLogin = () => {
useLogin().setLoginBack({ url: '/pages/member/index' })
}
const infoFill = ref(false)
const clickAvatar = () => {
// #ifdef MP-WEIXIN
infoFill.value.show = true
// #endif
// #ifdef H5
if (isWeixinBrowser()) {
useLogin().getAuthCode('snsapi_userinfo')
} else {
redirect({ url: '/pages/member/personal' })
}
// #endif
}
</script>
<style lang="scss" scoped>
.member-info {
background-image: linear-gradient(#E3F0FF, #F5F6F8)
}
</style>

View File

@ -35,7 +35,7 @@
import { t } from '@/locale'
import useMemberStore from '@/stores/member'
import { img } from '@/utils/common'
import { updateMember } from '@/api/member'
import { modifyMember } from '@/api/member'
import { fetchBase64Image } from '@/api/system'
const show = ref(false)
@ -92,7 +92,7 @@
loading.value = true
//
await updateMember({ field: 'headimg', value: formData.headimg })
await modifyMember({ field: 'headimg', value: formData.headimg })
.then(() => {
memberStore.info.headimg = formData.headimg
})
@ -102,7 +102,7 @@
if (!loading.value) return
//
updateMember({ field: 'nickname', value: formData.nickname })
modifyMember({ field: 'nickname', value: formData.nickname })
.then(() => {
memberStore.info.nickname = formData.nickname
loading.value = false

View File

@ -1,173 +1,178 @@
<template>
<u-popup :show="show" :round="10" @close="handleClose" :closeable="true" bgColor="#fff"
:closeOnClickOverlay="false">
<view class="flex flex-col h-[75vh]" v-if="payInfo">
<view class="head">
<view class="text-center py-[26rpx]">{{ t('pay.payTitle') }}</view>
<view class="flex items-end justify-center w-full text-xl font-bold py-[20rpx]">
<view class="text-base mr-[4rpx]">{{ t('currency') }}</view>
{{ moneyFormat(payInfo.money) }}
</view>
</view>
<scroll-view scroll-y="true" class="flex-1 pt-[20rpx]">
<view class="flex text-sm px-[30rpx] py-[20rpx]">
<view class="text-gray-500">{{ t('pay.orderInfo') }}</view>
<view class="text-right flex-1 pl-[30rpx] truncate">{{ payInfo.body }}</view>
</view>
<view class="mx-[30rpx] py-[10rpx] px-[30rpx] bg-white rounded-md bg-page">
<view
class="pay-item py-[18rpx] flex items-center border-0 border-b border-solid border-[#eee]"
v-for="(item, index) in payInfo.pay_type_list"
:key="index" @click="type = item.key">
<u-image :src="img(item.icon)" width="50rpx" height="50rpx"></u-image>
<view class="flex-1 px-[20rpx] text-sm font-bold">{{ item.name }}</view>
<u-icon name="checkbox-mark" color="var(--primary-color)" v-if="item.key == type"></u-icon>
</view>
</view>
</scroll-view>
<view class="p-[30rpx]">
<u-button type="primary" :loading="loading" :text="t('pay.confirmPay')" shape="circle"
@click="confirmPay"></u-button>
</view>
</view>
</u-popup>
<u-popup :show="show" :round="10" @close="handleClose" :closeable="true" bgColor="#fff"
:closeOnClickOverlay="false">
<view class="flex flex-col h-[75vh]" v-if="payInfo">
<view class="head">
<view class="text-center py-[26rpx]">{{ t('pay.payTitle') }}</view>
<view class="flex items-end justify-center w-full text-xl font-bold py-[20rpx]">
<view class="text-base mr-[4rpx]">{{ t('currency') }}</view>
{{ moneyFormat(payInfo.money) }}
</view>
</view>
<scroll-view scroll-y="true" class="flex-1 pt-[20rpx]">
<view class="flex text-sm px-[30rpx] py-[20rpx]">
<view class="text-gray-500">{{ t('pay.orderInfo') }}</view>
<view class="text-right flex-1 pl-[30rpx] truncate">{{ payInfo.body }}</view>
</view>
<view class="mx-[30rpx] py-[10rpx] px-[30rpx] bg-white rounded-md bg-page">
<block v-if="payInfo.pay_type_list.length">
<view class="pay-item py-[18rpx] flex items-center border-0 border-b border-solid border-[#eee]"
v-for="(item, index) in payInfo.pay_type_list" :key="index" @click="type = item.key">
<u-image :src="img(item.icon)" width="50rpx" height="50rpx"></u-image>
<view class="flex-1 px-[20rpx] text-sm font-bold">{{ item.name }}</view>
<u-icon name="checkbox-mark" color="var(--primary-color)" v-if="item.key == type"></u-icon>
</view>
</block>
<view class="py-[20rpx] text-center text-sm text-gray-subtitle">{{ t('pay.notHavePayType') }}</view>
</view>
</scroll-view>
<view class="p-[30rpx]">
<u-button type="primary" :loading="loading" :text="t('pay.confirmPay')" shape="circle"
@click="confirmPay"></u-button>
</view>
</view>
</u-popup>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { t } from '@/locale'
import { getPayInfo, pay } from '@/api/pay'
import { img, redirect, isWeixinBrowser, moneyFormat } from '@/utils/common'
import wechat from '@/utils/wechat'
import { ref } from 'vue'
import { t } from '@/locale'
import { getPayInfo, pay } from '@/api/pay'
import { img, redirect, isWeixinBrowser, moneyFormat } from '@/utils/common'
import wechat from '@/utils/wechat'
const show = ref(false)
const loading = ref(false)
// #ifdef H5
if (isWeixinBrowser()) wechat.init();
// #endif
const payInfo = ref<AnyObject | null>(null)
const type = ref('')
const show = ref(false)
const loading = ref(false)
/**
* 确认支付
*/
const confirmPay = () => {
if (uni.$u.test.isEmpty(type.value)) {
uni.showToast({ title: t('pay.notHavePayType'), icon: 'none' })
return
}
if (loading.value) return
loading.value = true
const payInfo = ref<AnyObject | null>(null)
const type = ref('')
pay({
out_trade_no: payInfo.value?.out_trade_no,
type: type.value
}).then(res => {
switch (type.value) {
case 'wechatpay':
// #ifndef H5
uni.requestPayment({
provider: 'wxpay',
...res.data,
success: (res) => {
redirect({ url: '/pages/pay/result', param: { code: payInfo.value?.out_trade_no }, mode: 'redirectTo' })
},
fail: (res) => {
loading.value = false
}
})
// #endif
// #ifdef H5
if (isWeixinBrowser()) {
res.data.timestamp = res.data.timeStamp
delete res.data.timeStamp
wechat.pay({
...res.data,
success: () => {
redirect({ url: '/pages/pay/result', param: { code: payInfo.value?.out_trade_no }, mode: 'redirectTo' })
},
cancel: () => {
loading.value = false
}
})
} else {
uni.setStorageSync('paymenting', payInfo.value?.out_trade_no)
location.href = res.data.h5_url
addListenerPayBack()
}
// #endif
break;
case 'alipay':
// #ifdef H5
if (isWeixinBrowser()) {
redirect({ url: '/pages/pay/browser', param: { code: payInfo.value?.out_trade_no, alipay: encodeURIComponent(res.data.url) }, mode: 'redirectTo' })
} else {
uni.setStorageSync('paymenting', payInfo.value?.out_trade_no)
location.href = res.data.url
addListenerPayBack()
}
// #endif
break;
default:
redirect({ url: '/pages/pay/result', param: { code: payInfo.value?.out_trade_no }, mode: 'redirectTo' })
}
}).catch(() => {
loading.value = false
})
}
/**
* 确认支付
*/
const confirmPay = () => {
if (uni.$u.test.isEmpty(type.value)) {
uni.showToast({ title: t('pay.notHavePayType'), icon: 'none' })
return
}
if (loading.value) return
loading.value = true
/**
* 检测是否是支付后返回
*/
uni.$on('checkIsReturnAfterPayment', () => {
if (uni.getStorageSync('paymenting')) {
redirect({
url: '/pages/pay/result',
param: { code: uni.getStorageSync('paymenting') },
mode: 'redirectTo',
success() {
uni.removeStorageSync('paymenting')
}
})
}
})
pay({
out_trade_no: payInfo.value?.out_trade_no,
type: type.value
}).then(res => {
switch (type.value) {
case 'wechatpay':
// #ifndef H5
uni.requestPayment({
provider: 'wxpay',
...res.data,
success: (res) => {
redirect({ url: '/pages/pay/result', param: { code: payInfo.value?.out_trade_no }, mode: 'redirectTo' })
},
fail: (res) => {
loading.value = false
}
})
// #endif
// #ifdef H5
if (isWeixinBrowser()) {
res.data.timestamp = res.data.timeStamp
delete res.data.timeStamp
wechat.pay({
...res.data,
success: () => {
redirect({ url: '/pages/pay/result', param: { code: payInfo.value?.out_trade_no }, mode: 'redirectTo' })
},
cancel: () => {
loading.value = false
}
})
} else {
uni.setStorageSync('paymenting', payInfo.value?.out_trade_no)
location.href = res.data.h5_url
addListenerPayBack()
}
// #endif
break;
case 'alipay':
// #ifdef H5
if (isWeixinBrowser()) {
redirect({ url: '/pages/pay/browser', param: { code: payInfo.value?.out_trade_no, alipay: encodeURIComponent(res.data.url) }, mode: 'redirectTo' })
} else {
uni.setStorageSync('paymenting', payInfo.value?.out_trade_no)
location.href = res.data.url
addListenerPayBack()
}
// #endif
break;
default:
redirect({ url: '/pages/pay/result', param: { code: payInfo.value?.out_trade_no }, mode: 'redirectTo' })
}
}).catch(() => {
loading.value = false
})
}
const open = (outTradeNo : string) => {
getPayInfo(outTradeNo)
.then((res : any) => {
let { data } = res
if (uni.$u.test.isEmpty(data)) {
uni.showToast({ title: t('pay.notObtainedInfo'), icon: 'none' })
return
}
if (data.money == 0) {
redirect({ url: '/pages/pay/result', param: { code: outTradeNo }, mode: 'redirectTo' })
return
}
if (data.status != 0) {
uni.showToast({ title: t('pay.paymentDocuments') + data.status_name, icon: 'none' })
return
}
payInfo.value = data
type.value = data.pay_type_list[0] ? data.pay_type_list[0].key : ''
show.value = true
})
.catch(() => { })
}
/**
* 检测是否是支付后返回
*/
uni.$on('checkIsReturnAfterPayment', () => {
if (uni.getStorageSync('paymenting')) {
redirect({
url: '/pages/pay/result',
param: { code: uni.getStorageSync('paymenting') },
mode: 'redirectTo',
success() {
uni.removeStorageSync('paymenting')
}
})
}
})
const emits = defineEmits(['close'])
const open = (outTradeNo : string) => {
getPayInfo(outTradeNo)
.then((res : any) => {
let { data } = res
if (uni.$u.test.isEmpty(data)) {
uni.showToast({ title: t('pay.notObtainedInfo'), icon: 'none' })
return
}
if (data.money == 0) {
redirect({ url: '/pages/pay/result', param: { code: outTradeNo }, mode: 'redirectTo' })
return
}
if (data.status != 0) {
uni.showToast({ title: t('pay.paymentDocuments') + data.status_name, icon: 'none' })
return
}
payInfo.value = data
type.value = data.pay_type_list[0] ? data.pay_type_list[0].key : ''
show.value = true
})
.catch(() => { })
}
const handleClose = () => {
uni.removeStorageSync('paymenting')
show.value = false
emits('close')
}
const emits = defineEmits(['close'])
defineExpose({
open
})
const handleClose = () => {
uni.removeStorageSync('paymenting')
show.value = false
emits('close')
}
defineExpose({
open
})
</script>
<style lang="scss" scoped>
.pay-item:last-child {
border: none;
}
.pay-item:last-child {
border: none;
}
</style>

View File

@ -1,29 +1,41 @@
<template>
<u-tabbar :value="value" @change="tabbarChange" :fixed="true" :placeholder="true" :safeAreaInsetBottom="true" :inactive-color="tabbar.textColor" :active-color="tabbar.textHoverColor" v-if="tabbar">
<block v-for="item in tabbar.list">
<u-tabbar-item :style="{'background-color': tabbar.backgroundColor}" :text="item.text" :icon="img(value == item.link.url ? item.iconSelectPath : item.iconPath)" :name="item.link.url" v-if="tabbar.type == 1"></u-tabbar-item>
<u-tabbar-item :style="{'background-color': tabbar.backgroundColor}" :icon="img(value == item.link.url ? item.iconSelectPath : item.iconPath)" :name="item.link.url" v-if="tabbar.type == 2"></u-tabbar-item>
<u-tabbar-item :style="{'background-color': tabbar.backgroundColor}" :text="item.text" :name="item.link.url" v-if="tabbar.type == 3"></u-tabbar-item>
</block>
</u-tabbar>
<u-tabbar :value="value" @change="tabbarChange" :fixed="true" :placeholder="true" :safeAreaInsetBottom="true"
:inactive-color="tabbar.textColor" :active-color="tabbar.textHoverColor" v-if="tabbar">
<block v-for="item in tabbar.list">
<u-tabbar-item :style="{'background-color': tabbar.backgroundColor}" :text="item.text"
:icon="img(value == item.link.url ? item.iconSelectPath : item.iconPath)" :name="item.link.url"
v-if="tabbar.type == 1"></u-tabbar-item>
<u-tabbar-item :style="{'background-color': tabbar.backgroundColor}"
:icon="img(value == item.link.url ? item.iconSelectPath : item.iconPath)" :name="item.link.url"
v-if="tabbar.type == 2"></u-tabbar-item>
<u-tabbar-item :style="{'background-color': tabbar.backgroundColor}" :text="item.text" :name="item.link.url"
v-if="tabbar.type == 3"></u-tabbar-item>
</block>
</u-tabbar>
<view class="tab-bar-placeholder"></view>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { redirect, currRoute, img } from '@/utils/common'
import useConfigStore from '@/stores/config'
import { computed } from 'vue'
import { redirect, currRoute, img } from '@/utils/common'
import useConfigStore from '@/stores/config'
const tabbar = computed(() => {
return useConfigStore().tabbar
})
const tabbar = computed(() => {
return useConfigStore().tabbar
})
const value = computed(() => {
return '/' + currRoute()
})
const value = computed(() => {
return '/' + currRoute()
})
const tabbarChange = (name: string) => {
redirect({ url: `${name}` })
}
const tabbarChange = (name : string) => {
redirect({ url: `${name}` })
}
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
.tab-bar-placeholder {
padding-bottom: calc(constant(safe-area-inset-bottom) + 112rpx);
padding-bottom: calc(env(safe-area-inset-bottom) + 112rpx);
}
</style>

View File

@ -12,11 +12,9 @@ export function useCaptcha(formData: formData) {
const refresh = async ()=> {
try {
const res:AnyObject = await getCaptcha()
if (res.code == 200) {
formData.captcha_key = res.data.captcha_key
formData.captcha_code = ''
image.value = res.data.img.replace(/\r\n/g, '')
}
formData.captcha_key = res.data.captcha_key
formData.captcha_code = ''
image.value = res.data.img.replace(/\r\n/g, '')
} catch (e) {
}
}

View File

@ -1,4 +1,4 @@
import { redirect, isWeixinBrowser } from '@/utils/common'
import { redirect, isWeixinBrowser, urlDeconstruction } from '@/utils/common'
import { weappLogin, wechatLogin } from '@/api/auth'
import { getWechatAuthCode } from '@/api/system'
import useMemberStore from '@/stores/member'
@ -14,18 +14,18 @@ export function useLogin() {
const config = useConfigStore()
// #ifdef MP-WEIXIN
if (uni.getStorageSync('openid') && config.login.is_bind_mobile) {
redirect({ url: '/pages/auth/bind' })
redirect({ url: '/pages/auth/bind', mode: 'redirectTo' })
return
}
// #endif
// #ifdef H5
if (isWeixinBrowser() && uni.getStorageSync('openid') && config.login.is_bind_mobile) {
redirect({ url: '/pages/auth/bind' })
redirect({ url: '/pages/auth/bind', mode: 'redirectTo' })
return
}
// #endif
redirect({ url: '/pages/auth/login' })
redirect({ url: '/pages/auth/login', mode: 'redirectTo' })
})
}
@ -83,8 +83,13 @@ export function useLogin() {
// #endif
// #ifdef H5
let url = `${location.origin}${location.pathname}`
let query = urlDeconstruction(location.href).query
query.code && (delete query.code)
Object.keys(query).length && (url += uni.$u.queryParams(query))
getWechatAuthCode({
url: `${location.origin}${location.pathname}`,
url,
scopes
}).then((res : AnyObject) => {
location.href = res.data.url

View File

@ -21,7 +21,7 @@ export function useSendSms(smsRef: AnyObject | null) {
let result: string | boolean = false
await sendSms(param).then(res=>{
if (res.code == 200) {
if (res.code == 1) {
result = res.data.key
} else {
smsRef.value.reset()
@ -29,6 +29,7 @@ export function useSendSms(smsRef: AnyObject | null) {
}
}).catch(err=>{
result = false
smsRef.value.reset()
})
return result
}

View File

@ -8,14 +8,19 @@ import wechat from '@/utils/wechat'
// #endif
export const useShare = () => {
let wechatOptions : WeixinJsSdk.OnMenuShareAppMessageOptions = {
var wechatOptions : WeixinJsSdk.OnMenuShareAppMessageOptions = {
title: '',
link: ''
};
let weappOptions = {};
var weappOptions = {};
// #ifdef H5
const wechatInit = async () => {
if (!isWeixinBrowser()) return;
await wechat.init();
}
// 微信公众号分享
const wechatShare = () => {
if (!isWeixinBrowser()) return;
@ -23,17 +28,26 @@ export const useShare = () => {
}
// #endif
const setShare = (options : any = {}) => {
const setShare = async (options : any = {}) => {
let memberStore = useMemberStore();
// 初始化sdk
await wechatInit();
if (options && options.wechat && options.weapp) {
let query = currShareRoute().params;
if (memberStore.info) {
query.push('mid=' + memberStore.info.member_id);
query.mid = memberStore.info.member_id;
}
let str = [];
for (let key in query) {
str.push(key + '=' + query[key]);
}
// #ifdef H5
let link = location.origin + location.pathname + (query.length > 0 ? '?' + query.join('&') : '');
let link = location.origin + location.pathname + (str.length > 0 ? '?' + str.join('&') : '');
wechatOptions = {
title: options.wechat.title || '',
link: options.wechat.link || link,
@ -45,37 +59,35 @@ export const useShare = () => {
weappOptions = {
title: options.weapp.title || '',
query: options.weapp.path || '/' + currRoute() + (query.length > 0 ? '?' + query.join('&') : ''),
query: options.weapp.path || '/' + currRoute() + (str.length > 0 ? '?' + str.join('&') : ''),
imageUrl: options.weapp.url ? img(options.weapp.url) : ''
}
} else {
getShareInfo({ route: '/' + currRoute(), params: currShareRoute().params.toString() }).then((res : any) => {
if (res.code == 200) {
let data = res.data;
getShareInfo({ route: '/' + currRoute(), params: JSON.stringify(currShareRoute().params) }).then((res : any) => {
let data = res.data;
// #ifdef H5
let wechat = data.wechat;
if (wechat) {
let link = location.origin + location.pathname + (data.query ? '?' + data.query : '');
wechatOptions = {
link: link,
title: wechat.title,
desc: wechat.desc,
imgUrl: wechat.url ? img(wechat.url) : ''
}
}
wechatShare()
// #endif
// #ifdef H5
let wechat = data.wechat;
if (wechat) {
let link = location.origin + location.pathname + (data.query ? '?' + data.query : '');
wechatOptions = {
link: link,
title: wechat.title,
desc: wechat.desc,
imgUrl: wechat.url ? img(wechat.url) : ''
}
}
wechatShare()
// #endif
let weapp = data.weapp;
if (weapp) {
weappOptions = {
query: data.url,
title: weapp.title,
imageUrl: weapp.url ? img(weapp.url) : ''
}
}
}
let weapp = data.weapp;
if (weapp) {
weappOptions = {
query: data.url,
title: weapp.title,
imageUrl: weapp.url ? img(weapp.url) : ''
}
}
})
}

View File

@ -1,13 +1,18 @@
{
// pages.json
"pages.index.index": "",
"pages.article.list": "资讯中心",
"pages.article.detail": "文章详情",
"pages.member.index": "",
"pages.auth.login": "登录",
"pages.auth.register": "注册",
"pages.auth.resetpwd": "找回密码",
"pages.setting.index": "设置",
"pages.auth.bind": "绑定手机号",
"pages.member.personal": "个人资料"
// pages.json
"pages.index.index": "",
"pages.article.list": "资讯中心",
"pages.article.detail": "文章详情",
"pages.member.index": "",
"pages.auth.login": "登录",
"pages.auth.register": "注册",
"pages.auth.resetpwd": "找回密码",
"pages.setting.index": "设置",
"pages.auth.bind": "绑定手机号",
"pages.member.personal": "个人资料",
"pages.member.balance": "我的余额",
"pages.member.detailed_account": "流水明细",
"pages.member.apply_cash_out": "申请提现",
"pages.member.cash_out": "提现记录",
"pages.member.cash_out_detail": "提现详情"
}

View File

@ -5,6 +5,8 @@
"captchaTitle": "请完成验证",
"confirm": "确认",
"cancel": "取消",
"save": "保存",
"delete": "删除",
"captchaPlaceholder": "请输入验证码",
"mobilePlaceholder": "请输入手机号码",
"mobileError": "请输入正确的手机号",
@ -36,5 +38,9 @@
"completePay": "已完成支付",
"incompletePay": "未完成支付",
"getting": "获取支付结果中"
}
},
"memberLanguage": "与你分享我的观点,共享真实世界",
"myBalance": "我的余额",
"myPoint": "我的积分",
"customerService": "联系客服"
}

View File

@ -0,0 +1,7 @@
{
"alipayAccountNo": "支付宝账号",
"addBankCard": "添加银行卡",
"addAlipayAccount": "添加支付宝账号",
"endNumber": "尾号",
"bankCard": "银行卡"
}

View File

@ -0,0 +1,17 @@
{
"addBankCard": "添加银行卡",
"addBankCardTips": "请添加持卡人本人的银行卡",
"addAlipayAccount": "添加支付宝账号",
"addAlipayAccountTips": "请添加已实名的支付宝账号",
"bankRealname": "持卡人姓名",
"bankRealnamePlaceholder": "请输入持卡人姓名",
"bankName": "银行名称",
"bankNamePlaceholder": "请输入银行名称",
"bankAccountNo": "银行卡号",
"bankAccountNoPlaceholder": "请输入银行卡号",
"alipayRealname": "真实姓名",
"alipayRealnamePlaceholder": "请输入真实姓名",
"alipayAccountNo": "支付宝账号",
"alipayAccountNoPlaceholder": "请输入支付宝账号",
"deleteConfirm": "确定要删除该账号吗?"
}

View File

@ -0,0 +1,29 @@
{
"cashOut": "提现",
"balanceDetail": "余额明细",
"cashOutTo": "提现到",
"cashOutTypePlaceholder": "请选择提现方式",
"wechatpay": "微信默认钱包",
"cashOutMoneyTip": "提现金额",
"money": "可提现余额",
"allTx": "全部提现",
"minWithdrawal": "最小提现金额为",
"commissionTo": "手续费为",
"cashOutList": "提现记录",
"cashOutToWechat": "提现至微信",
"cashOutToWechatTips": "提现至微信零钱",
"cashOutToAlipay": "提现至支付宝",
"cashOutToAlipayTips": "请先添加支付宝账号",
"cashOutToBank": "提现至银行卡",
"cashOutToBankTips": "请先添加银行卡",
"alipayAccountNo": "支付宝账号",
"debitCard": "储蓄卡",
"abnormalOperation": "异常操作",
"noAvailableCashOutType": "没有可用的提现方式",
"applyMoneyPlaceholder": "请输入提现金额",
"moneyformatError": "提现金额格式错误",
"applyMoneyExceed": "提现金额超出可提现金额",
"applyMoneyBelow": "提现金额小于最低提现金额",
"replace": "更换",
"toAdd": "去添加"
}

View File

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

View File

@ -0,0 +1,11 @@
{
"applyTime": "申请时间",
"toBeReviewed": "官方正在审核,请耐心等待",
"toBeTransfer": "官方正在转账,请耐心等待",
"transfer": "官方已转账,请及时查收",
"cancelApply": "申请已取消",
"balanceDetail": "余额记录",
"commissionDetail": "佣金记录",
"emptyTip": "暂无余额记录",
"commissemptyTip": "暂无佣金记录"
}

View File

@ -0,0 +1,12 @@
{
"statusName": "当前状态",
"cashOutNo": "交易号",
"serviceMoney": "手续费",
"createTime": "申请时间",
"auditTime": "审核时间",
"transferBank": "银行名称",
"transferAccount": "收款账号",
"refuseReason": "拒绝理由",
"transferTypeName": "转账方式名称",
"transferTime": "转账时间"
}

View File

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

View File

@ -0,0 +1,6 @@
{
"balanceDetail": "余额明细",
"commissionDetail": "佣金明细",
"emptyTip": "暂无余额明细",
"commissemptyTip": "暂无佣金明细"
}

View File

@ -1,12 +0,0 @@
{
"nickname": "昵称",
"sex": "性别",
"mobile": "手机号",
"birthday": "生日",
"unknown": "未知",
"updateHeadimg": "更换头像",
"updateNickname": "修改昵称",
"man": "男",
"woman": "女",
"bindMobile": "绑定手机"
}

View File

@ -0,0 +1,4 @@
{
"rechargeRecord": "充值记录",
"emptyTip": "暂无充值记录"
}

View File

@ -0,0 +1,12 @@
{
"statusName": "当前状态",
"cashOutNo": "交易号",
"serviceMoney": "手续费",
"createTime": "申请时间",
"auditTime": "审核时间",
"transferBank": "银行名称",
"transferAccount": "收款账号",
"refuseReason": "拒绝理由",
"transferTypeName": "转账方式名称",
"transferTime": "转账时间"
}

View File

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

View File

@ -1,68 +1,11 @@
{
"pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages
"pages": [ // pageshttps://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.index.index%"
}
}, {
"path": "pages/index/diy",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.index.diy%"
}
},
{
"path": "pages/auth/login",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "%pages.auth.login%"
}
},
{
"path": "pages/auth/register",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "%pages.auth.register%"
}
},
{
"path": "pages/auth/resetpwd",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "%pages.auth.resetpwd%"
}
},
{
"path": "pages/auth/bind",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "%pages.auth.bind%"
}
},
{
"path": "pages/auth/agreement",
"style": {
"navigationBarTitleText": "",
"navigationBarBackgroundColor": "#ffffff"
}
},
{
"path": "pages/article/list",
@ -73,6 +16,60 @@
"navigationBarTitleText": "%pages.article.list%"
}
},
{
"path": "pages/auth/agreement",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.auth.agreement%"
}
},
{
"path": "pages/auth/bind",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.auth.bind%"
}
},
{
"path": "pages/auth/login",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.auth.login%"
}
},
{
"path": "pages/auth/register",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.auth.register%"
}
},
{
"path": "pages/auth/resetpwd",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.auth.resetpwd%"
}
},
{
"path": "pages/index/diy",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.index.diy%"
}
},
{
"path": "pages/article/detail",
"style": {
@ -82,6 +79,83 @@
"navigationBarTitleText": "%pages.article.detail%"
}
},
{
"path": "pages/member/apply_cash_out",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.member.apply_cash_out%"
},
"needLogin": true
},
{
"path": "pages/member/commission",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.member.commission%"
},
"needLogin": true
},
{
"path": "pages/member/balance",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.member.balance%"
},
"needLogin": true
},
{
"path": "pages/member/recharge_record",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.member.recharge_record%"
},
"needLogin": true
},
{
"path": "pages/member/recharge_record_detail",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.member.recharge_record_detail%"
},
"needLogin": true
},
{
"path": "pages/member/detailed_account",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.member.detailed_account%"
}
},
{
"path": "pages/member/cash_out",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.member.cash_out%"
}
},
{
"path": "pages/member/cash_out_detail",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.member.cash_out_detail%"
}
},
{
"path": "pages/member/index",
"style": {
@ -92,22 +166,19 @@
{
"path": "pages/member/info",
"style": {
"navigationBarTitleText": "%pages.member.index%"
},
"needLogin": true
},
{
"path": "pages/setting/index",
"style": {
"navigationBarBackgroundColor": "#f7f7f7",
"navigationBarTitleText": "%pages.setting.index%"
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.member.info%"
},
"needLogin": true
},
{
"path": "pages/member/personal",
"style": {
"navigationBarBackgroundColor": "#f7f7f7",
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.member.personal%"
},
"needLogin": true
@ -118,17 +189,51 @@
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.member.balance%"
"navigationBarTitleText": "%pages.member.point%"
},
"needLogin": true
},
{
"path": "pages/member/balance",
"path": "pages/member/account",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.member.balance%"
"navigationBarTitleText": "%pages.member.account%"
},
"needLogin": true
},
{
"path": "pages/member/account_edit",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.member.account_edit%"
},
"needLogin": true
},
{
"path": "pages/pay/browser",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "%pages.pay.browser%"
}
},
{
"path": "pages/pay/result",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "%pages.pay.result%"
}
},
{
"path": "pages/setting/index",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%pages.setting.index%"
},
"needLogin": true
},
@ -140,20 +245,16 @@
// #endif
"navigationBarTitleText": "%pages.webview.index%"
}
},
{
"path": "pages/pay/result",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/pay/browser",
"style": {
"navigationStyle": "custom"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "",
"navigationBarBackgroundColor": "#ffffff",
"backgroundColor": "#F8F8F8",
"backgroundColorTop": "#F8F8F8",
"backgroundColorBottom": "#F8F8F8"
},
"tabBar": {
"list": [{
"pagePath": "pages/index/index"
@ -166,16 +267,12 @@
}
]
},
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"uniIdRouter": {},
"easycom": {
"custom": {
"^u-(.*)": "uview-plus/components/u-$1/u-$1.vue",
"diy-system-(\W.*)": "@/components/diy/system/$1/index.vue",
"diy-extend-(\W.*)": "@/components/diy/extend/$1/index.vue",
"diy-(\W.*)": "@/components/diy/$1/index.vue"
}
}

View File

@ -58,19 +58,19 @@
id: id.value,
name: name.value
}).then((res : any) => {
if (res.code == 200) {
let sources = JSON.parse(res.data.value);
diyData.global = sources.global;
diyData.value = sources.value;
uni.setNavigationBarTitle({
title: diyData.global.title
})
if (res.data.value) {
let sources = JSON.parse(res.data.value);
diyData.global = sources.global;
diyData.value = sources.value;
uni.setNavigationBarTitle({
title: diyData.global.title
})
}
let share = res.data.share ? JSON.parse(res.data.share) : null;
setShare(share);
let share = res.data.share ? JSON.parse(res.data.share) : null;
setShare(share);
loading.value = false;
}
loading.value = false;
});
}
});

View File

@ -53,17 +53,16 @@
getDiyInfo({
name: 'DIY_INDEX'
}).then((res : any) => {
if (res.code == 200) {
let sources = JSON.parse(res.data.value);
diyData.global = sources.global;
diyData.value = sources.value;
if (res.data.value) {
let sources = JSON.parse(res.data.value);
diyData.global = sources.global;
diyData.value = sources.value;
uni.setNavigationBarTitle({
title: diyData.global.title
})
}
uni.setNavigationBarTitle({
title: diyData.global.title
})
loading.value = false;
}
loading.value = false;
});
}

View File

@ -0,0 +1,77 @@
<template>
<view class="w-screen h-screen bg-page">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="getCashoutAccountListFn">
<view class="h-[20rpx]"></view>
<view class="p-[30rpx] bg-white mx-[32rpx] my-[20rpx] rounded flex" v-for="(item, index) in accountList" :key="index" @click="handleClick(item)">
<view class="w-[100rpx] h-[100rpx] flex items-center justify-center mr-[10rpx]">
<image
src="data:image/png;base64,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"
mode="widthFix" class="w-[80rpx]" v-if="item.account_type == 'bank'"></image>
<text class="iconfont iconzhifubaoxuanzhong text-[#188dfb] text-[80rpx]" v-else></text>
</view>
<view>
<view>{{ item.account_type == 'bank' ? item.bank_name : t('alipayAccountNo') }}</view>
<view v-if="item.account_type == 'bank'" class="text-sm text-gray-subtitle mt-[10rpx]">{{ t('endNumber') }} {{ item.account_no.substring(item.account_no.length - 4) }}{{ t('bankCard') }}</view>
<view v-else class="text-sm text-gray-subtitle mt-[10rpx]">{{ item.account_no }}</view>
</view>
</view>
<view class="p-[30rpx] bg-white mx-[32rpx] my-[20rpx] rounded flex" @click="redirect({ url: '/pages/member/account_edit', param: { type: accountType, mode } })">
<u-icon name="plus" color="#333" size="16"></u-icon>
<text class="text-sm ml-[10rpx] flex-1">{{ accountType == 'bank' ? t('addBankCard') : t('addAlipayAccount') }}</text>
<u-icon name="arrow-right" color="#333" size="14"></u-icon>
</view>
</mescroll-body>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { redirect } from '@/utils/common'
import { getCashoutAccountList } from '@/api/member'
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue'
import useMescroll from '@/components/mescroll/hooks/useMescroll.js'
import { onPageScroll, onReachBottom, onLoad } from '@dcloudio/uni-app'
import { t } from '@/locale'
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom)
const accountList = ref<Array<any>>([])
const loading = ref(false)
const accountType = ref('bank')
const mescrollRef = ref(null)
const mode = ref('get')
onLoad((data) => {
data.type && (accountType.value = data.type)
data.mode && (mode.value = data.mode)
})
const getCashoutAccountListFn = (mescroll : mescrollStructure) => {
loading.value = false;
let data : object = {
page: mescroll.num,
limit: mescroll.size,
account_type: accountType.value
};
getCashoutAccountList(data).then((res) => {
const newArr = (res.data.data as Array<Object>);
//
if (mescroll.num == 1) {
accountList.value = []; //
}
accountList.value = accountList.value.concat(newArr);
mescroll.endSuccess(newArr.length);
loading.value = true;
}).catch(() => {
loading.value = true;
mescroll.endErr(); // ,
})
}
const handleClick = (data: AnyObject) => {
if (mode.value == 'get') redirect({ url: '/pages/member/account_edit', param: { id: data.account_id, type: accountType.value, mode: mode.value } })
else redirect({ url: '/pages/member/apply_cash_out', param: { account_id: data.account_id, type: accountType.value } })
}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,153 @@
<template>
<scroll-view scroll-y="true" class="w-screen h-screen bg-page">
<view class="h-[30rpx]"></view>
<view class="p-[30rpx] bg-white mx-[32rpx] rounded">
<block v-if="formData.account_type == 'bank'">
<view class="text-center text-base font-bold mt-[50rpx]">{{ t('addBankCard') }}</view>
<view class="text-center text-sm mt-[10rpx]">{{ t('addBankCardTips') }}</view>
<view class="mt-[50rpx]">
<u-form labelPosition="left" :model="formData" labelWidth="200rpx" errorType='toast' :rules="rules"
ref="formRef">
<view class="mt-[10rpx]">
<u-form-item :label="t('bankRealname')" prop="realname" :border-bottom="true">
<u-input v-model="formData.realname" border="none" clearable
:placeholder="t('bankRealnamePlaceholder')"></u-input>
</u-form-item>
</view>
<view class="mt-[10rpx]">
<u-form-item :label="t('bankName')" prop="bank_name" :border-bottom="true">
<u-input v-model="formData.bank_name" border="none" clearable
:placeholder="t('bankNamePlaceholder')"></u-input>
</u-form-item>
</view>
<view class="mt-[10rpx]">
<u-form-item :label="t('bankAccountNo')" prop="account_no" :border-bottom="true">
<u-input v-model="formData.account_no" border="none" clearable
:placeholder="t('bankAccountNoPlaceholder')"></u-input>
</u-form-item>
</view>
</u-form>
</view>
</block>
<block v-if="formData.account_type == 'alipay'">
<view class="text-center text-base font-bold mt-[50rpx]">{{ t('addAlipayAccount') }}</view>
<view class="text-center text-sm mt-[10rpx]">{{ t('addAlipayAccountTips') }}</view>
<view class="mt-[50rpx]">
<u-form labelPosition="left" :model="formData" labelWidth="200rpx" errorType='toast' :rules="rules"
ref="formRef">
<view class="mt-[10rpx]">
<u-form-item :label="t('alipayRealname')" prop="realname" :border-bottom="true">
<u-input v-model="formData.realname" border="none" clearable
:placeholder="t('alipayRealnamePlaceholder')"></u-input>
</u-form-item>
</view>
<view class="mt-[10rpx]">
<u-form-item :label="t('alipayAccountNo')" prop="account_no" :border-bottom="true">
<u-input v-model="formData.account_no" border="none" clearable
:placeholder="t('alipayAccountNoPlaceholder')"></u-input>
</u-form-item>
</view>
</u-form>
</view>
</block>
<view class="mt-[100rpx]">
<u-button :text="t('save')" type="primary" shape="circle" :loading="loading"
@click="handleSave"></u-button>
<view class="mt-[30rpx]" v-if="formData.account_id">
<u-button :text="t('delete')" type="primary" shape="circle" :plain="true" :loading="loading"
@click="deleteConfirm = true"></u-button>
</view>
</view>
</view>
</scroll-view>
<u-modal :show="deleteConfirm" :content="t('deleteConfirm')" :confirmText="t('confirm')" :cancelText="t('cancel')"
:showCancelButton="true" @confirm="handleDelete" @cancel="deleteConfirm = false"></u-modal>
</template>
<script setup lang="ts">
import { ref, computed, reactive } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { getCashoutAccountInfo, addCashoutAccount, editCashoutAccount, deleteCashoutAccount } from '@/api/member'
import { t } from '@/locale'
import { redirect } from '@/utils/common'
const loading = ref(false)
const formRef = ref(null)
const mode = ref('get')
const deleteConfirm = ref(false)
const formData = reactive<AnyObject>({
account_id: 0,
account_type: 'bank',
bank_name: '',
realname: '',
account_no: ''
})
const rules = computed(() => {
return {
'realname': {
type: 'string',
required: true,
message: formData.account_type == 'bank' ? t('bankRealnamePlaceholder') : t('alipayRealnamePlaceholder'),
trigger: ['blur', 'change'],
},
'bank_name': {
type: 'string',
required: formData.account_type == 'bank',
message: t('bankNamePlaceholder'),
trigger: ['blur', 'change'],
},
'account_no': {
type: 'string',
required: true,
message: formData.account_type == 'bank' ? t('bankAccountNoPlaceholder') : t('alipayAccountNoPlaceholder'),
trigger: ['blur', 'change'],
}
}
})
onLoad((data) => {
data.type && (formData.account_type = data.type)
data.mode && (mode.value = data.mode)
if (data.id) {
formData.account_id = data.id
getCashoutAccountInfo({ account_id: data.id }).then((res : responseResult) => {
if (res.data) {
Object.keys(formData).forEach((key : string) => {
if (res.data[key] != undefined) formData[key] = res.data[key]
})
}
})
}
})
const handleSave = () => {
const save = formData.account_id ? editCashoutAccount : addCashoutAccount
formRef.value.validate().then(() => {
if (loading.value) return
loading.value = true
save(formData).then((res) => {
if (mode.value == 'get') redirect({ url: '/pages/member/account', param: { type: formData.account_type, mode: mode.value } })
else redirect({ url: '/pages/member/apply_cash_out', param: { account_id: res.data, type: formData.account_type } })
}).catch(() => {
loading.value = false
})
})
}
const handleDelete = () => {
deleteCashoutAccount(formData.account_id).then(() => {
redirect({ url: '/pages/member/account', mode: 'redirectTo' })
})
}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,278 @@
<template>
<scroll-view scroll-y="true" class="w-screen h-screen bg-page" v-if="!pageLoading">
<view>
<view class="p-[30rpx] bg-white">
<view>{{t('cashOutMoneyTip')}}</view>
<view class="flex py-[20rpx] items-baseline border-0 border-b-[2rpx] border-solid border-gray-200">
<text class="text-[60rpx] ">{{ t('currency') }}</text>
<input type="digit" class="h-[70rpx] leading-[70rpx] pl-[10rpx] flex-1 font-bold text-[60rpx]"
v-model="applyData.apply_money" />
<image @click="clearMoney" v-if="applyData.apply_money"
:src="img('static/resource/images/member/apply_cash_out/close.png')" class="w-[40rpx] h-[40rpx]"
mode="widthFix" />
</view>
<view class="pt-[20rpx]">
<text
class="text-gray-400 text-[28rpx]">{{t('money')}}{{ t('currency') }}{{ moneyFormat(cashOutMoney) }}</text>
<text class="pl-[10rpx] text-[28rpx] text-primary" @click="allMoney">{{t('allTx')}}</text>
</view>
<view>
<text
class="text-[24rpx] text-gray-400">{{t('minWithdrawal')}}{{ t('currency') }}{{ moneyFormat(config.min) }}</text>
<text class="text-[24rpx] text-gray-400">{{t('commissionTo')}}{{ config.rate + '%' }}</text>
</view>
</view>
<view class="px-[30rpx] bg-white mt-[30rpx]">
<!-- 提现到微信 -->
<view class="py-[30rpx] flex" v-if="config.transfer_type.includes('wechat') && memberStore.info && (memberStore.info.wx_openid || memberStore.info.weapp_openid)">
<view><text class="iconfont iconweixin1 text-[#43c93e] text-[70rpx]"></text></view>
<view class="flex-1 px-[20rpx]">
<view>{{ t('cashOutToWechat') }}</view>
<view class="text-[#bbb] text-[26rpx] mt-[16rpx]">{{ t('cashOutToWechatTips') }}</view>
</view>
<view class="flex items-center" @click="applyData.transfer_type = 'wechat'">
<text class="iconfont iconduigou text-[40rpx] text-primary"
v-if="applyData.transfer_type == 'wechat'"></text>
<text class="iconfont iconcheckbox_nol text-[40rpx] text-[#bbb]"
v-else></text>
</view>
</view>
<!-- 提现到支付宝 -->
<view class="py-[30rpx] flex" v-if="config.transfer_type.includes('alipay')">
<view><text class="iconfont iconzhifubaoxuanzhong text-[#188dfb] text-[70rpx]"></text></view>
<view class="flex-1 px-[20rpx]">
<view>{{ t('cashOutToAlipay') }}</view>
<view class="text-[#bbb] text-[26rpx] mt-[16rpx]">
<view v-if="alipayAccountInfo">
{{ t('cashOutTo') }}{{ t('alipayAccountNo') }}{{ alipayAccountInfo.account_no }} <text class="text-black" @click="redirect({ url: '/pages/member/account', param: { type: 'alipay', mode: 'select' } })">{{ t('replace') }}</text>
</view>
<view v-else>
{{ t('cashOutToAlipayTips') }}
</view>
</view>
</view>
<view class="flex items-center">
<u-button :plain="true" type="primary" shape="circle" :custom-style="{height: '56rpx'}" v-if="!alipayAccountInfo" @click="redirect({ url: '/pages/member/account', param: { type: 'alipay', mode: 'select' } })">{{ t('toAdd') }}</u-button>
<view v-else @click="applyData.transfer_type = 'alipay'">
<text class="iconfont iconduigou text-[40rpx] text-primary"
v-if="applyData.transfer_type == 'alipay'"></text>
<text class="iconfont iconcheckbox_nol text-[40rpx] text-[#bbb]"
v-else></text>
</view>
</view>
</view>
<!-- 提现到银行卡 -->
<view class="py-[30rpx] flex" v-if="config.transfer_type.includes('bank')">
<view class="w-[70rpx] flex justify-center">
<image
src="data:image/png;base64,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"
mode="widthFix" class="w-[60rpx]"></image>
</view>
<view class="flex-1 px-[20rpx]">
<view>{{ t('cashOutToBank') }}</view>
<view class="text-[#bbb] text-[26rpx] mt-[16rpx]">
<view v-if="bankAccountInfo">
{{ t('cashOutTo') }}{{ bankAccountInfo.bank_name }}{{ t('debitCard') }}{{ bankAccountInfo.account_no.substring(bankAccountInfo.account_no.length - 4) }} <text class="text-black" @click="redirect({ url: '/pages/member/account', param: { type: 'bank', mode: 'select' } })">{{ t('replace') }}</text>
</view>
<view v-else>
{{ t('cashOutToBankTips') }}
</view>
</view>
</view>
<view class="flex items-center">
<u-button :plain="true" type="primary" shape="circle" :custom-style="{height: '56rpx'}" v-if="!bankAccountInfo" @click="redirect({ url: '/pages/member/account', param: { type: 'bank', mode: 'select' } })">{{ t('toAdd') }}</u-button>
<view v-else @click="applyData.transfer_type = 'bank'">
<text class="iconfont iconduigou text-[40rpx] text-primary"
v-if="applyData.transfer_type == 'bank'"></text>
<text class="iconfont iconcheckbox_nol text-[40rpx] text-[#bbb]"
v-else></text>
</view>
</view>
</view>
</view>
<view class="px-[32rpx]">
<u-button type="primary" shape="circle" :text="t('cashOut')" class="mt-[60rpx] mb-[40rpx]"
:disabled="applyData.apply_money == '' || applyData.apply_money == 0" :loading="loading"
@click="cashOut"></u-button>
</view>
<view class="mt-[40rpx] text-center text-sm" @click="redirect({ url: '/pages/member/cash_out'})">
{{t('cashOutList')}}
</view>
</view>
</scroll-view>
<u-loading-page :loading="pageLoading" bg-color="#e8e8e8" loading-text=""></u-loading-page>
</template>
<script lang="ts" setup>
import { ref, reactive, watch, computed } from 'vue'
import { t } from '@/locale'
import { moneyFormat, redirect, img } from '@/utils/common'
import useMemberStore from '@/stores/member'
import { cashOutConfig, cashOutApply, getFirstCashoutAccountInfo, getCashoutAccountInfo } from '@/api/member'
import { onLoad } from '@dcloudio/uni-app'
const pageLoading = ref(true)
const loading = ref(false)
const memberStore = useMemberStore()
//
const applyData = reactive({
apply_money: '',
transfer_type: '',
account_type: 'money',
account_id: 0
})
//
const cashOutMoney = computed(() => {
return memberStore.info ? memberStore.info[ applyData.account_type ] : 0
})
watch(() => applyData.transfer_type, (nval) => {
switch (nval) {
case 'bank':
applyData.account_id = bankAccountInfo.value ? bankAccountInfo.value.account_id : 0
break;
case 'alipay':
applyData.account_id = alipayAccountInfo.value ? alipayAccountInfo.value.account_id : 0
break;
default:
applyData.account_id = 0
}
}, { immediate: true })
const config = reactive<AnyObject>({
is_auto_transfer: 0, //
is_auto_verify: 0, //
is_open: 0, //
min: 0, //
rate: 0, //
transfer_type: [] //
})
let query:AnyObject | undefined = {}
onLoad(async (data) => {
query = data
uni.getStorageSync('cashOutAccountType') && (applyData.account_type = uni.getStorageSync('cashOutAccountType'))
if (!['money', 'commission'].includes(applyData.account_type)) {
uni.showToast({
title: t('abnormalOperation'),
icon: 'none',
success() {
setTimeout(() => { uni.navigateBack({ delta: 1}) }, 1500)
}
})
return
}
//
await cashOutConfig().then((res : any) => {
for (let key in res.data) {
config[key] = res.data[key];
}
if (config.transfer_type.includes('wechat') && memberStore.info && (!memberStore.info.wx_openid && !memberStore.info.weapp_openid)) config.transfer_type.splice(0, 1)
config.transfer_type.includes('bank') && getBankAccountInfo()
config.transfer_type.includes('alipay') && getAlipayAccountInfo()
applyData.transfer_type = config.transfer_type[0]
pageLoading.value = false
})
})
//
const allMoney = () => {
applyData.apply_money = moneyFormat(cashOutMoney)
}
//
const clearMoney = () => {
applyData.apply_money = '';
}
const verify = () => {
if (!applyData.transfer_type) {
uni.showToast({ title: t('noAvailableCashOutType'), icon: 'none' })
return false
}
if (uni.$u.test.isEmpty(applyData.apply_money)) {
uni.showToast({ title: t('applyMoneyPlaceholder'), icon: 'none' })
return false
}
if (!uni.$u.test.amount(applyData.apply_money)) {
uni.showToast({ title: t('moneyformatError'), icon: 'none' })
return false
}
if (parseFloat(applyData.apply_money) > parseFloat(cashOutMoney.value)) {
uni.showToast({ title: t('applyMoneyExceed'), icon: 'none' })
return false
}
if (parseFloat(applyData.apply_money) < parseFloat(config.min)) {
uni.showToast({ title: t('applyMoneyBelow'), icon: 'none' })
return false
}
return true;
}
/**
* 获取支付宝提现账号信息
*/
const alipayAccountInfo = ref(null)
const getAlipayAccountInfo = () => {
const data = { account_type: 'alipay', account_id: 0 }
let request = getFirstCashoutAccountInfo
if (query.type && query.type == 'alipay' && query.account_id) {
request = getCashoutAccountInfo
data.account_id = query.account_id
}
request(data).then(res => {
if (res.data && res.data.account_id) alipayAccountInfo.value = res.data
})
}
/**
* 获取银行卡提现账号信息
*/
const bankAccountInfo = ref(null)
const getBankAccountInfo = () => {
const data = { account_type: 'bank', account_id: 0 }
let request = getFirstCashoutAccountInfo
if (query.type && query.type == 'bank' && query.account_id) {
request = getCashoutAccountInfo
data.account_id = query.account_id
}
request(data).then(res => {
if (res.data && res.data.account_id) bankAccountInfo.value = res.data
})
}
/**
* 申请提现
*/
const cashOut = ()=> {
if (verify()) {
if (loading.value) return
loading.value = true
cashOutApply(applyData)
.then(res => {
redirect({ url: '/pages/member/cash_out' })
})
.catch(() => {
loading.value = false
})
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -1,209 +1,147 @@
<template>
<view class="bg-gray-100 min-h-[100vh]">
<view class="bg-gradient-to-r from-red-500 to-red-400 fixed top-0 left-0 right-0 z-10">
<view class="px-5 py-6 bg-right-top bg-no-repeat bg-contain"
:style="{'backgroundImage': `url(${img('static/resource/images/member/balance_bg.png')})`}">
<text class="text-white">{{t('availableBalance')}}</text>
<view class="flex align-center justify-between mt-[15rpx]">
<text
class="text-4xl text-white using-hidden w-95">{{memberStore.info ? moneyFormat(memberStore.info.balance) : 0.00 }}</text>
<view class="w-[60px]">
<u-button type="primary" :plain="true" :text="t('recharge')" size="small"
:customStyle="{backgroundColor: 'transparent',color: '#fff', borderColor: '#fff'}"
@click="topUpFn"></u-button>
</view>
</view>
</view>
</view>
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="getBalanceListFn" top="253rpx">
<view
class="bg-white flex items-center border-solid border-t-0 border-l-0 border-r-0 border-b-1 border-gray-300 px-2 py-3">
<u-icon name="list-dot" color="#666" size="20"></u-icon>
<text class="text-sm">{{t('balanceDetail')}}</text>
</view>
<view v-for="(item,index) in balanceList" :key="item.id"
:class="['bg-white relative px-2 py-3',{'border-solid border-t-0 border-l-0 border-r-0 border-b-1 border-gray-200': balanceList.length-1 != index}] ">
<view class="text-base">{{item.from_type_name}}</view>
<view class="text-xs text-gray-400 mt-1">{{item.create_time}}</view>
<view class="text-sm absolute top-[50%] transform -translate-y-[50%] right-2">{{item.account_data}}
</view>
</view>
<mescroll-empty v-if="!balanceList.length && loading"></mescroll-empty>
</mescroll-body>
<view class="account-info-wrap">
<view class="account-info-head" :style="{ background: 'url(' + img('static/resource/images/member/balance_bg.png') + ') no-repeat 95% 30% / auto 250rpx, linear-gradient(314deg, #FE7849 0%, #FF1959 100%)'}">
<view class="name">{{t('balanceInfo')}}</view>
<view class="content">
<view class="money">
{{ memberStore.info ? moneyFormat((parseFloat(memberStore.info.balance) + parseFloat(memberStore.info.money)).toString()) : 0.00 }}
</view>
<view class="text">{{t('accountBalance')}}</view>
<view class="money-wrap">
<view class="money-item" @click="redirect({ url: '/pages/member/detailed_account', param: { type : 'balance' } })">
<view class="money">
{{ moneyFormat(memberStore.info?.balance)|| '0.00' }}
</view>
<view class="text leading-none">{{ t('balance') }}</view>
</view>
<view class="money-item" @click="redirect({ url: '/pages/member/detailed_account', param: { type : 'money' } })">
<view class="money">
{{ moneyFormat(memberStore.info?.money)|| '0.00' }}
</view>
<view class="text leading-none">{{ t('money') }}</view>
</view>
</view>
</view>
</view>
<u-popup :show="topUpShow" mode="center" :round="10" @close="closePopup" :closeable="true">
<view class="w-80 px-3 pb-5 pt-7 box-border">
<u--input :placeholder="t('rechargeAmountPlaceholder')" v-model="rechargeAmount" border="bottom"
type="number"
clearable>
</u--input>
<view class="top-up-wrap flex flex-wrap justify-around mt-3">
<view
:class="['top-up-item w-22 box-border border-1 text-center rounded mt-2 py-3 px-4 border-gray-400 border-solid',{'border-primary text-primary':rechargeAmount == 20}]"
@click="rechargeAmount = 20">
<text>20</text>
</view>
<view
:class="['top-up-item w-22 box-border border-1 text-center rounded mt-2 py-3 px-4 border-gray-400 border-solid',{'border-primary text-primary':rechargeAmount == 30}]"
@click="rechargeAmount = 30">
<text>30</text>
</view>
<view
:class="['top-up-item w-22 box-border border-1 text-center rounded mt-2 py-3 px-4 border-gray-400 border-solid',{'border-primary text-primary':rechargeAmount == 50}]"
@click="rechargeAmount = 50">
<text>50</text>
</view>
<view
:class="['top-up-item w-22 box-border border-1 text-center rounded mt-2 py-3 px-4 border-gray-400 border-solid',{'border-primary text-primary':rechargeAmount == 100}]"
@click="rechargeAmount = 100">
<text>100</text>
</view>
<view
:class="['top-up-item w-22 box-border border-1 text-center rounded mt-2 py-3 px-4 border-gray-400 border-solid',{'border-primary text-primary':rechargeAmount == 200}]"
@click="rechargeAmount = 200">
<text>200</text>
</view>
<view
:class="['top-up-item w-22 box-border border-1 text-center rounded mt-2 py-3 px-4 border-gray-400 border-solid',{'border-primary text-primary':rechargeAmount == 300}]"
@click="rechargeAmount = 300">
<text>300</text>
</view>
</view>
<view class="mt-5 px-2">
<u-button type="primary" shape="circle" :loading="rechargeLoading" :text="t('clickRecharge')"
@click="recharge"></u-button>
</view>
</view>
</u-popup>
<view class="account-info-btn">
<u-button type="primary" shape="circle" class="btn"
:customStyle="{backgroundColor: '#FE4E50',color: '#fff', borderColor: '#FE4E50',width: 'calc(100vw - 64rpx)'}"
@click="topUpFn">
<img class="max-w-[36rpx] max-h-[36rpx] mr-1" :src="img('static/resource/images/member/reset.png')" alt="">
<text>{{t('recharge')}}</text>
</u-button>
<u-button v-if="cashOutConfigObj.is_open == 1" type="primary" :plain="true" shape="circle" class="btn"
:customStyle="{backgroundColor: '#fff',color: '#FE4E50', borderColor: '#FE4E50',width: 'calc(100vw - 64rpx)'}"
@click="applyCashOut">
<img class="max-w-[36rpx] max-h-[36rpx] mr-1" :src="img('static/resource/images/member/withdraw_deposit.png')" alt="">
<text>{{t('cashOut')}}</text>
</u-button>
</view>
<pay ref="payRef" @close="rechargeLoading = false"></pay>
</view>
<!-- 充值 -->
<u-popup :show="topUpShow" mode="center" :round="10" @close="closePopup" :closeable="true">
<view class="w-80 px-3 pb-4 pt-7 box-border">
<u--input :placeholder="t('rechargeAmountPlaceholder')" v-model="rechargeAmount" border="bottom"
type="number" clearable>
</u--input>
<view class="top-up-wrap flex flex-wrap justify-around mt-3">
<view v-for="(item,index) in rechargePackage" :key="index"
:class="['top-up-item w-22 box-border border-1 text-center rounded mt-2 py-3 px-4 border-gray-400 border-solid',{'border-primary text-primary':rechargeAmount == item}]"
@click="rechargeAmount = item">
<text>{{item}}{{t('yuan')}}</text>
</view>
</view>
<view class="mt-5 px-2">
<u-button type="primary" shape="circle" :loading="rechargeLoading" :text="t('clickRecharge')"
@click="recharge"></u-button>
</view>
<view class="mt-[20rpx] text-center text-sm"
@click="redirect({ url: '/pages/member/recharge_record' })">{{t('rechargeRecord')}}</view>
</view>
</u-popup>
<pay ref="payRef" @close="rechargeLoading = false"></pay>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { t } from '@/locale'
import { moneyFormat, img } from '@/utils/common';
import { getBalanceList, createRecharge } from '@/api/member';
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
import { onPageScroll, onReachBottom, onShow } from '@dcloudio/uni-app';
import useMemberStore from '@/stores/member'
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
import { ref, reactive } from 'vue'
import { t } from '@/locale'
import { moneyFormat, redirect, img } from '@/utils/common';
import { createRecharge, cashOutConfig } from '@/api/member';
import { onShow } from '@dcloudio/uni-app';
import useMemberStore from '@/stores/member'
const memberStore = useMemberStore(),
balanceList = ref<Array<any>>([]),
mescrollRef = ref(null),
loading = ref<boolean>(false),
topUpShow = ref<boolean>(false);
const memberStore = useMemberStore(),
topUpShow = ref<boolean>(false);
interface mescrollStructure {
num : number,
size : number,
endSuccess : Function,
[propName : string] : any
}
const getBalanceListFn = (mescroll : mescrollStructure) => {
loading.value = false;
let data : Object = {
page: mescroll.num,
page_size: mescroll.size,
};
interface acceptingDataStructure {
data : acceptingDataItemStructure,
msg : string,
code : number
}
interface acceptingDataItemStructure {
data : object,
[propName : string] : number | string | object
}
getBalanceList(data).then((res : acceptingDataStructure) => {
let newArr = res.data.data;
mescroll.endSuccess(newArr.length);
//
if (mescroll.num == 1) {
balanceList.value = []; //
const topUpFn = () => {
topUpShow.value = true;
}
const closePopup = () => {
topUpShow.value = false;
}
const rechargePackage = ref([20, 30, 50, 100, 200, 300])
const rechargeAmount = ref<string | number>("");
const rechargeLoading = ref(false)
const payRef = ref(null)
const cashOutConfigObj = reactive({
is_auto_transfer: 0, //
is_auto_verify: 0, //
is_open: 0, //
min: 0, //
rate: 0, //
transfer_type: [] //
})
onShow(() => {
// h5
// #ifdef H5
uni.$emit('checkIsReturnAfterPayment')
// #endif
cashOutConfig().then((res) => {
for (let key in res.data) {
cashOutConfigObj[key] = res.data[key];
}
balanceList.value = balanceList.value.concat(newArr);
loading.value = true;
}).catch(() => {
loading.value = true;
mescroll.endErr(); // ,
})
}
})
})
const topUpFn = () => {
topUpShow.value = true;
}
/**
* 发起充值
*/
const recharge = () => {
if (uni.$u.test.isEmpty(rechargeAmount.value)) {
uni.showToast({ title: t('rechargeAmountPlaceholder'), icon: 'none' })
return
}
if (!uni.$u.test.amount(rechargeAmount.value) || rechargeAmount.value <= 0) {
uni.showToast({ title: t('rechargeAmountError'), icon: 'none' })
return
}
if (rechargeLoading.value) return
rechargeLoading.value = true
const closePopup = () => {
topUpShow.value = false;
}
const rechargeAmount = ref<string | number>("");
const rechargeLoading = ref(false)
const payRef = ref(null)
onShow(() => {
// h5
// #ifdef H5
uni.$emit('checkIsReturnAfterPayment')
// #endif
})
/**
* 发起充值
*/
const recharge = () => {
if (uni.$u.test.isEmpty(rechargeAmount.value)) {
uni.showToast({ title: t('rechargeAmountPlaceholder'), icon: 'none' })
return
}
if (!uni.$u.test.amount(rechargeAmount.value) || rechargeAmount.value <= 0) {
uni.showToast({ title: t('rechargeAmountError'), icon: 'none' })
return
}
if (rechargeLoading.value) return
rechargeLoading.value = true
createRecharge({ recharge_money: rechargeAmount.value })
.then(res => {
payRef.value?.open(res.data.out_trade_no)
})
.catch(() => {
rechargeLoading.value = false
})
createRecharge({ recharge_money: rechargeAmount.value }).then(res => {
payRef.value?.open(res.data.out_trade_no)
}).catch(() => {
rechargeLoading.value = false
})
}
const applyCashOut = ()=> {
uni.setStorageSync('cashOutAccountType', 'money')
redirect({ url: '/pages/member/apply_cash_out' })
}
</script>
<style lang="scss" scoped>
@mixin flex {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
/* 单行超出隐藏 */
.using-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
white-space: break-spaces;
}
.popup-content {
@include flex;
align-items: center;
justify-content: center;
padding: 15px;
height: 50px;
background-color: #fff;
}
@import '@/styles/account_info.scss';
</style>

View File

@ -0,0 +1,76 @@
<template>
<view class="member-record-list">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="getCashOutListFn">
<view v-for="(item,index) in cashOutList" :key="item.id" class="member-record-item" @click="toDetailFn(item)">
<view class="name">{{item.transfer_type_name}}</view>
<view class="desc">{{t('applyTime')}}: {{item.create_time}}</view>
<view class="desc">{{ item.status != -1 ? currentStatusDesc(item.status) : item.refuse_reason}}</view>
<view class="money" :class="item.apply_money > 0 ? 'text-active' : ''">
{{ item.apply_money > 0 ? '+' + item.apply_money : item.apply_money }}
</view>
<view class="state">
{{ item.status_name }}
</view>
</view>
<mescroll-empty v-if="!cashOutList.length && loading" :option="{tip : (account_type == 'commission' ? t('commissemptyTip') : t('emptyTip') )}"></mescroll-empty>
</mescroll-body>
</view>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import { t } from '@/locale'
import { redirect, img } from '@/utils/common';
import { getCashOutList } from '@/api/member';
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app';
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
let cashOutList = ref<Array<any>>([]);
let mescrollRef = ref(null);
let loading = ref<boolean>(false);
let account_type = uni.getStorageSync('cashOutAccountType')
const currentStatusDesc = (status) =>{
switch(status){
case 1:
return t('toBeReviewed')
case 2:
return t('toBeTransfer')
case 3:
return t('transfer')
case -2:
return t('cancelApply')
}
}
const getCashOutListFn = (mescroll)=>{
let data = ref({});
loading.value = false;
data.value.page = mescroll.num;
data.value.page_size = mescroll.size;
data.value.account_type = account_type;
getCashOutList(data.value).then((res) => {
let newArr = res.data.data;
mescroll.endSuccess(newArr.length);
//
if (mescroll.num == 1){
cashOutList.value = []; //
}
cashOutList.value = cashOutList.value.concat(newArr);
loading.value = true;
}).catch(()=>{
loading.value = true;
mescroll.endErr(); // ,
})
}
const toDetailFn = (data)=>{
redirect({ url: '/pages/member/cash_out_detail', param: { id: data.id }});
}
</script>
<style lang="scss">
@import '@/styles/member_record_list.scss';
</style>

View File

@ -0,0 +1,77 @@
<template>
<view class="member-record-detail">
<view class="money-wrap">
<text>-{{ cashOutInfo.apply_money }}</text>
<text>{{ cashOutInfo.status_name }}</text>
</view>
<!-- 状态0待审核1.待转账2已转账 -1拒绝' -->
<view class="item">
<view class="line-wrap">
<text class="label">{{t('cashOutNo')}}</text>
<text class="value">{{ cashOutInfo.cash_out_no }}</text>
</view>
<view class="line-wrap">
<text class="label">{{t('serviceMoney')}}</text>
<text class="value">{{ cashOutInfo.service_money }}</text>
</view>
<view class="line-wrap">
<text class="label">{{t('createTime')}}</text>
<text class="value">{{ cashOutInfo.create_time }}</text>
</view>
<view class="line-wrap" v-if="cashOutInfo.status">
<text class="label">{{t('auditTime')}}</text>
<text class="value">{{ cashOutInfo.audit_time }}</text>
</view>
<view class="line-wrap" v-if="cashOutInfo.transfer_bank">
<text class="label">{{t('transferBank')}}</text>
<text class="value">{{ cashOutInfo.transfer_bank }}</text>
</view>
<view class="line-wrap">
<text class="label">{{t('transferAccount')}}</text>
<text class="value">{{ cashOutInfo.transfer_account }}</text>
</view>
<view class="line-wrap" v-if="cashOutInfo.status == -1 && cashOutInfo.refuse_reason">
<text class="label">{{t('refuseReason')}}</text>
<text class="value">{{ cashOutInfo.refuse_reason }}</text>
</view>
<view class="line-wrap" v-if="cashOutInfo.status == 2">
<text class="label">{{t('transferTypeName')}}</text>
<text class="value">{{ cashOutInfo.transfer_type_name }}</text>
</view>
<view class="line-wrap" v-if="cashOutInfo.status == 2">
<text class="label">{{t('transferTime')}}</text>
<text class="value">{{ cashOutInfo.transfer_time }}</text>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { t } from '@/locale'
import { redirect, img } from '@/utils/common';
import { getCashOutDetail } from '@/api/member';
let cashOutInfo = ref({});
let loading = ref<boolean>(false);
onLoad((option) => {
let id = option.id || "";
getCashoutAccountListFn(id)
})
const getCashoutAccountListFn = (id) => {
loading.value = false;
getCashOutDetail(id).then((res) => {
cashOutInfo.value = res.data;
loading.value = true;
}).catch(() => {
loading.value = true;
})
}
</script>
<style lang="scss">
@import '@/styles/member_record_detail.scss';
</style>

View File

@ -0,0 +1,53 @@
<template>
<view class="account-info-wrap">
<view class="account-info-head"
:style="{ background: 'url(' + img('static/resource/images/member/balance_bg.png') + ') no-repeat 95% 30% / auto 250rpx, linear-gradient(314deg, #FE7849 0%, #FF1959 100%)'}">
<view class="name">{{t('commissionInfo')}}</view>
<view class="content">
<view class="money" @click="redirect({ url: '/pages/member/detailed_account', param: { type : 'commission' } })">
{{ memberStore.info ? moneyFormat(memberStore.info.commission) : 0.00 }}
</view>
<view class="text" @click="redirect({ url: '/pages/member/detailed_account', param: { type : 'commission' } })">{{t('accountCommission')}}</view>
<view class="money-wrap">
<view class="money-item">
<view class="money">
{{ moneyFormat(memberStore.info?.commission_get)|| '0.00' }}
</view>
<view class="text">{{ t('commission') }}</view>
</view>
<view class="money-item">
<view class="money">
{{ moneyFormat(memberStore.info?.commission_cash_outing)|| '0.00' }}
</view>
<view class="text">{{ t('money') }}</view>
</view>
</view>
</view>
</view>
<view class="account-info-btn">
<u-button type="primary" :plain="true" shape="circle" class="btn"
:customStyle="{backgroundColor: '#fff',color: '#FE4E50', borderColor: '#FE4E50',width: 'calc(100vw - 64rpx)'}"
@click="applyCashOut">
<img class="max-w-[36rpx] max-h-[36rpx] mr-1" :src="img('static/resource/images/member/withdraw_deposit.png')" alt="">
<text>{{t('cashOut')}}</text>
</u-button>
</view>
</view>
</template>
<script setup lang="ts">
import { t } from '@/locale'
import { moneyFormat, redirect, img } from '@/utils/common';
import useMemberStore from '@/stores/member'
const memberStore = useMemberStore();
const applyCashOut = ()=> {
uni.setStorageSync('cashOutAccountType', 'commission')
redirect({ url: '/pages/member/apply_cash_out' })
}
</script>
<style lang="scss">
@import '@/styles/account_info.scss';
</style>

View File

@ -0,0 +1,83 @@
<template>
<view class="member-record-list">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="getListFn" top="">
<view v-for="(item,index) in list" :key="item.id" class="member-record-item">
<view class="name">{{item.from_type_name}}</view>
<view class="desc" v-if="item.memo">{{item.memo}}</view>
<view class="desc">{{item.create_time}}</view>
<view class="money" :class="item.account_data > 0 ? 'text-active' : ''">
{{ item.account_data > 0 ? '+' + item.account_data : item.account_data }}
</view>
</view>
<mescroll-empty v-if="!list.length && loading" :option="{tip : (type == 'commission' ? t('commissemptyTip') : t('emptyTip') )}"></mescroll-empty>
</mescroll-body>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { t } from '@/locale'
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
import { getBalanceList, getMoneyList, getCommissionList} from '@/api/member';
import { onPageScroll, onReachBottom, onLoad, onShow } from '@dcloudio/uni-app';
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
const type = ref('')
onLoad((options) => {
type.value = options.type || 'balance';
});
const list = ref<Array<any>>([]),
loading = ref<boolean>(false),
mescrollRef = ref(null);
interface mescrollStructure {
num : number,
size : number,
endSuccess : Function,
[propName : string] : any
}
const getListFn = (mescroll : mescrollStructure) => {
loading.value = false;
let data : Object = {
page: mescroll.num,
page_size: mescroll.size
};
interface acceptingDataStructure {
data : acceptingDataItemStructure,
msg : string,
code : number
}
interface acceptingDataItemStructure {
data : object,
[propName : string] : number | string | object
}
let fnList = (params : any) => { };
if (type.value == 'balance') fnList = getBalanceList;
else if (type.value == 'money') fnList = getMoneyList;
else if (type.value == 'commission') fnList = getCommissionList;
fnList(data).then((res : acceptingDataStructure) => {
let newArr = res.data.data;
mescroll.endSuccess(newArr.length);
//
if (mescroll.num == 1) {
list.value = []; //
}
list.value = list.value.concat(newArr);
loading.value = true;
}).catch(() => {
loading.value = true;
mescroll.endErr(); // ,
})
}
</script>
<style lang="scss">
@import '@/styles/member_record_list.scss';
</style>

View File

@ -48,15 +48,15 @@
getDiyInfo({
name: 'DIY_MEMBER_INDEX'
}).then((res : any) => {
if (res.code == 200) {
let sources = JSON.parse(res.data.value);
diyData.global = sources.global;
diyData.value = sources.value;
uni.setNavigationBarTitle({
title: diyData.global.title
})
loading.value = false;
}
if (res.data.value) {
let sources = JSON.parse(res.data.value);
diyData.global = sources.global;
diyData.value = sources.value;
uni.setNavigationBarTitle({
title: diyData.global.title
})
}
loading.value = false;
});
}
useMemberStore().getMemberInfo()

View File

@ -67,7 +67,7 @@
import { t } from '@/locale'
import useMemberStore from '@/stores/member'
import { img, mobileConceal } from '@/utils/common'
import { updateMember } from '@/api/member'
import { modifyMember } from '@/api/member'
import { fetchBase64Image, uploadImage } from '@/api/system'
const memberStore = useMemberStore()
@ -86,7 +86,7 @@
const updateNicknameConfirm = () => {
if (uni.$u.test.isEmpty(updateNickname.value)) { uni.showToast({ title: t('nicknamePlaceholder'), icon: 'none' }); return }
updateMember({
modifyMember({
field: 'nickname',
value: updateNickname.value
}).then(res => {
@ -106,7 +106,7 @@
]
})
const updateSex = (e) => {
updateMember({
modifyMember({
field: 'sex',
value: e.value
}).then(res => {
@ -123,7 +123,7 @@
encoding: 'base64', //
success: res => {
fetchBase64Image({ content: res.data }).then(uploadRes => {
updateMember({
modifyMember({
field: 'headimg',
value: uploadRes.data.url
}).then(res => {
@ -139,7 +139,7 @@
filePath: event.file.url,
name: 'file'
}).then(res => {
updateMember({
modifyMember({
field: 'headimg',
value: res.data.url
}).then(() => {
@ -154,7 +154,7 @@
*/
const birthdayPicker = ref(false)
const updateBirthday = (e) => {
updateMember({
modifyMember({
field: 'birthday',
value: uni.$u.date(e.value, 'yyyy-mm-dd')
}).then(() => {

View File

@ -0,0 +1,80 @@
<template>
<view class="member-record-list">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="getListFn" top="">
<view v-for="(item,index) in list" :key="item.id" class="member-record-item" @click="toDetailFn(item)">
<view class="name">{{item.from_type_name}}</view>
<view class="desc" v-if="item.memo">{{item.memo}}</view>
<view class="desc">{{item.create_time}}</view>
<view class="money" :class="item.account_data > 0 ? 'text-active' : ''">
{{ item.account_data > 0 ? '+' + item.account_data : item.account_data }}
</view>
</view>
<mescroll-empty v-if="!list.length && loading" :option="{tip : t('emptyTip') }"></mescroll-empty>
</mescroll-body>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { t } from '@/locale'
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
import { getRechargeList} from '@/api/member';
import { onPageScroll, onReachBottom, onLoad } from '@dcloudio/uni-app';
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
const list = ref<Array<any>>([]),
loading = ref<boolean>(false),
mescrollRef = ref(null);
interface mescrollStructure {
num : number,
size : number,
endSuccess : Function,
[propName : string] : any
}
const getListFn = (mescroll : mescrollStructure) => {
loading.value = false;
let data : Object = {
page: mescroll.num,
page_size: mescroll.size
};
interface acceptingDataStructure {
data : acceptingDataItemStructure,
msg : string,
code : number
}
interface acceptingDataItemStructure {
data : object,
[propName : string] : number | string | object
}
getRechargeList(data).then((res : acceptingDataStructure) => {
let newArr = res.data.data;
mescroll.endSuccess(newArr.length);
//
if (mescroll.num == 1) {
list.value = []; //
}
list.value = list.value.concat(newArr);
loading.value = true;
}).catch(() => {
loading.value = true;
mescroll.endErr(); // ,
})
}
const toDetailFn = (data)=>{
redirect({ url: '/pages/member/recharge_record_detail', param: { id: data.order_id }});
}
</script>
<style lang="scss" scoped>
@import '@/styles/member_record_list.scss';
</style>

View File

@ -0,0 +1,77 @@
<template>
<view class="member-record-detail">
<view class="money-wrap">
<text>-{{ cashOutInfo.apply_money }}</text>
<text>{{ cashOutInfo.status_name }}</text>
</view>
<!-- 状态0待审核1.待转账2已转账 -1拒绝' -->
<view class="item">
<view class="line-wrap">
<text class="label">{{t('cashOutNo')}}</text>
<text class="value">{{ cashOutInfo.cash_out_no }}</text>
</view>
<view class="line-wrap">
<text class="label">{{t('serviceMoney')}}</text>
<text class="value">{{ cashOutInfo.service_money }}</text>
</view>
<view class="line-wrap">
<text class="label">{{t('createTime')}}</text>
<text class="value">{{ cashOutInfo.create_time }}</text>
</view>
<view class="line-wrap" v-if="cashOutInfo.status">
<text class="label">{{t('auditTime')}}</text>
<text class="value">{{ cashOutInfo.audit_time }}</text>
</view>
<view class="line-wrap" v-if="cashOutInfo.transfer_bank">
<text class="label">{{t('transferBank')}}</text>
<text class="value">{{ cashOutInfo.transfer_bank }}</text>
</view>
<view class="line-wrap">
<text class="label">{{t('transferAccount')}}</text>
<text class="value">{{ cashOutInfo.transfer_account }}</text>
</view>
<view class="line-wrap" v-if="cashOutInfo.status == -1 && cashOutInfo.refuse_reason">
<text class="label">{{t('refuseReason')}}</text>
<text class="value">{{ cashOutInfo.refuse_reason }}</text>
</view>
<view class="line-wrap" v-if="cashOutInfo.status == 2">
<text class="label">{{t('transferTypeName')}}</text>
<text class="value">{{ cashOutInfo.transfer_type_name }}</text>
</view>
<view class="line-wrap" v-if="cashOutInfo.status == 2">
<text class="label">{{t('transferTime')}}</text>
<text class="value">{{ cashOutInfo.transfer_time }}</text>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { t } from '@/locale'
import { redirect, img } from '@/utils/common';
import { getRechargeDetail } from '@/api/member';
let cashOutInfo = ref({});
let loading = ref<boolean>(false);
onLoad((option) => {
let id = option.id || "";
getCashoutAccountListFn(id)
})
const getCashoutAccountListFn = (id) => {
loading.value = false;
getRechargeDetail(id).then((res) => {
cashOutInfo.value = res.data;
loading.value = true;
}).catch(() => {
loading.value = true;
})
}
</script>
<style lang="scss">
@import '@/styles/member_record_detail.scss';
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1,5 +1,5 @@
import { defineStore } from 'pinia'
import { getToken, setToken, removeToken, redirect } from '@/utils/common'
import { setToken, removeToken, redirect } from '@/utils/common'
import { getMemberInfo } from '@/api/member'
import { logout } from '@/api/auth'
@ -11,7 +11,7 @@ interface Member {
const useMemberStore = defineStore('member', {
state: () : Member => {
return {
token: getToken(),
token: uni.getStorageSync(import.meta.env.VITE_REQUEST_STORAGE_TOKEN_KEY),
info: null
}
},
@ -26,12 +26,12 @@ const useMemberStore = defineStore('member', {
.then((res : any) => {
this.info = res.data
})
.catch(() => {
this.logout()
.catch(async () => {
await this.logout()
})
},
logout(isRedirect : boolean = false) {
logout().then(() => {
async logout(isRedirect : boolean = false) {
await logout().then(() => {
this.$reset()
removeToken()
isRedirect && redirect({ url: '/pages/index/index' })

View File

@ -0,0 +1,41 @@
.account-info-wrap{
@apply bg-[#F5F6FA] min-h-[100vh];
.account-info-head{
@apply relative h-40;
.name{
@apply ml-4 pt-7 text-white text-lg mb-3;
}
.content{
@apply absolute bg-white left-3 right-3 rounded-lg p-5;
.money{
@apply text-xl font-bold;
}
.text{
@apply text-xs text-slate-500 mt-2;
}
.money-wrap{
@apply mt-5 flex;
.money-item{
@apply flex-1;
}
.money{
@apply text-lg;
}
.text{
@apply mt-1;
}
}
}
}
.account-info-btn{
@apply flex mt-24 ml-3 mr-3;
.btn{
&:first-of-type{
@apply mr-1 rounded;
}
&:last-of-type{
@apply ml-1 rounded;
}
}
}
}

View File

@ -1,51 +1,98 @@
@font-face {
font-family: "iconfont";
/* Project id 3952239 */
src: url('//at.alicdn.com/t/c/font_3952239_vfd4vlalsk.woff2?t=1680088109665') format('woff2'),
url('//at.alicdn.com/t/c/font_3952239_vfd4vlalsk.woff?t=1680088109665') format('woff'),
url('//at.alicdn.com/t/c/font_3952239_vfd4vlalsk.ttf?t=1680088109665') format('truetype');
font-family: "iconfont"; /* Project id 3952239 */
src: url('//at.alicdn.com/t/c/font_3952239_ukixio2ve7k.woff2?t=1684147503182') format('woff2'),
url('//at.alicdn.com/t/c/font_3952239_ukixio2ve7k.woff?t=1684147503182') format('woff'),
url('//at.alicdn.com/t/c/font_3952239_ukixio2ve7k.ttf?t=1684147503182') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.iconcheckbox_nol:before {
content: "\e626";
}
.iconweixin1:before {
content: "\e878";
}
.iconyinlian:before {
content: "\e68b";
}
.iconzhifubaoxuanzhong:before {
content: "\e802";
}
.iconshuaxin:before {
content: "\e631";
}
.iconkefu:before {
content: "\e612";
}
.iconfenxiang:before {
content: "\e610";
}
.icondianzan:before {
content: "\ec7f";
}
.iconhuiyuanjiage:before {
content: "\e611";
}
.iconxiazai:before {
content: "\e69c";
}
.icondunpai:before {
content: "\e80b";
}
.icona-shejianchangguan:before {
content: "\e647";
}
.iconduigou:before {
content: "\e632";
content: "\e632";
}
.iconzhifushibai:before {
content: "\e663";
content: "\e663";
}
.iconweixinzhifu2:before {
content: "\e62b";
content: "\e62b";
}
.iconalipay:before {
content: "\e618";
content: "\e618";
}
.iconbalance:before {
content: "\e73b";
content: "\e73b";
}
.iconwode-xian:before {
content: "\e60f";
content: "\e60f";
}
.iconwodezixun:before {
content: "\e645";
content: "\e645";
}
.iconshouye-zhihui:before {
content: "\e61d";
content: "\e61d";
}
.iconshezhi:before {
content: "\e600";
}
content: "\e600";
}

View File

@ -0,0 +1,25 @@
page{
background-color: #f5f6fa;
@apply pt-4;
}
.member-record-detail{
@apply m-4 mt-0 bg-white rounded-md px-4 py-6;
.money-wrap{
@apply flex items-center flex-col mb-6;
text:first-of-type{
@apply text-3xl font-bold mt-1;
}
text:last-of-type{
@apply text-sm mt-3;
}
}
.line-wrap{
@apply flex justify-between text-sm mt-3;
.label{
@apply text-[#878787];
}
.value{
@apply text-[#222];
}
}
}

View File

@ -0,0 +1,21 @@
.member-record-list{
@apply min-h-[100vh];
.member-record-item{
@apply relative mx-4 border-solid border-t-0 border-l-0 border-r-0 border-b-1 border-[#ECEBEC] py-3;
.name{
@apply text-sm;
}
.desc{
@apply text-xs text-[#8D8C8D] mt-1;
}
.text-active{
color: #FF0D3E;
}
.money{
@apply absolute right-3 top-4 text-base font-bold;
}
.state{
@apply absolute right-3 top-11 text-[#8D8C8D] text-xs;
}
}
}

View File

@ -1,5 +1,6 @@
import { getTabbarPages } from './pages'
import useDiyStore from '@/stores/diy'
import useMemberStore from '@/stores/member'
/**
*
@ -105,17 +106,14 @@ export const currShareRoute = () => {
// #endif
// 拼接参数
let params = [];
let params = {};
for (let key in currentParam) {
params.push(key + '=' + currentParam[key])
params[key] = currentParam[key]
}
let currentPath = '/' + currentRoute;
let currentQuery = params.join('&');
if (currentQuery) currentPath += '?' + currentQuery;
return {
path: currentPath,
query: currentQuery,
params: params
}
}
@ -125,7 +123,7 @@ export const currShareRoute = () => {
* @returns
*/
export function getToken() : null | string {
return uni.getStorageSync(import.meta.env.VITE_REQUEST_STORAGE_TOKEN_KEY)
return useMemberStore().token
}
/**

View File

@ -1,6 +1,7 @@
import { language } from '@/locale'
import { checkNeedLogin } from '@/utils/auth'
import { urlDeconstruction } from '@/utils/common'
import { urlDeconstruction, getToken } from '@/utils/common'
import { memberLog } from '@/api/auth'
/**
*
@ -12,10 +13,15 @@ export const redirectInterceptor = () => {
uni.addInterceptor(name, {
invoke(args) {
const route = urlDeconstruction(args.url)
// 加载语言包
language.loadLocaleMessages(route.path, uni.getLocale())
// 校验是否需要登录
checkNeedLogin(route)
// 添加会员访问日志
if (getToken()) memberLog({ route: route.path, params: JSON.stringify(route.query), pre_route: getCurrentPages()[0].route })
}
})
})
@ -25,9 +31,11 @@ export const redirectInterceptor = () => {
*
*/
export const launchInterceptor = () => {
// 加载语言包
const launch = uni.getLaunchOptionsSync()
launch.path = `/${launch.path}`
language.loadLocaleMessages(launch.path, uni.getLocale())
// 校验是否需要登录
checkNeedLogin(launch)
@ -38,6 +46,10 @@ export const launchInterceptor = () => {
// #ifdef H5
const match = location.href.match(/\/s(\d*)\//);
if (match) uni.setStorageSync('site_id', match[1])
if (match) uni.setStorageSync('wap_site_id', match[1])
else uni.removeStorageSync('wap_site_id')
// #endif
// 添加会员访问日志
if (getToken()) memberLog({ route: launch.path, params: JSON.stringify(launch.query || {}), pre_route: '' })
}

View File

@ -27,7 +27,7 @@ class Request {
this.config.header[import.meta.env.VITE_REQUEST_HEADER_SITEID_KEY] = import.meta.env.VITE_SITE_ID
// #endif
// #ifdef H5
this.config.header[import.meta.env.VITE_REQUEST_HEADER_SITEID_KEY] = uni.getStorageSync('site_id') || import.meta.env.VITE_SITE_ID
this.config.header[import.meta.env.VITE_REQUEST_HEADER_SITEID_KEY] = uni.getStorageSync('wap_site_id') || import.meta.env.VITE_SITE_ID
// #endif
this.config.header[import.meta.env.VITE_REQUEST_HEADER_CHANNEL_KEY] = getAppChannel()
@ -66,18 +66,18 @@ class Request {
*/
public upload(url : string, data : AnyObject = {}, config : RequestConfig = {}) {
this.requestInterceptors()
Object.assign(this.config, {
const params = Object.assign(uni.$u.deepClone(this.config), {
url: this.baseUrl + url,
...data
})
return new Promise((resolve, reject) => {
uni.uploadFile({
...this.config,
...params,
success: res => {
const data = JSON.parse(res.data)
if (data.code == 200) {
if (data.code == 1) {
this.config.showSuccessMessage && uni.showToast({ title: data.msg, icon: 'none' })
resolve(data)
} else {
@ -99,7 +99,7 @@ class Request {
private request(method : string, url : string, data ?: AnyObject) {
this.requestInterceptors()
Object.assign(this.config, {
const params = Object.assign(uni.$u.deepClone(this.config), {
url: this.baseUrl + url,
method,
data
@ -107,10 +107,10 @@ class Request {
return new Promise((resolve, reject) => {
uni.request({
...this.config,
...params,
success: res => {
const data = res.data
if (data.code == 200) {
if (data.code == 1) {
this.config.showSuccessMessage && uni.showToast({ title: data.msg, icon: 'none' })
resolve(data)
} else {

View File

@ -1,12 +1,15 @@
import wx from 'weixin-js-sdk'
import { getWechatSkdConfig } from '@/api/system'
import { isWeixinBrowser } from '@/utils/common'
class Wechat {
constructor() {
this.init()
// #ifdef H5
// isWeixinBrowser() && this.init()
// #endif
}
private init() {
public init() {
getWechatSkdConfig({
url: uni.getSystemInfoSync().platform == 'ios' ? uni.getStorageSync('initUrl') : location.href
}).then((res : responseResult) => {