钱包转账

This commit is contained in:
weiwei committed 2025-04-02 19:27:23 +08:00
1 parent fb82c9d3a1
commit 03adc25ca2
10 files changed
+722 -481

No files matched your search

+2 -83
View File
@@ -9,63 +9,7 @@
</tm-sheet>
<tm-button class="mt-40" :block="true" @click="disabled ? '' : handlePay()" :disabled="disabled">支付</tm-button>
<view class="bg-[#f5f5f5] px-1 py-2 rounded-4 absolute bottom-0 w-full">
<view class="flex mb-2.5" v-for="(row, rowIndex) in keyboardLayout" :key="rowIndex">
<view
class="flex-1 h-[60px] flex items-center justify-center bg-white text-2xl text-[#333] mx-[5px] rounded-lg cursor-pointer select-none active:bg-[#f0f0f0]"
v-for="(key, keyIndex) in row"
:key="keyIndex"
@click="handleKeyPress(key)"
>
{{ key }}
</view>
</view>
<view class="flex mb-0">
<view
class="flex-1 h-[60px] flex items-center justify-center bg-white text-2xl text-[#333] mx-[5px] rounded-lg cursor-pointer select-none active:bg-[#f0f0f0]"
@click="handleKeyPress('.')"
>
.
</view>
<view
class="flex-auto h-[60px] flex items-center justify-center bg-white text-2xl text-[#333] mx-[5px] rounded-lg cursor-pointer select-none active:bg-[#f0f0f0]"
@click="handleKeyPress('0')"
>
0
</view>
<view
class="flex-1 h-[60px] flex items-center justify-center bg-white mx-[5px] rounded-lg cursor-pointer select-none active:bg-[#f0f0f0]"
@click="handleDelete"
>
<svg
t="1742457305987"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="4499"
width="24"
height="24"
>
<path
d="M897.706667 831.146667H286.72c-8.533333 0-15.36-3.413333-20.48-10.24L39.253333 527.36c-6.826667-8.533333-6.826667-22.186667 0-30.72l226.986667-293.546667c5.12-6.826667 11.946667-10.24 20.48-10.24h610.986667c51.2 0 92.16 40.96 92.16 92.16v453.973334c0 51.2-40.96 92.16-92.16 92.16z m-599.04-51.2h599.04c22.186667 0 40.96-18.773333 40.96-40.96V285.013333c0-22.186667-18.773333-40.96-40.96-40.96H298.666667L92.16 512l206.506667 267.946667z"
fill="#333333"
p-id="4500"
></path>
<path
d="M670.72 650.24c-6.826667 0-13.653333-1.706667-18.773333-6.826667L426.666667 416.426667c-10.24-10.24-10.24-25.6 0-35.84 10.24-10.24 25.6-10.24 35.84 0l226.986666 226.986666c10.24 10.24 10.24 25.6 0 35.84-6.826667 5.12-11.946667 6.826667-18.773333 6.826667z"
fill="#333333"
p-id="4501"
></path>
<path
d="M443.733333 650.24c-6.826667 0-13.653333-1.706667-18.773333-6.826667-10.24-10.24-10.24-25.6 0-35.84l226.986667-226.986666c10.24-10.24 25.6-10.24 35.84 0 10.24 10.24 10.24 25.6 0 35.84L462.506667 643.413333c-5.12 5.12-11.946667 6.826667-18.773334 6.826667z"
fill="#333333"
p-id="4502"
></path>
</svg>
</view>
</view>
</view>
<numberKeyboard v-model="amount" />
</view>
</crud-layout>
</template>
@@ -78,13 +22,9 @@ import payApi from "@@/api/pay"
import { storePrice } from "@/sheep/utils/formatMoney"
import { router } from "@/sheep"
import { merchantApi } from "@/sheep/api"
import numberKeyboard from "@/sheep/components/numberKeyboard.vue"
const amount = ref("")
const keyboardLayout = ref([
["1", "2", "3"],
["4", "5", "6"],
["7", "8", "9"],
])
const scanData = ref<{ id?: string; name?: string }>({})
const disabled = ref(false)
@@ -113,27 +53,6 @@ const displayAmount = computed(() => {
)
})
// 按下键盘
const handleKeyPress = (key) => {
if (key === "." && amount.value.includes(".")) return
if (key === "." && !amount.value) {
amount.value = "0."
return
}
if (amount.value.includes(".")) {
const decimalPlaces = amount.value.split(".")[1]
if (decimalPlaces && decimalPlaces.length >= 2) return
}
amount.value += key
}
// 点击删除
const handleDelete = () => {
amount.value = amount.value.slice(0, -1)
}
// 点击支付
const handlePay = () => {
if (!scanData.value.id || !scanData.value.name) return uni.showToast({ title: "扫码信息不存在", icon: "none" })
+190
View File
@@ -0,0 +1,190 @@
<template>
<view class="bg-gray-100 flex-col min-h-screen">
<view class="flex-row items-center justify-center my-2">
<text class="text-lg font-bold">转入{{ state.targetWalletTypeName }}</text>
</view>
<tm-cell
title="转入方式"
icon="money-cny-circle-fill"
icon-color="#0779FD"
iconSize="64"
:label="state.sourceWalletTypeName"
labelColor="#7f7f7f"
labelSize="30"
@click="sourceWalletSelect"
/>
<tm-sheet>
<text class="text-gray-700 font-bold text-lg">转入金额</text>
<view class="flex-row items-center">
<text class="text-3xl text-[#333] mr-2">¥</text>
<text v-if="!amount" class="text-xl text-gray-300">转入金额</text>
<text v-else class="text-3xl">{{ formattedAmount }}</text>
</view>
</tm-sheet>
<!-- 金额限制提示 -->
<view class="h-30rpx">
<view v-if="storePrice(amount) > curSourceWallet?.balance" class="text-xs c-red px-8">注:转账金额不能超过钱包余额</view>
</view>
<view class="p-4 font-bold mt-10">
<tm-button block @click="confirmTransfer">确定转入</tm-button>
</view>
<number-keyboard v-model="amount" />
<!-- 选择转入方式 -->
<tm-drawer
v-model:show="show"
title="选择转入方式"
size="50%"
bg-color="#efefef"
position="bottom"
:show-footer="true"
:showClose="true"
>
<view class="m-4">
<view
v-for="(v, index) in state.walletList"
:key="index"
class="card mb-2 overflow-hidden relative border-4 border-solid border-white duration-200 flex justify-between items-center p-4"
:class="{ 'border-4 border-solid border-blue!': state.sourceWalletTypeId == v.walletTypeId }"
@click="state.sourceWalletTypeId = v.walletTypeId"
>
<view class="flex items-center">
<image class="w-70 h-70 mr-2" :src="filePath(v.walletTypeIcon)" />
<view class="flex flex-col">
<view class="main-text-32">{{ v.walletTypeName }}</view>
<view class="text-gray-500 text-sm">{{ v.cardNumber }}</view>
</view>
</view>
<view class="main-text-32">余额:{{ hooks.useMoney(v.balance) + "元" }}</view>
</view>
</view>
<template #footer>
<tm-button block @click="confirmSourceWallet" class="flex-1 font-bold">确定</tm-button>
</template>
</tm-drawer>
</view>
</template>
<script setup lang="ts">
import { ref, computed, reactive } from "vue"
import { onLoad } from "@dcloudio/uni-app"
import NumberKeyboard from "@/sheep/components/numberKeyboard.vue"
import { payApi, walletApi } from "@/sheep/api"
import { hooks, router } from "@@/index"
import { filePath } from "@/sheep/utils/file"
import { storePrice } from "@/sheep/utils/formatMoney"
const amount = ref("")
const show = ref(false)
const state = reactive<any>({
targetWalletTypeId: "",
targetWalletTypeName: "",
walletList: [],
sourceWalletTypeId: "",
sourceWalletTypeName: "",
})
const curSourceWallet = computed(() => {
if (!state.sourceWalletTypeId) {
state.sourceWalletTypeId = state.walletList[0]?.walletTypeId
state.sourceWalletTypeName = state.walletList[0]?.walletTypeName
return state.walletList[0]
}
return state.walletList.find((item: any) => item.walletTypeId == state.sourceWalletTypeId)
})
onLoad(async (options) => {
if (options?.walletTypeId) {
state.targetWalletTypeId = options.walletTypeId
state.targetWalletTypeName = options.walletTypeName
} else {
uni.showToast({ title: "钱包id不存在", icon: "none" })
}
const res = await walletApi.all()
if (res.code == 0) {
state.walletList = res.data.records.filter((item: any) => item.walletTypeId != state.targetWalletTypeId)
}
})
// 源钱包选择
const sourceWalletSelect = () => {
state.sourceWalletTypeId = ""
show.value = true
}
// 确认源钱包
const confirmSourceWallet = () => {
show.value = false
state.sourceWalletTypeName = state.walletList.find((item: any) => item.walletTypeId == state.sourceWalletTypeId).walletTypeName
}
// 格式化金额显示
const formattedAmount = computed(() => {
if (!amount.value) return ""
// 处理小数点情况
if (amount.value.endsWith(".")) {
return amount.value
}
const parts = amount.value.split(".")
// 添加千位分隔符
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",")
// 处理小数部分
if (parts.length > 1) {
// 如果小数部分不足两位,不自动补零
return `${parts[0]}.${parts[1]}`
}
return parts[0]
})
// 确认转账
const confirmTransfer = async () => {
if (!amount.value || amount.value === "0" || amount.value === "0." || parseFloat(amount.value) === 0) {
return uni.showToast({ title: "金额不能为零", icon: "none" })
}
const numAmount = storePrice(parseFloat(amount.value.endsWith(".") ? amount.value.slice(0, -1) : amount.value))
if (numAmount > curSourceWallet.value.balance) {
return uni.showToast({ title: "转账金额不能超过钱包余额", icon: "none" })
}
// console.log("state.sourceWalletTypeId", state.sourceWalletTypeId)
// console.log("state.targetWalletTypeId", state.targetWalletTypeId)
// console.log("金额", numAmount)
uni.showModal({
title: "确定转入吗?",
success: async (res) => {
if (res.confirm) {
try {
uni.showLoading({ title: "正在转入...", mask: true })
const res = await payApi.transferMoney({
sourceWalletTypeId: state.sourceWalletTypeId,
targetWalletTypeId: state.targetWalletTypeId,
balance: numAmount,
})
if (res.code == 0) {
uni.showToast({ title: "转账成功", icon: "success" })
router.jump("/pages/wallet/list", {}, 2)
} else {
uni.showToast({ title: res.msg, icon: "none" })
}
} catch (error: any) {
uni.showToast({
title: error.message,
icon: "none",
})
} finally {
uni.hideLoading()
}
}
},
})
}
</script>
+6
View File
@@ -119,6 +119,11 @@ const doFreeze = async () => {
uni.hideLoading()
}
}
// 转账
const doTransferMoney = (v: any) => {
router.jump("/pages/pay/transferMoney", { walletTypeId: v.walletTypeId, walletTypeName: v.walletTypeName }, 2)
}
</script>
<template>
@@ -173,6 +178,7 @@ const doFreeze = async () => {
</view>
<view class="flex-row items-center justify-end space-x-20rpx m-t-10rpx">
<!-- <view v-if="v.walletTypeUniqueCode == 1 && !v.cardNumber" class="botder_btn" @tap.stop="openBindDialog(v)">绑定</view> -->
<view class="botder_btn" @tap.stop="doTransferMoney(v)">转入</view>
<view v-if="v.walletTypeUniqueCode == 1 && v.cardNumber && v.isFreeze != 1" class="botder_btn" @tap.stop="openFreezeDialog(v)">
申请冻结
</view>