feat: 添加钱包功能,创建钱包状态管理,更新个人资料页面,优化样式和交互
This commit is contained in:
5
auto-imports.d.ts
vendored
5
auto-imports.d.ts
vendored
@@ -296,6 +296,7 @@ declare global {
|
|||||||
const useVibrate: typeof import('@vueuse/core').useVibrate
|
const useVibrate: typeof import('@vueuse/core').useVibrate
|
||||||
const useVirtualList: typeof import('@vueuse/core').useVirtualList
|
const useVirtualList: typeof import('@vueuse/core').useVirtualList
|
||||||
const useWakeLock: typeof import('@vueuse/core').useWakeLock
|
const useWakeLock: typeof import('@vueuse/core').useWakeLock
|
||||||
|
const useWalletStore: typeof import('./src/store/wallet').useWalletStore
|
||||||
const useWebNotification: typeof import('@vueuse/core').useWebNotification
|
const useWebNotification: typeof import('@vueuse/core').useWebNotification
|
||||||
const useWebSocket: typeof import('@vueuse/core').useWebSocket
|
const useWebSocket: typeof import('@vueuse/core').useWebSocket
|
||||||
const useWebWorker: typeof import('@vueuse/core').useWebWorker
|
const useWebWorker: typeof import('@vueuse/core').useWebWorker
|
||||||
@@ -328,6 +329,9 @@ declare global {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export type { Language } from './src/composables/useLanguage'
|
export type { Language } from './src/composables/useLanguage'
|
||||||
import('./src/composables/useLanguage')
|
import('./src/composables/useLanguage')
|
||||||
|
// @ts-ignore
|
||||||
|
export type { Wallet } from './src/store/wallet'
|
||||||
|
import('./src/store/wallet')
|
||||||
}
|
}
|
||||||
|
|
||||||
// for vue template auto import
|
// for vue template auto import
|
||||||
@@ -624,6 +628,7 @@ declare module 'vue' {
|
|||||||
readonly useVibrate: UnwrapRef<typeof import('@vueuse/core')['useVibrate']>
|
readonly useVibrate: UnwrapRef<typeof import('@vueuse/core')['useVibrate']>
|
||||||
readonly useVirtualList: UnwrapRef<typeof import('@vueuse/core')['useVirtualList']>
|
readonly useVirtualList: UnwrapRef<typeof import('@vueuse/core')['useVirtualList']>
|
||||||
readonly useWakeLock: UnwrapRef<typeof import('@vueuse/core')['useWakeLock']>
|
readonly useWakeLock: UnwrapRef<typeof import('@vueuse/core')['useWakeLock']>
|
||||||
|
readonly useWalletStore: UnwrapRef<typeof import('./src/store/wallet')['useWalletStore']>
|
||||||
readonly useWebNotification: UnwrapRef<typeof import('@vueuse/core')['useWebNotification']>
|
readonly useWebNotification: UnwrapRef<typeof import('@vueuse/core')['useWebNotification']>
|
||||||
readonly useWebSocket: UnwrapRef<typeof import('@vueuse/core')['useWebSocket']>
|
readonly useWebSocket: UnwrapRef<typeof import('@vueuse/core')['useWebSocket']>
|
||||||
readonly useWebWorker: UnwrapRef<typeof import('@vueuse/core')['useWebWorker']>
|
readonly useWebWorker: UnwrapRef<typeof import('@vueuse/core')['useWebWorker']>
|
||||||
|
|||||||
25
src/store/wallet.ts
Normal file
25
src/store/wallet.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import type { Treaty } from "@elysiajs/eden";
|
||||||
|
import { client, safeClient } from "@/api";
|
||||||
|
|
||||||
|
export type Wallet = Treaty.Data<typeof client.api.wallet.wallets.get>[number];
|
||||||
|
|
||||||
|
export const useWalletStore = defineStore("wallet", () => {
|
||||||
|
const wallets = ref<Wallet[]>([]);
|
||||||
|
const balanceWallet = ref<Wallet | null>(null);
|
||||||
|
|
||||||
|
async function syncWallets() {
|
||||||
|
const { data } = await safeClient(client.api.wallet.wallets.get(), { silent: true });
|
||||||
|
wallets.value = data.value || [];
|
||||||
|
}
|
||||||
|
async function syncBalanceWallet() {
|
||||||
|
const { data } = await safeClient(client.api.wallet.wallet_by_code({ walletTypeCode: "balance" }).get(), { silent: true });
|
||||||
|
balanceWallet.value = data.value || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
wallets,
|
||||||
|
balanceWallet,
|
||||||
|
syncWallets,
|
||||||
|
syncBalanceWallet,
|
||||||
|
};
|
||||||
|
});
|
||||||
55
src/views/profile/index.ts
Normal file
55
src/views/profile/index.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { cardOutline, chatbubblesOutline, listOutline, locationOutline, lockClosedOutline, settingsOutline, shieldCheckmarkOutline } from "ionicons/icons";
|
||||||
|
|
||||||
|
export const myApps = [
|
||||||
|
{
|
||||||
|
id: "real_name",
|
||||||
|
name: "实名认证",
|
||||||
|
icon: shieldCheckmarkOutline,
|
||||||
|
color: "#c32120",
|
||||||
|
path: "/real-name",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "address",
|
||||||
|
name: "收货地址",
|
||||||
|
icon: locationOutline,
|
||||||
|
color: "#c32120",
|
||||||
|
path: "/address",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "payment",
|
||||||
|
name: "收款方式",
|
||||||
|
icon: cardOutline,
|
||||||
|
color: "#c32120",
|
||||||
|
path: "/payment",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "customer_service",
|
||||||
|
name: "在线客服",
|
||||||
|
icon: chatbubblesOutline,
|
||||||
|
color: "#c32120",
|
||||||
|
path: "/customer-service",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "settings",
|
||||||
|
name: "个人设置",
|
||||||
|
icon: settingsOutline,
|
||||||
|
color: "#c32120",
|
||||||
|
path: "/settings",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "security",
|
||||||
|
name: "安全中心",
|
||||||
|
icon: lockClosedOutline,
|
||||||
|
color: "#c32120",
|
||||||
|
path: "/security",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "asset_details",
|
||||||
|
name: "资产明细",
|
||||||
|
icon: listOutline,
|
||||||
|
color: "#c32120",
|
||||||
|
path: "/asset-details",
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export type MyApp = (typeof myApps)[number];
|
||||||
@@ -1,108 +1,47 @@
|
|||||||
<script lang='ts' setup>
|
<script lang='ts' setup>
|
||||||
import {
|
import { alertController } from "@ionic/vue";
|
||||||
alertCircleOutline,
|
import { arrowDownOutline, arrowUpOutline, exitOutline, homeOutline, walletOutline } from "ionicons/icons";
|
||||||
arrowDownOutline,
|
import { authClient } from "@/auth";
|
||||||
arrowUpOutline,
|
import { myApps } from "./";
|
||||||
cardOutline,
|
|
||||||
chatbubblesOutline,
|
|
||||||
chevronForwardOutline,
|
|
||||||
documentTextOutline,
|
|
||||||
exitOutline,
|
|
||||||
homeOutline,
|
|
||||||
listOutline,
|
|
||||||
locationOutline,
|
|
||||||
lockClosedOutline,
|
|
||||||
personOutline,
|
|
||||||
settingsOutline,
|
|
||||||
shieldCheckmarkOutline,
|
|
||||||
walletOutline,
|
|
||||||
} from "ionicons/icons";
|
|
||||||
|
|
||||||
// 用户信息
|
const router = useRouter();
|
||||||
const userInfo = ref({
|
const userStore = useUserStore();
|
||||||
name: "周少华",
|
const walletStore = useWalletStore();
|
||||||
phone: "138****1234",
|
const { userProfile } = storeToRefs(userStore);
|
||||||
inviteCode: "ABCD1234",
|
const { balanceWallet } = storeToRefs(walletStore);
|
||||||
avatar: "@/assets/images/avatar.jpg",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 钱包余额
|
walletStore.syncBalanceWallet();
|
||||||
const wallet = ref({
|
|
||||||
profitBalance: 15286.50, // 收益钱包余额
|
|
||||||
accountBalance: 32150.80, // 账户余额
|
|
||||||
});
|
|
||||||
|
|
||||||
// 我的应用列表
|
|
||||||
const myApps = ref([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: "实名认证",
|
|
||||||
icon: shieldCheckmarkOutline,
|
|
||||||
color: "#c32120",
|
|
||||||
path: "/real-name",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: "收货地址",
|
|
||||||
icon: locationOutline,
|
|
||||||
color: "#c32120",
|
|
||||||
path: "/address",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: "收款方式",
|
|
||||||
icon: cardOutline,
|
|
||||||
color: "#c32120",
|
|
||||||
path: "/payment",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
name: "在线客服",
|
|
||||||
icon: chatbubblesOutline,
|
|
||||||
color: "#c32120",
|
|
||||||
path: "/customer-service",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
name: "个人设置",
|
|
||||||
icon: settingsOutline,
|
|
||||||
color: "#c32120",
|
|
||||||
path: "/settings",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
name: "安全中心",
|
|
||||||
icon: lockClosedOutline,
|
|
||||||
color: "#c32120",
|
|
||||||
path: "/security",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
name: "资产明细",
|
|
||||||
icon: listOutline,
|
|
||||||
color: "#c32120",
|
|
||||||
path: "/asset-details",
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
function handleRecharge() {
|
function handleRecharge() {
|
||||||
console.log("快捷充值");
|
router.push("/recharge");
|
||||||
// TODO: 实现充值功能
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleWithdraw() {
|
function handleWithdraw() {
|
||||||
console.log("快捷提现");
|
router.push("/withdraw");
|
||||||
// TODO: 实现提现功能
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAppClick(app: any) {
|
async function handleLogout() {
|
||||||
console.log("点击应用:", app.name);
|
const alert = await alertController.create({
|
||||||
// TODO: 跳转到对应页面
|
header: "退出登录",
|
||||||
}
|
message: "确定要退出登录吗?",
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: "取消",
|
||||||
|
role: "cancel",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "退出登录",
|
||||||
|
role: "destructive",
|
||||||
|
handler: async () => {
|
||||||
|
userStore.signOut();
|
||||||
|
authClient.signOut();
|
||||||
|
router.replace("/layout/riwa");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
function handleLogout() {
|
await alert.present();
|
||||||
console.log("退出登录");
|
|
||||||
// TODO: 实现退出登录功能
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -118,14 +57,14 @@ function handleLogout() {
|
|||||||
<img alt="用户头像" src="@/assets/images/avatar.jpg">
|
<img alt="用户头像" src="@/assets/images/avatar.jpg">
|
||||||
</ion-avatar>
|
</ion-avatar>
|
||||||
<div>
|
<div>
|
||||||
<div class="text-danger text-xl font-bold">
|
<div class="text-primary text-xl font-bold">
|
||||||
{{ userInfo.name }}
|
{{ userProfile?.nickname }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-danger text-sm font-semibold opacity-90">
|
<div class="text-primary text-sm font-semibold opacity-90">
|
||||||
手机号:{{ userInfo.phone }}
|
手机号:{{ userProfile?.user.username }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-danger text-sm font-semibold opacity-90">
|
<div class="text-primary text-sm font-semibold opacity-90">
|
||||||
邀请码:{{ userInfo.inviteCode }}
|
邀请码:{{ userProfile?.inviteCode }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -136,7 +75,7 @@ function handleLogout() {
|
|||||||
<section class="mb-4 -mt-12">
|
<section class="mb-4 -mt-12">
|
||||||
<div class="card rounded-2xl shadow-lg p-5">
|
<div class="card rounded-2xl shadow-lg p-5">
|
||||||
<div class="flex items-center gap-2 mb-4">
|
<div class="flex items-center gap-2 mb-4">
|
||||||
<ion-icon :icon="walletOutline" class="text-2xl text-[#1e71c4]" />
|
<ion-icon :icon="walletOutline" class="text-2xl text-[#c41e3a]" />
|
||||||
<div class="text-lg font-bold text-[#1a1a1a] m-0">
|
<div class="text-lg font-bold text-[#1a1a1a] m-0">
|
||||||
我的钱包
|
我的钱包
|
||||||
</div>
|
</div>
|
||||||
@@ -144,20 +83,20 @@ function handleLogout() {
|
|||||||
|
|
||||||
<!-- 余额展示 -->
|
<!-- 余额展示 -->
|
||||||
<div class="grid grid-cols-2 gap-4 mb-4">
|
<div class="grid grid-cols-2 gap-4 mb-4">
|
||||||
<div class="bg-gradient-to-br from-[#ffffff] to-[#e8f5ff] rounded-xl p-4">
|
<div class="bg-linear-to-br from-[#fff7f0] to-[#ffe8e8] rounded-xl p-4">
|
||||||
<div class="text-xs mb-1">
|
<div class="text-xs mb-1">
|
||||||
收益钱包
|
收益钱包
|
||||||
</div>
|
</div>
|
||||||
<div class="text-2xl font-bold text-[#1e71c4] mb-1">
|
<div class="text-2xl font-bold text-[#c41e3a] mb-1">
|
||||||
¥{{ wallet.profitBalance.toFixed(2) }}
|
¥{{ balanceWallet?.available }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-gradient-to-br from-[#ffffff] to-[#e8f5ff] rounded-xl p-4">
|
<div class="bg-linear-to-br from-[#fff7f0] to-[#ffe8e8] rounded-xl p-4">
|
||||||
<div class="text-xs mb-1">
|
<div class="text-xs mb-1">
|
||||||
账户余额
|
账户余额
|
||||||
</div>
|
</div>
|
||||||
<div class="text-2xl font-bold text-[#1e71c4] mb-1">
|
<div class="text-2xl font-bold text-[#c41e3a] mb-1">
|
||||||
¥{{ wallet.accountBalance.toFixed(2) }}
|
¥{{ balanceWallet?.available }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -189,7 +128,7 @@ function handleLogout() {
|
|||||||
<section class="my-5">
|
<section class="my-5">
|
||||||
<div class="card rounded-2xl shadow-lg p-5">
|
<div class="card rounded-2xl shadow-lg p-5">
|
||||||
<div class="flex items-center gap-2 mb-4">
|
<div class="flex items-center gap-2 mb-4">
|
||||||
<ion-icon :icon="homeOutline" class="text-2xl text-[#1e71c4]" />
|
<ion-icon :icon="homeOutline" class="text-2xl text-[#c41e3a]" />
|
||||||
<div class="text-lg font-bold text-[#1a1a1a] m-0">
|
<div class="text-lg font-bold text-[#1a1a1a] m-0">
|
||||||
我的应用
|
我的应用
|
||||||
</div>
|
</div>
|
||||||
@@ -200,7 +139,7 @@ function handleLogout() {
|
|||||||
v-for="app in myApps"
|
v-for="app in myApps"
|
||||||
:key="app.id"
|
:key="app.id"
|
||||||
class="flex flex-col items-center gap-2 cursor-pointer transition-transform active:scale-95"
|
class="flex flex-col items-center gap-2 cursor-pointer transition-transform active:scale-95"
|
||||||
@click="handleAppClick(app)"
|
@click="$router.push(app.path)"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="app-item w-13 h-13 rounded-xl flex-center shadow-md"
|
class="app-item w-13 h-13 rounded-xl flex-center shadow-md"
|
||||||
@@ -227,13 +166,13 @@ function handleLogout() {
|
|||||||
|
|
||||||
<style lang='css' scoped>
|
<style lang='css' scoped>
|
||||||
.card {
|
.card {
|
||||||
background: linear-gradient(180deg, #eef9ff, #ffffff 15%);
|
background: linear-gradient(180deg, #ffeef1, #ffffff 15%);
|
||||||
}
|
}
|
||||||
.recharge-btn {
|
.recharge-btn {
|
||||||
--background: linear-gradient(135deg, #1778ac 0%, #265166 100%);
|
--background: linear-gradient(135deg, #c41e3a 0%, #8b1a2e 100%);
|
||||||
--background-activated: linear-gradient(135deg, #1778ac 0%, #265166 100%);
|
--background-activated: linear-gradient(135deg, #8b1a2e 0%, #c41e3a 100%);
|
||||||
--border-radius: 12px;
|
--border-radius: 12px;
|
||||||
--box-shadow: 0 2px 8px rgba(30, 124, 196, 0.3);
|
--box-shadow: 0 2px 8px rgba(196, 30, 58, 0.3);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
@@ -241,8 +180,8 @@ function handleLogout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.withdraw-btn {
|
.withdraw-btn {
|
||||||
--border-color: #1972a2;
|
--border-color: #c41e3a;
|
||||||
--color: #1e6ac4;
|
--color: #c41e3a;
|
||||||
--border-radius: 12px;
|
--border-radius: 12px;
|
||||||
--border-width: 2px;
|
--border-width: 2px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@@ -255,6 +194,6 @@ function handleLogout() {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
.app-item {
|
.app-item {
|
||||||
background: #3f8bba;
|
background: linear-gradient(135deg, rgb(249 103 102 / 93%), rgb(195, 33, 32));
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user