提现功能需要添加

This commit is contained in:
bobobobo
2026-01-04 23:35:06 +08:00
parent a4ae562396
commit 42eba945e8
58 changed files with 4825 additions and 1015 deletions

View File

@@ -53,6 +53,9 @@
:placeholder-style="placeholderStyle"
:placeholder="props.placeholder"
/>
<view v-else class="right-box">
<slot name="right"></slot>
</view>
</view>
<view v-if="hasDefaultSlot" class="bottom-slot">
<slot></slot>
@@ -74,6 +77,10 @@
width: 100%;
display: flex;
justify-content: space-between;
.right-box {
display: flex;
align-items: center;
}
}
.bottom-slot {
margin-top: 26rpx;

View File

@@ -0,0 +1,81 @@
<script setup>
import { ref, watch } from 'vue'
const show = defineModel({
type: Boolean,
default: false
})
const name = defineModel('name', {
type: [String, Number],
default: ''
})
const props = defineProps({
title: {
type: String,
default: ''
},
/** 是否为性别选项 */
isSex: {
type: Boolean,
default: false
}
})
const emits = defineEmits(['confirm'])
const inputDialog = ref(null)
watch(
() => show.value,
v => {
if (v) {
// 'bottom'
inputDialog.value.open()
}
}
)
const close = () => {
show.value = false
}
const dialogInputConfirm = () => {
close()
emits('confirm')
}
</script>
<template>
<uni-popup ref="inputDialog" type="dialog">
<uni-popup-dialog
v-model="name"
mode="input"
:title="props.title"
:placeholder="`请输入${props.title}`"
@close="close"
@confirm="dialogInputConfirm"
>
<uni-data-checkbox
v-if="props.isSex"
v-model="name"
:localdata="[
{
text: '男',
value: '0'
},
{
text: '女',
value: '1'
},
{
text: '未知',
value: '2'
}
]"
></uni-data-checkbox>
</uni-popup-dialog>
</uni-popup>
</template>
<style lang="scss" scoped></style>

View File

@@ -52,10 +52,12 @@
>
<view class="left-box">
<image
src="https://wx1.sinaimg.cn/mw690/92eeb099gy1i29hl0ne80j21jk2bcash.jpg"
mode="scaleToFill"
v-if="userInfo?.avatar"
:src="userInfo?.avatar"
mode="aspectFill"
class="avatar"
></image>
<uni-icons v-else type="contact-filled" size="70"></uni-icons>
<view class="nickname">
<text class="name">{{ userInfo?.userName || '' }}</text>
<text class="name">ID:{{ userInfo?.userId || '' }}</text>

View File

