This commit is contained in:
全栈小学生 2023-06-02 19:12:27 +08:00
parent 05a8c49ce6
commit 0825a05f0e
9 changed files with 321 additions and 287 deletions

View File

@ -67,5 +67,5 @@ export function bind(data : AnyObject) {
* 访
*/
export function memberLog(data : AnyObject) {
return request.post('member/log', data)
return request.post('member/log', data, { showErrorMessage: false })
}

View File

@ -1,11 +1,5 @@
<template>
<view :style="warpCss">
<!-- #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">
<!-- 唤起获取微信 -->
@ -102,12 +96,14 @@
const memberStore = useMemberStore()
// #ifdef H5
const { query } = urlDeconstruction(location.href)
if (query.code && isWeixinBrowser()) {
wechatSync({ code: query.code }).then(res => {
memberStore.getMemberInfo()
})
}
// #endif
const info = computed(() => {
//

View File

@ -1,122 +1,124 @@
<template>
<u-popup :show="show" :round="10" @close="show = false" :closeable="true">
<view class="mx-[30rpx] pb-[20rpx] pt-[40rpx] border-t">
<view class="text-base">{{ t('getAvatarNickname') }}</view>
<view class="text-sm mt-[18rpx] text-gray-400">{{ t('getAvatarNicknameTips') }}</view>
</view>
<u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef">
<view class="mx-[30rpx]">
<view class="mt-[20rpx]">
<u-form-item :label="t('headimg')" prop="headimg" :border-bottom="true">
<button class="m-0 my-[10rpx] p-0 w-[140rpx] h-[140rpx]" open-type="chooseAvatar"
@chooseavatar="onChooseAvatar">
<view class="w-full h-full flex items-center justify-center overflow-hidden">
<u-image :src="img(formData.headimg)" width="140rpx" v-if="formData.headimg"></u-image>
<u-icon name="plus" v-else></u-icon>
</view>
</button>
</u-form-item>
<u-form-item :label=" t('nickname')" prop="nickname" :border-bottom="true">
<input type="nickname" v-model="formData.nickname" :placeholder="t('nicknamePlaceholder')"
@blur="bindNickname">
</u-form-item>
</view>
</view>
<view class="p-[30rpx] mt-[20rpx]">
<u-button type="primary" :loading="loading" :text="t('confirm')" shape="circle"
@click="confirm"></u-button>
</view>
</u-form>
</u-popup>
<u-popup :show="show" :round="10" @close="show = false" :closeable="true">
<view class="mx-[30rpx] pb-[20rpx] pt-[40rpx] border-t">
<view class="text-base">{{ t('getAvatarNickname') }}</view>
<view class="text-sm mt-[18rpx] text-gray-400">{{ t('getAvatarNicknameTips') }}</view>
</view>
<u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef">
<view class="mx-[30rpx]">
<view class="mt-[20rpx]">
<u-form-item :label="t('headimg')" prop="headimg" :border-bottom="true">
<button class="m-0 my-[10rpx] p-0 w-[140rpx] h-[140rpx]" open-type="chooseAvatar"
@chooseavatar="onChooseAvatar">
<view class="w-full h-full flex items-center justify-center overflow-hidden">
<u-image :src="img(formData.headimg)" width="140rpx" v-if="formData.headimg"></u-image>
<u-icon name="plus" v-else></u-icon>
</view>
</button>
</u-form-item>
<u-form-item :label=" t('nickname')" prop="nickname" :border-bottom="true">
<input type="nickname" v-model="formData.nickname" :placeholder="t('nicknamePlaceholder')"
@blur="bindNickname">
</u-form-item>
</view>
</view>
<view class="p-[30rpx] mt-[20rpx]">
<u-button type="primary" :loading="loading" :text="t('confirm')" shape="circle"
@click="confirm"></u-button>
</view>
</u-form>
</u-popup>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { t } from '@/locale'
import useMemberStore from '@/stores/member'
import { img } from '@/utils/common'
import { modifyMember } from '@/api/member'
import { fetchBase64Image } from '@/api/system'
import { ref, reactive, computed, watch } from 'vue'
import { t } from '@/locale'
import useMemberStore from '@/stores/member'
import { img } from '@/utils/common'
import { modifyMember } from '@/api/member'
import { fetchBase64Image } from '@/api/system'
const show = ref(false)
const loading = ref(false)
const memberStore = useMemberStore()
const info = computed(() => memberStore.info)
const show = ref(false)
const loading = ref(false)
const memberStore = useMemberStore()
const info = computed(() => memberStore.info)
const formData = reactive({
nickname: '',
headimg: ''
})
const formData = reactive({
nickname: '',
headimg: ''
})
watch(() => info.value, () => {
formData.nickname = info.value.nickname
formData.headimg = info.value.headimg
}, { immediate: true })
watch(() => info.value, () => {
if (info.value) {
formData.nickname = info.value.nickname
formData.headimg = info.value.headimg
}
}, { immediate: true })
const onChooseAvatar = (e) => {
uni.getFileSystemManager().readFile({
filePath: e.detail.avatarUrl, //
encoding: 'base64', //
success: res => {
fetchBase64Image({ content: res.data }).then(uploadRes => {
formData.headimg = uploadRes.data.url
})
}
})
}
const onChooseAvatar = (e) => {
uni.getFileSystemManager().readFile({
filePath: e.detail.avatarUrl, //
encoding: 'base64', //
success: res => {
fetchBase64Image({ content: res.data }).then(uploadRes => {
formData.headimg = uploadRes.data.url
})
}
})
}
const bindNickname = (e) => {
formData.nickname = e.detail.value
}
const bindNickname = (e) => {
formData.nickname = e.detail.value
}
const rules = {
'headimg': {
type: 'string',
required: true,
message: t('headimgPlaceholder'),
trigger: ['blur', 'change'],
},
'nickname': {
type: 'string',
required: true,
message: t('nicknamePlaceholder'),
trigger: ['blur', 'change'],
}
}
const rules = {
'headimg': {
type: 'string',
required: true,
message: t('headimgPlaceholder'),
trigger: ['blur', 'change'],
},
'nickname': {
type: 'string',
required: true,
message: t('nicknamePlaceholder'),
trigger: ['blur', 'change'],
}
}
const formRef = ref(null)
const formRef = ref(null)
const confirm = async () => {
formRef.value.validate().then(async () => {
if (loading.value) return
loading.value = true
const confirm = async () => {
formRef.value.validate().then(async () => {
if (loading.value) return
loading.value = true
//
await modifyMember({ field: 'headimg', value: formData.headimg })
.then(() => {
memberStore.info.headimg = formData.headimg
})
.catch(() => {
loading.value = false
})
if (!loading.value) return
//
await modifyMember({ field: 'headimg', value: formData.headimg })
.then(() => {
memberStore.info.headimg = formData.headimg
})
.catch(() => {
loading.value = false
})
if (!loading.value) return
//
modifyMember({ field: 'nickname', value: formData.nickname })
.then(() => {
memberStore.info.nickname = formData.nickname
loading.value = false
show.value = false
})
.catch(() => {
loading.value = false
})
})
}
//
modifyMember({ field: 'nickname', value: formData.nickname })
.then(() => {
memberStore.info.nickname = formData.nickname
loading.value = false
show.value = false
})
.catch(() => {
loading.value = false
})
})
}
defineExpose({
show
})
defineExpose({
show
})
</script>
<style lang="scss" scoped></style>

View File

@ -23,7 +23,7 @@
<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 class="py-[20rpx] text-center text-sm text-gray-subtitle" v-else>{{ t('pay.notHavePayType') }}</view>
</view>
</scroll-view>
<view class="p-[30rpx]">

View File

@ -31,8 +31,10 @@ export const useShare = () => {
const setShare = async (options : any = {}) => {
let memberStore = useMemberStore();
// #ifdef H5
// 初始化sdk
await wechatInit();
// #endif
if (options && options.wechat && options.weapp) {
let query = currShareRoute().params;
@ -64,30 +66,30 @@ export const useShare = () => {
}
} else {
getShareInfo({ route: '/' + currRoute(), params: JSON.stringify(currShareRoute().params) }).then((res : any) => {
let data = res.data;
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

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

View File

@ -8,7 +8,7 @@
<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]"
:src="img('static/resource/images/member/apply_withdrawal/close.png')" class="w-[40rpx] h-[40rpx]"
mode="widthFix" />
</view>
<view class="pt-[20rpx]">

View File

@ -1,20 +1,24 @@
<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%)'}">
<u-loading-page :loading="loading" loadingText=""></u-loading-page>
<view class="account-info-wrap" v-show="!loading">
<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 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-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-item"
@click="redirect({ url: '/pages/member/detailed_account', param: { type : 'money' } })">
<view class="money">
{{ moneyFormat(memberStore.info?.money)|| '0.00' }}
</view>
@ -28,18 +32,19 @@
<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>
<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>
<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>
<!-- 充值 -->
<u-popup :show="topUpShow" mode="center" :round="10" @close="closePopup" :closeable="true">
<view class="w-80 px-3 pb-4 pt-7 box-border">
@ -101,6 +106,8 @@
transfer_type: [] //
})
const loading = ref(true);
onShow(() => {
// h5
// #ifdef H5
@ -108,9 +115,10 @@
// #endif
cashOutConfig().then((res) => {
for (let key in res.data) {
cashOutConfigObj[key] = res.data[key];
}
for (let key in res.data) {
cashOutConfigObj[key] = res.data[key];
}
loading.value = false;
})
})
@ -135,11 +143,11 @@
rechargeLoading.value = false
})
}
const applyCashOut = ()=> {
uni.setStorageSync('cashOutAccountType', 'money')
redirect({ url: '/pages/member/apply_cash_out' })
}
const applyCashOut = () => {
uni.setStorageSync('cashOutAccountType', 'money')
redirect({ url: '/pages/member/apply_cash_out' })
}
</script>
<style lang="scss" scoped>

View File

@ -3,156 +3,170 @@ import { t } from '@/locale'
import { getToken, getAppChannel, getSiteId } from './common'
interface RequestConfig {
showErrorMessage ?: boolean
showSuccessMessage ?: boolean
showErrorMessage ?: boolean
showSuccessMessage ?: boolean
}
interface RequestOptions extends UniNamespace.RequestOptions, RequestOptions { }
class Request {
private baseUrl : string
private baseUrl : string
private config : RequestOptions = {
url: '',
header: {}
}
private config : RequestOptions = {
url: '',
header: {}
}
constructor() {
// #ifdef H5
this.baseUrl = import.meta.env.VITE_APP_BASE_URL || `${location.origin}/api/`
// #endif
// #ifndef H5
this.baseUrl = import.meta.env.VITE_APP_BASE_URL
// #endif
if (process.env.NODE_ENV == 'development') {
this.config.header[import.meta.env.VITE_REQUEST_HEADER_SITEID_KEY] = getSiteId(uni.getStorageSync('wap_site_id') || import.meta.env.VITE_SITE_ID)
} else {
this.config.header[import.meta.env.VITE_REQUEST_HEADER_SITEID_KEY] = getSiteId(import.meta.env.VITE_SITE_ID)
}
constructor() {
// #ifdef H5
this.baseUrl = import.meta.env.VITE_APP_BASE_URL || `${location.origin}/api/`
// #endif
this.config.header[import.meta.env.VITE_REQUEST_HEADER_CHANNEL_KEY] = getAppChannel()
}
// #ifndef H5
this.baseUrl = import.meta.env.VITE_APP_BASE_URL
// #endif
/**
*
*/
private requestInterceptors() {
// 携带token site-id
getToken() && (this.config.header[import.meta.env.VITE_REQUEST_HEADER_TOKEN_KEY] = getToken())
}
try {
if (process.env.NODE_ENV == 'development') {
this.config.header[import.meta.env.VITE_REQUEST_HEADER_SITEID_KEY] = getSiteId(uni.getStorageSync('wap_site_id') || import.meta.env.VITE_SITE_ID)
} else {
this.config.header[import.meta.env.VITE_REQUEST_HEADER_SITEID_KEY] = getSiteId(import.meta.env.VITE_SITE_ID)
}
this.config.header[import.meta.env.VITE_REQUEST_HEADER_CHANNEL_KEY] = getAppChannel()
} catch (e) {
}
public get(url : string, data : AnyObject = {}, config : RequestConfig = {}) {
Object.assign(this.config, config)
return this.request('GET', url, data)
}
}
public post(url : string, data : AnyObject = {}, config : RequestConfig = {}) {
Object.assign(this.config, config)
return this.request('POST', url, data)
}
/**
*
*/
private requestInterceptors() {
// 携带token site-id
try {
getToken() && (this.config.header[import.meta.env.VITE_REQUEST_HEADER_TOKEN_KEY] = getToken())
this.config.header[import.meta.env.VITE_REQUEST_HEADER_CHANNEL_KEY] = getAppChannel()
if (process.env.NODE_ENV == 'development') {
this.config.header[import.meta.env.VITE_REQUEST_HEADER_SITEID_KEY] = getSiteId(uni.getStorageSync('wap_site_id') || import.meta.env.VITE_SITE_ID)
} else {
this.config.header[import.meta.env.VITE_REQUEST_HEADER_SITEID_KEY] = getSiteId(import.meta.env.VITE_SITE_ID)
}
} catch (e) {
}
}
public put(url : string, data : AnyObject = {}, config : RequestConfig = {}) {
Object.assign(this.config, config)
return this.request('PUT', url, data)
}
public get(url : string, data : AnyObject = {}, config : RequestConfig = {}) {
Object.assign(this.config, config)
return this.request('GET', url, data)
}
public delete(url : string, config : RequestConfig = {}) {
Object.assign(this.config, config)
return this.request('DELETE', url)
}
public post(url : string, data : AnyObject = {}, config : RequestConfig = {}) {
Object.assign(this.config, config)
return this.request('POST', url, data)
}
/**
*
*/
public upload(url : string, data : AnyObject = {}, config : RequestConfig = {}) {
this.requestInterceptors()
const params = Object.assign(uni.$u.deepClone(this.config), {
url: this.baseUrl + url,
...data
})
return new Promise((resolve, reject) => {
uni.uploadFile({
...params,
success: res => {
const data = JSON.parse(res.data)
if (data.code == 1) {
this.config.showSuccessMessage && uni.showToast({ title: data.msg, icon: 'none' })
resolve(data)
} else {
this.handleAuthError(data.code)
this.config.showErrorMessage && uni.showToast({ title: data.msg, icon: 'none' })
reject(data)
}
},
fail: res => {
reject(res)
}
})
})
}
public put(url : string, data : AnyObject = {}, config : RequestConfig = {}) {
Object.assign(this.config, config)
return this.request('PUT', url, data)
}
/**
*
*/
private request(method : string, url : string, data ?: AnyObject) {
this.requestInterceptors()
public delete(url : string, config : RequestConfig = {}) {
Object.assign(this.config, config)
return this.request('DELETE', url)
}
const params = Object.assign(uni.$u.deepClone(this.config), {
url: this.baseUrl + url,
method,
data
})
/**
*
*/
public upload(url : string, data : AnyObject = {}, config : RequestConfig = {}) {
this.requestInterceptors()
return new Promise((resolve, reject) => {
uni.request({
...params,
success: res => {
const data = res.data
if (data.code == 1) {
this.config.showSuccessMessage && uni.showToast({ title: data.msg, icon: 'none' })
resolve(data)
} else {
this.handleAuthError(data.code)
this.config.showErrorMessage && uni.showToast({ title: data.msg, icon: 'none' })
reject(data)
}
},
fail: res => {
reject(res)
},
complete: (res) => {
this.handleRequestFail(res)
}
})
})
}
const params = Object.assign(uni.$u.deepClone(this.config), {
url: this.baseUrl + url,
...data
})
private handleAuthError(code : number) {
switch (code) {
case 401:
useMemberStore().logout()
break;
}
}
private handleRequestFail(res) {
if (res.errMsg && res.errMsg == "request:ok") {
if (typeof res.data == 'string') {
uni.showToast({ icon: 'none', title: this.baseUrl + t('requestFail') })
return
}
}
if (res.errMsg == 'request:fail') {
uni.showToast({ icon: 'none', title: this.baseUrl + t('requestFail') })
return
}
if (res.errMsg && res.errMsg == 'request:fail url not in domain list') {
uni.showToast({ icon: 'none', title: this.baseUrl + t('notInDomainList') });
return
}
}
return new Promise((resolve, reject) => {
uni.uploadFile({
...params,
success: res => {
const data = JSON.parse(res.data)
if (data.code == 1) {
this.config.showSuccessMessage && uni.showToast({ title: data.msg, icon: 'none' })
resolve(data)
} else {
this.handleAuthError(data.code)
this.config.showErrorMessage && uni.showToast({ title: data.msg, icon: 'none' })
reject(data)
}
},
fail: res => {
reject(res)
}
})
})
}
/**
*
*/
private request(method : string, url : string, data ?: AnyObject) {
this.requestInterceptors()
const params = Object.assign(uni.$u.deepClone(this.config), {
url: this.baseUrl + url,
method,
data
})
return new Promise((resolve, reject) => {
uni.request({
...params,
success: res => {
const data = res.data
if (data.code == 1) {
this.config.showSuccessMessage && uni.showToast({ title: data.msg, icon: 'none' })
resolve(data)
} else {
this.handleAuthError(data.code)
this.config.showErrorMessage && uni.showToast({ title: data.msg, icon: 'none' })
reject(data)
}
},
fail: res => {
reject(res)
},
complete: (res) => {
this.handleRequestFail(res)
}
})
})
}
private handleAuthError(code : number) {
switch (code) {
case 401:
useMemberStore().logout()
break;
}
}
private handleRequestFail(res) {
if (res.errMsg && res.errMsg == "request:ok") {
if (typeof res.data == 'string') {
uni.showToast({ icon: 'none', title: this.baseUrl + t('requestFail') })
return
}
}
if (res.errMsg == 'request:fail') {
uni.showToast({ icon: 'none', title: this.baseUrl + t('requestFail') })
return
}
if (res.errMsg && res.errMsg == 'request:fail url not in domain list') {
uni.showToast({ icon: 'none', title: this.baseUrl + t('notInDomainList') });
return
}
}
}
export default new Request()