@@ -1,27 +1,84 @@
<script setup>
import { reactive } from 'vue'
import { useAuthUser } from '@/composables/useAuthUser'
import PopupBox from '../components/popup-box.vue'
import { chooseImage } from '@/utils/media.js'
import { uploadSingleFile } from '@/utils/uploadFile'
import { useUserStore } from '@/stores/user'
const { updateUserInfo } = useUserStore()
const itemList = [
{ title: '我的二维码', key: '1', value: '' },
{ title: 'ID', key: '2', value: 'userId' },
{ title: '昵称', key: '3', value: 'userName' },
{ title: '性别', key: '4', value: '' },
{ title: '性别', key: '4', value: 'sex' },
{ title: '手机号码', key: '5', value: 'mobile' },
{ title: '个性签名', key: '6', value: '' }
{ title: '个性签名', key: '6', value: 'perSignature' }
]
/** 可修改的 key */
const MODIFY_KEY = ['3', '4', '6']
const { userInfo } = useAuthUser()
const popupData = reactive({
show: false,
title: '修改信息',
name: '',
key: '',
value: ''
})
const formData = reactive({
avatar: '',
userName: '',
sex: '',
perSignature: ''
})
const upInfo = (key, value) => {
if (MODIFY_KEY.includes(key)) {
const titleData = {
3: '昵称',
4: '性别',
6: '个性签名'
}[key]
popupData.value = value
popupData.key = key
popupData.title = titleData
popupData.name = userInfo.value[value]
popupData.show = true
}
}
const editAvatar = async () => {
const paths = await chooseImage({ count: 1 })
const url = await uploadSingleFile(paths[0], {
url: '/api/common/admin/upload/up/single'
})
formData.avatar = url
updateUserInfo({ avatar: url })
}
const onConfirm = () => {
if (MODIFY_KEY.includes(popupData.key)) {
if (popupData.name === userInfo.value[popupData.value]) return
if (popupData.name === '') return
updateUserInfo({ [popupData.value]: popupData.name })
}
}
</script>
<template>
<nav-bar isTopBg isPlaceholder title="个人中心"></nav-bar>
<view class="personal-center">
<view class="public-card">
<view class="public-card" @click="editAvatar">
<view class="left-img">
<image
src="https://p4.itc.cn/images01/20220619/46660ed163164c14be90e605a73ee5e8.jpeg"
v-if="userInfo.avatar"
:src="userInfo.avatar"
mode="aspectFill"
class="avatar"
></image>
<uni-icons v-else type="contact-filled" size="60"></uni-icons>
</view>
<view class="right-box">
<text class="value">换头像</text>
@@ -33,20 +90,37 @@
v-for="(item, index) in itemList"
:key="index"
class="public-card"
@click="upInfo(item.key, item.value)"
>
<view class="left-box">
<text>{{ item.title }}</text>
<text v-if="item.key === '6'" class="text">
这个人很懒什么也没有
{{ userInfo[item.value] || '这个人很懒什么也没有' }}
</text>
</view>
<view class="right-box">
<text v-if="!['1', '6'].includes(item.key)" class="value">
{{ item.value ? userInfo[item.value] : '' }}
</text>
<view v-if="!['1', '6'].includes(item.key)" class="value">
<text v-if="item.key === '4'">
{{
userInfo[item.value] === '2'
? '未设置'
: userInfo[item.value] === '0'
? ''
: ''
}}
</text>
<text v-else>{{ item.value ? userInfo[item.value] : '' }}</text>
</view>
<uni-icons type="right" size="16" color="#999999"></uni-icons>
</view>
</view>
<popup-box
v-model="popupData.show"
v-model:name="popupData.name"
:isSex="popupData.key === '4'"
:title="popupData.title"
@confirm="onConfirm"
/>
</view>
</template>

View File

@@ -59,7 +59,7 @@ page {
}
}
.right-box {
align-items: flex-end;
align-items: center;
.value {
font-weight: 600;
font-size: 28rpx;

View File

@@ -1,14 +1,30 @@
<script setup>
import { onLoad } from '@dcloudio/uni-app'
import { reactive } from 'vue'
import { useUI } from '@/utils/use-ui'
import { navigateBack } from '@/utils/router'
import {
addUserThirdPay,
addUserPayPwd,
getUserThirdPay,
getUserBankDetail
} from '@/api/my-index'
import CardInput from '../../components/card-input.vue'
/** 是否第三方进入 */
const IS_THIRD_PAY = ['101', '102']
const { showToast } = useUI()
const stateData = reactive({
title: '',
state: '0'
state: '0',
loading: true
})
const formData = reactive({
// 修改id
id: '',
// 银行卡名称
name: '',
// 开户行名称
@@ -18,34 +34,131 @@
// 微信/支付宝号
codeName: '',
// 图片链接
img: ''
img: '',
// 银行卡类型
cardType: '',
// 图片回显列表
imgList: []
})
const onAdd = () => {
console.log(formData)
const data = {
bankName: formData.name,
cardNumber: formData.cardNum,
bankName: formData.khName
const onAdd = async () => {
let data = {}
const name = formData.id ? '修改' : '添加'
const method = formData.id ? 'put' : 'post'
if (IS_THIRD_PAY.includes(stateData.state)) {
if (!formData.codeName) {
showToast('请输入账号')
return
}
if (!formData.img) {
showToast('请上传收款码')
return
}
data = {
paymentType: stateData.state === '101' ? 2 : 1,
qrCodeUrl: formData.img,
accountNumber: formData.codeName,
paymentId: formData.id
}
await addUserThirdPay(data, method)
} else {
if (!formData.name) {
showToast('请输入银行名称')
return
}
if (!formData.khName) {
showToast('请输入持卡人姓名')
return
}
if (!formData.cardNum) {
showToast('请输入银行卡号')
return
}
if (!formData.cardType) {
showToast('请选择银行卡类型')
return
}
data = {
bankName: formData.name,
cardHolder: formData.khName,
cardNumber: formData.cardNum,
cardType: formData.cardType,
cardId: formData.id
}
await addUserPayPwd(data, method)
}
await showToast(`${name}成功`, 'success')
navigateBack()
}
/** 获取详情 */
const getDetail = async () => {
stateData.loading = true
const res = await getUserThirdPay(
stateData.state === '101' ? '2' : '1'
)
let titltData = ''
if (res?.data) {
const { paymentId, accountNumber, qrCodeUrl } = res.data
formData.codeName = accountNumber
formData.img = qrCodeUrl
formData.id = paymentId
formData.imgList = [
{
url: qrCodeUrl
}
]
titltData = {
101: '修改支付宝账户',
102: '修改微信账户'
}[stateData.state]
} else {
titltData = {
101: '添加支付宝账户',
102: '添加微信账户'
}[stateData.state]
}
stateData.title = titltData
stateData.loading = false
}
/** 获取对应银行卡详情 */
const getBankDetail = async () => {
stateData.loading = true
const res = await getUserBankDetail(stateData.state)
const { cardId, bankName, cardHolder, cardNumber, cardType } =
res.data
formData.id = cardId
formData.name = bankName
formData.khName = cardHolder
formData.cardNum = cardNumber
formData.cardType = cardType
stateData.title = '修改银行卡'
stateData.loading = false
}
onLoad(e => {
const titltData = {
0: '添加银行卡',
101: '添加支付宝账户',
102: '添加微信账户'
}[e.key]
stateData.title = titltData
stateData.state = e.key
if (IS_THIRD_PAY.includes(e.key)) {
getDetail()
} else {
if (e.key === '0') {
stateData.title = '添加银行卡'
stateData.loading = false
} else {
getBankDetail()
}
}
})
</script>
<template>
<view>
<view v-if="!stateData.loading">
<nav-bar isTopBg isPlaceholder :title="stateData.title">
<template #right>
<text class="public-navbar__right-btn" @click="onAdd">添加</text>
<text class="public-navbar__right-btn" @click="onAdd">
{{ formData.id ? '修改' : '添加' }}
</text>
</template>
</nav-bar>
@@ -54,8 +167,26 @@
class="card-details"
>
<CardInput v-model="formData.name" title="银行名称"></CardInput>
<CardInput v-model="formData.khName" title="开户行"></CardInput>
<CardInput v-model="formData.khName" title="持卡人姓名"></CardInput>
<CardInput v-model="formData.cardNum" title="银行卡号"></CardInput>
<CardInput :isInput="false" title="银行卡类型">
<template #right>
<uni-data-checkbox
v-model="formData.cardType"
:localdata="[
{
text: '借记卡',
value: 1
},
{
text: '信用卡',
value: 2
}
]"
class="card-checkbox"
></uni-data-checkbox>
</template>
</CardInput>
</view>
<view v-else class="card-details">
@@ -65,8 +196,16 @@
stateData.state === '101' ? '支付宝账号' : '微信账号'
}`"
></CardInput>
<CardInput :is-input="false" title="收款码">
<cb-file-picker v-model="formData.img"></cb-file-picker>
<CardInput
:is-input="false"
:title="`${
stateData.state === '101' ? '支付宝' : '微信'
}收款码(必传)`"
>
<cb-file-picker
v-model="formData.img"
v-model:list="formData.imgList"
></cb-file-picker>
</CardInput>
</view>
</view>
@@ -77,4 +216,10 @@
.card-details {
padding: 32rpx 24rpx;
}
.card-checkbox {
:deep(.uni-label-pointer) {
margin: 0 !important;
margin-left: 60rpx !important;
}
}
</style>

View File

@@ -1,56 +1,107 @@
<script setup>
import { ref } from 'vue'
import { navigateTo } from '@/utils/router'
import { onShow } from '@dcloudio/uni-app'
import { getUserBankList, deleteUserPayPwd } from '@/api/my-index'
import { useUI } from '@/utils/use-ui'
const itemList = ref([
{
title: '支付宝',
key: '101',
icon: '/static/images/my-index/zfb.png'
},
{ title: '微信', key: '102', icon: '/static/images/my-index/wx.png' }
])
/** 是否第三方进入 */
const IS_THIRD_PAY = ['0', '101', '102']
const itemList = ref([])
const { showToast, showDialog } = useUI()
const onAddCard = key => {
navigateTo('/pages/my-index/wallet/bank-card/card-details', { key })
}
const getList = async type => {
itemList.value = []
const res = await getUserBankList()
itemList.value = [
{
bankName: '支付宝',
key: '101',
icon: '/static/images/my-index/zfb.png'
},
{
bankName: '微信',
key: '102',
icon: '/static/images/my-index/wx.png'
},
...res.data
]
if (type === 1) {
showToast('删除成功', 'success')
}
}
const onDelete = async id => {
const res = await showDialog('提示', '确定要删除吗?')
if (!res) return
await deleteUserPayPwd(id)
await getList(1)
}
onShow(() => {
getList()
})
</script>
<template>
<view class="bank-card">
<view
v-for="(item, index) in itemList"
:key="index"
class="public-card"
@click="onAddCard(item.key)"
>
<view class="left-img">
<image
:src="
item.icon
? item.icon
: 'https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2024%2F1227%2F842e0e65j00sp543n001fd000i700iim.jpg&thumbnail=660x2147483647&quality=80&type=jpg'
"
mode="aspectFill"
class="card"
></image>
<text>{{ item.title }}</text>
</view>
<view class="right-box">
<uni-icons type="right" size="16" color="#999999"></uni-icons>
</view>
</view>
<uni-swipe-action>
<uni-swipe-action-item
v-for="(item, index) in itemList"
:key="index"
:disabled="!!item.key"
class="card-box"
>
<view
class="public-card"
@click="onAddCard(item.key || item.cardId)"
>
<view class="left-img">
<image
v-if="item.icon"
:src="item.icon"
mode="aspectFill"
class="card"
></image>
<text>{{ item.bankName }}</text>
</view>
<view class="right-box">
<text v-if="item.cardNumber">{{ item.cardNumber }}</text>
<uni-icons type="right" size="16" color="#999999"></uni-icons>
</view>
</view>
<template v-slot:right>
<view
class="public-uni-swipe-action-right"
@click="onDelete(item.cardId)"
>
<uni-icons type="trash" size="18" color="#ffffff"></uni-icons>
<text class="iocn-name">删除</text>
</view>
</template>
</uni-swipe-action-item>
</uni-swipe-action>
<!-- 底部按钮 -->
<bottom-view>
<bottom-view v-if="itemList.length > 0">
<cb-button @click="onAddCard('0')">+添加银行卡</cb-button>
</bottom-view>
</view>
</template>
<style lang="scss" scoped>
@import '@/styles/global.scss';
@import '../../styles/index.scss';
.bank-card {
padding: 38rpx 24rpx;
}
.card-box + .card-box {
margin-top: 16rpx;
}
</style>

View File

@@ -1,12 +1,17 @@
<script setup>
import { onLoad } from '@dcloudio/uni-app'
import { reactive } from 'vue'
import CardInput from '../components/card-input.vue'
import { useUI } from '@/utils/use-ui'
import { navigateBack } from '@/utils/router'
import { validateTransactionPassword } from '@/utils/validate'
import { updateUserPayPwd, getUserPayPwd } from '@/api/my-index'
const { showToast } = useUI()
const formData = reactive({
id: '',
state: '0',
// 旧密码
password: '',
// 新密码
@@ -14,41 +19,72 @@
// 确认密码
confirmPassword: ''
})
const onEdit = () => {
const passwordValue = validateTransactionPassword(
formData.password,
'旧密码'
)
if (!passwordValue.valid) {
showToast(passwordValue.message)
return
const onEdit = async () => {
let data = {}
if (formData.state === '1') {
const passwordValue = validateTransactionPassword(
formData.password,
'旧密码'
)
if (!passwordValue.valid) {
showToast(passwordValue.message)
return
}
const newPasswordValue = validateTransactionPassword(
formData.newPassword,
'新的交易密码'
)
if (!newPasswordValue.valid) {
showToast(newPasswordValue.message)
return
}
const confirmPasswordValue = validateTransactionPassword(
formData.confirmPassword,
'确认交易密码'
)
if (!confirmPasswordValue.valid) {
showToast(confirmPasswordValue.message)
return
}
if (formData.newPassword !== formData.confirmPassword) {
showToast('两次密码不一致')
return
}
data = {
id: formData.id,
oldPassword: formData.password,
password: formData.confirmPassword
}
} else {
if (!formData.password) {
showToast('请输入设置交易密码')
return
}
data = {
password: formData.password
}
}
const newPasswordValue = validateTransactionPassword(
formData.newPassword,
'新的交易密码'
)
if (!newPasswordValue.valid) {
showToast(newPasswordValue.message)
return
}
const confirmPasswordValue = validateTransactionPassword(
formData.confirmPassword,
'确认交易密码'
)
if (!confirmPasswordValue.valid) {
showToast(confirmPasswordValue.message)
return
}
if (formData.newPassword !== formData.confirmPassword) {
showToast('两次密码不一致')
return
}
console.log('修改密码:', formData)
await updateUserPayPwd(data, formData.id ? 'put' : 'post')
await showToast(`${formData.id ? '修改' : '添加'}成功`, 'success')
navigateBack()
}
const getData = async () => {
const res = await getUserPayPwd()
formData.id = res.data.id
}
onLoad(e => {
formData.state = e.type
if (e.type === '1') {
getData()
}
})
</script>
<template>
@@ -59,7 +95,7 @@
</template>
</nav-bar>
<view class="input-box">
<view v-if="formData.state === '1'" class="input-box">
<CardInput
v-model="formData.password"
title="旧密码"
@@ -76,6 +112,13 @@
type="password"
></CardInput>
</view>
<view v-else class="input-box">
<CardInput
v-model="formData.password"
title="设置交易密码"
type="password"
></CardInput>
</view>
</view>
</template>

View File

@@ -1,26 +1,38 @@
<script setup>
import { ref } from 'vue'
import { navigateTo } from '@/utils/router'
import { onShow } from '@dcloudio/uni-app'
import { getUserPayPwd } from '@/api/my-index'
import { useAuthUser } from '@/composables/useAuthUser'
const itemList = [
{
title: '提现卡',
key: '1',
url: '/pages/my-index/wallet/bank-card/index'
},
{ title: '交易记录', key: '2', url: '' },
{
title: '修改支付密码',
key: '3',
url: '/pages/my-index/wallet/edit-password'
},
{ title: '实名认证', key: '4', url: '/pages/my-index/wallet/real-id' }
]
const { userInfo } = useAuthUser()
const itemList = ref([])
const getData = async () => {
itemList.value = []
const res = await getUserPayPwd()
console.log(res, '===')
const isSetPayPwd = res?.data ? '修改支付密码' : '设置支付密码'
itemList.value = [
{
title: '提现卡',
key: '1',
url: '/pages/my-index/wallet/bank-card/index'
},
{ title: '交易记录', key: '2', url: '' },
{
title: isSetPayPwd,
key: '3',
isType: !!res?.data,
url: '/pages/my-index/wallet/edit-password'
},
{
title: '实名认证',
key: '4',
url: '/pages/my-index/wallet/real-id'
}
]
}
onShow(() => {
@@ -34,7 +46,7 @@
<view class="top-card">
<view class="left-box">
<text>我的资产</text>
<text>1222</text>
<text>{{ userInfo?.totalPoints }}</text>
</view>
<view class="right-box">
<button>充值</button>
@@ -46,7 +58,13 @@
v-for="(item, index) in itemList"
:key="index"
class="public-card"
@click="item.url && navigateTo(item.url)"
@click="
item.url &&
navigateTo(
item.url,
item.key === '3' ? { type: item.isType ? 1 : 0 } : null
)
"
>
<view class="left-box">
<text>{{ item.title }}</text>

View File

@@ -1,44 +1,121 @@
<script setup>
import { reactive } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { ref, reactive } from 'vue'
import CardInput from '../components/card-input.vue'
import { useUI } from '@/utils/use-ui'
import { navigateBack } from '@/utils/router'
import { getUserIdCard, addUserIdCard } from '@/api/my-index'
import { validateIdCard } from '@/utils/validate'
const { showToast } = useUI()
const loading = ref(true)
const formData = reactive({
// 修改id
id: '',
// 正面
front: '',
// 背面
back: '',
// 手机号
phone: '',
// 姓名
realName: '',
// 身份证号码
idCard: ''
idCard: '',
frontList: [],
backList: []
})
const getData = async () => {
loading.value = true
const res = await getUserIdCard()
if (res?.data) {
formData.id = res.data.id
formData.front = res.data.idCardFrontUrl
formData.back = res.data.idCardBackUrl
formData.realName = res.data.realName
formData.idCard = res.data.idCardNumber
formData.frontList = [{ url: res.data.idCardFrontUrl }]
formData.backList = [{ url: res.data.idCardBackUrl }]
}
loading.value = false
}
const onAddCode = async () => {
if (!formData.front) {
showToast('请上传身份证人像面')
return
}
if (!formData.back) {
showToast('请上传身份证国徽面')
return
}
if (!formData.realName) {
showToast('请输入姓名')
return
}
const codeData = validateIdCard(formData.idCard)
if (!codeData.valid) {
showToast(codeData.message)
return
}
const data = {
idCardFrontUrl: formData.front,
idCardBackUrl: formData.back,
realName: formData.realName,
idCardNumber: formData.idCard
}
await addUserIdCard(data)
await showToast(`添加成功`, 'success')
navigateBack()
}
onLoad(() => {
getData()
})
</script>
<template>
<view class="real-id">
<view v-if="!loading" class="real-id">
<!-- 说明 -->
<text class="top-text">*为保证您的账户安全,请先完成实名认证</text>
<CardInput :is-input="false" title="收款码">
<view class="qrcode-box">
<cb-file-picker v-model="formData.front" isFront></cb-file-picker>
<cb-file-picker v-model="formData.back" isBack></cb-file-picker>
<cb-file-picker
v-model="formData.front"
v-model:list="formData.frontList"
isFront
></cb-file-picker>
<cb-file-picker
v-model="formData.back"
v-model:list="formData.backList"
isBack
></cb-file-picker>
</view>
</CardInput>
<CardInput
v-model="formData.phone"
title="手机号"
type="tel"
placeholder="请输入手机号"
v-model="formData.realName"
title="姓名"
placeholder="请输入姓名"
></CardInput>
<CardInput
v-model="formData.idCard"
type="text"
title="身份证号"
placeholder="请输入身份证号"
></CardInput>
<!-- 底部按钮 -->
<bottom-view>
<cb-button @click="onAddCode">
确认{{ formData.id ? '修改' : '添加' }}
</cb-button>
</bottom-view>
</view>
</template>