zhb пре 2 месеци
родитељ
комит
8d7e795b94

+ 49 - 0
components/cwg-label-line-value.vue

@@ -0,0 +1,49 @@
+<template>
+    <view class="info-item">
+        <span class="label">{{ label }}</span>
+        <span class="line"></span>
+        <span class="value">{{ value }}</span>
+    </view>
+</template>
+
+<script setup>
+
+const props = defineProps({
+    label: {
+        type: String,
+        required: ""
+    },
+    value: {
+        type: String,
+        required: "--"
+    },
+});
+</script>
+
+<style scoped lang="scss">
+@import "@/uni.scss";
+
+.info-item {
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-end;
+    font-size: px2rpx(14);
+
+    .label {
+        color: #6c8595;
+    }
+
+    .line {
+        flex: 1;
+        height: 1px;
+        border-top: 1px dashed rgba(108, 133, 149, 0.5);
+        margin-bottom: px2rpx(1);
+
+    }
+
+    .value {
+        font-weight: 500;
+        color: #2e3a47;
+    }
+}
+</style>

+ 0 - 1
components/cwg-sidebar.vue

@@ -93,7 +93,6 @@ const updateSubmenuHeight = (index: number) => {
     if (refs && refs[index]) {
         const el = refs[index].$el || refs[index];
         const height = measureHeight(el);
-        console.log(height, 12121);
 
         if (height > 0) {
             menu.value[index].submenuHeight = height;

+ 646 - 0
pages/customer/components/AccountCard.vue

@@ -0,0 +1,646 @@
+<template>
+    <view class="account-card">
+        <!-- 折叠/展开按钮 -->
+        <button class="collapse-btn" @click="toggleExpand">
+            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
+                stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
+                :class="['chevron-icon', { expanded: isExpanded }]">
+                <path d="M6 15l6 -6l6 6" />
+            </svg>
+        </button>
+
+        <!-- 标签区域 -->
+        <view class="labels-container">
+            <view class="labels">
+                <view v-for="(label, index) in account.labels" :key="index" class="label-badge">
+                    {{ label }}
+                </view>
+            </view>
+            <view class="account-number"># {{ account.accountNumber }}</view>
+            <view class="account-nickname">{{ account.nickname }}</view>
+        </view>
+
+        <!-- 主要内容区域(余额和操作按钮) -->
+        <view class="main-content">
+            <!-- 余额 -->
+            <view class="balance">
+                <text class="balance-number">{{ balanceInteger }}</text>
+                <text class="balance-decimal">{{ balanceDecimal }} {{ account.currency }}</text>
+            </view>
+
+            <!-- 移动端圆形按钮组(≤1100px显示) -->
+            <view class="mobile-buttons">
+                <!-- 交易 -->
+                <view class="circle-btn" @click="handleAction('trade')">
+                    <view class="circle-icon">
+                        <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
+                            <path
+                                d="M4.66797 2.66602V4.66602M4.66797 8.66602V13.3327M11.3346 2.66602V4.66602M11.3346 11.3327V13.3327M2.66797 5.33268C2.66797 5.15587 2.73821 4.9863 2.86323 4.86128C2.98826 4.73625 3.15782 4.66602 3.33464 4.66602H6.0013C6.17811 4.66602 6.34768 4.73625 6.47271 4.86128C6.59773 4.9863 6.66797 5.15587 6.66797 5.33268V7.99935C6.66797 8.17616 6.59773 8.34573 6.47271 8.47075C6.34768 8.59578 6.17811 8.66602 6.0013 8.66602H3.33464C3.15782 8.66602 2.98826 8.59578 2.86323 8.47075C2.73821 8.34573 2.66797 8.17616 2.66797 7.99935V5.33268ZM9.33464 5.33268C9.33464 5.15587 9.40487 4.9863 9.5299 4.86128C9.65492 4.73625 9.82449 4.66602 10.0013 4.66602H12.668C12.8448 4.66602 13.0143 4.73625 13.1394 4.86128C13.2644 4.9863 13.3346 5.15587 13.3346 5.33268V10.666C13.3346 10.8428 13.2644 11.0124 13.1394 11.1374C13.0143 11.2624 12.8448 11.3327 12.668 11.3327H10.0013C9.82449 11.3327 9.65492 11.2624 9.5299 11.1374C9.40487 11.0124 9.33464 10.8428 9.33464 10.666V5.33268Z"
+                                stroke="currentColor" stroke-width="1.33" stroke-linecap="round"
+                                stroke-linejoin="round" />
+                        </svg>
+                    </view>
+                    <text class="circle-label">交易</text>
+                </view>
+
+                <!-- 入金(带限制包装,此处简化) -->
+                <view class="circle-btn" @click="toDeposit">
+                    <view class="circle-icon">
+                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
+                            stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                            <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" />
+                            <path d="M8 12l4 4" />
+                            <path d="M12 8v8" />
+                            <path d="M16 12l-4 4" />
+                        </svg>
+                    </view>
+                    <text class="circle-label">入金</text>
+                </view>
+
+                <!-- 出金 -->
+                <view class="circle-btn" @click="toWithdraw">
+                    <view class="circle-icon">
+                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
+                            stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                            <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" />
+                            <path d="M15 9l-6 6" />
+                            <path d="M15 15v-6h-6" />
+                        </svg>
+                    </view>
+                    <text class="circle-label">出金</text>
+                </view>
+
+                <!-- 转账 -->
+                <view class="circle-btn" @click="toTransfer">
+                    <view class="circle-icon">
+                        <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
+                            <path d="M21 17H3M21 17L17.5 20.5M21 17L17.5 13.5M6.5 10.5L3 7M3 7L6.5 3.5M3 7H21"
+                                stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
+                        </svg>
+                    </view>
+                    <text class="circle-label">转账</text>
+                </view>
+
+                <!-- 更多(三点) -->
+                <view class="circle-btn" @click="handleAction('more')">
+                    <view class="circle-icon">
+                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
+                            stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                            <path d="M12 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
+                            <path d="M12 19m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
+                            <path d="M12 5m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
+                        </svg>
+                    </view>
+                    <text class="circle-label">更多</text>
+                </view>
+            </view>
+
+            <!-- 桌面端按钮组(>1100px显示) -->
+            <view class="desktop-buttons">
+                <view class="action-btn primary" @click="handleAction('trade')">
+                    <span class="btn-icon">
+                        <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
+                            <path
+                                d="M4.66797 2.66602V4.66602M4.66797 8.66602V13.3327M11.3346 2.66602V4.66602M11.3346 11.3327V13.3327M2.66797 5.33268C2.66797 5.15587 2.73821 4.9863 2.86323 4.86128C2.98826 4.73625 3.15782 4.66602 3.33464 4.66602H6.0013C6.17811 4.66602 6.34768 4.73625 6.47271 4.86128C6.59773 4.9863 6.66797 5.15587 6.66797 5.33268V7.99935C6.66797 8.17616 6.59773 8.34573 6.47271 8.47075C6.34768 8.59578 6.17811 8.66602 6.0013 8.66602H3.33464C3.15782 8.66602 2.98826 8.59578 2.86323 8.47075C2.73821 8.34573 2.66797 8.17616 2.66797 7.99935V5.33268ZM9.33464 5.33268C9.33464 5.15587 9.40487 4.9863 9.5299 4.86128C9.65492 4.73625 9.82449 4.66602 10.0013 4.66602H12.668C12.8448 4.66602 13.0143 4.73625 13.1394 4.86128C13.2644 4.9863 13.3346 5.15587 13.3346 5.33268V10.666C13.3346 10.8428 13.2644 11.0124 13.1394 11.1374C13.0143 11.2624 12.8448 11.3327 12.668 11.3327H10.0013C9.82449 11.3327 9.65492 11.2624 9.5299 11.1374C9.40487 11.0124 9.33464 10.8428 9.33464 10.666V5.33268Z"
+                                stroke="currentColor" stroke-width="1.33" stroke-linecap="round"
+                                stroke-linejoin="round" />
+                        </svg>
+                    </span>
+                    交易
+                </view>
+                <view class="action-btn" @click="toDeposit">
+                    <span class="btn-icon">
+                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
+                            stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                            <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" />
+                            <path d="M8 12l4 4" />
+                            <path d="M12 8v8" />
+                            <path d="M16 12l-4 4" />
+                        </svg>
+                    </span>
+                    入金
+                </view>
+                <view class="action-btn" @click="toWithdraw">
+                    <span class="btn-icon">
+                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
+                            stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                            <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" />
+                            <path d="M15 9l-6 6" />
+                            <path d="M15 15v-6h-6" />
+                        </svg>
+                    </span>
+                    出金
+                </view>
+                <view class="action-btn" @click="toTransfer">
+                    <span class="btn-icon">
+                        <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
+                            <path d="M21 17H3M21 17L17.5 20.5M21 17L17.5 13.5M6.5 10.5L3 7M3 7L6.5 3.5M3 7H21"
+                                stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
+                        </svg>
+                    </span>
+                    转账
+                </view>
+                <view class="action-btn icon-only" @click="handleAction('more')">
+                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
+                        stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                        <path d="M12 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
+                        <path d="M12 19m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
+                        <path d="M12 5m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
+                    </svg>
+                </view>
+            </view>
+        </view>
+        <view ref="infoBottomRef" class="info-bottom" :style="{
+            height: isExpanded ? infoBottomHeight + 'px' : '0px',
+            transition: 'height 281ms cubic-bezier(0.4, 0, 0.2, 1)'
+        }">
+            <!-- 底部信息区域(折叠时隐藏) -->
+            <view class="info-section">
+                <view class="info-column">
+                    <cwg-label-line-value :label="t('Label.Leverage')" :value="account.actualLeverage" />
+                    <cwg-label-line-value label="浮动盈/亏" :value="account.floatingPL" />
+                    <cwg-label-line-value :label="t('Label.Balance')" :value="account.balanceWithSymbol" />
+                </view>
+                <view class="info-column">
+                    <cwg-label-line-value :label="t('Label.Equity')" :value="account.equityWithSymbol" />
+                    <cwg-label-line-value :label="t('Label.Credit')" :value="account.creditWithSymbol" />
+                    <cwg-label-line-value label="平台" :value="account.platform" />
+                </view>
+            </view>
+            <!-- 额外操作行(服务器、登录、更改密码,折叠时隐藏) -->
+            <view class="extra-actions">
+                <!-- 登录复制行 -->
+                <view class="copy-row">
+                    <span class="label">{{ account.platform }} 登陆</span>
+                    <span class="value">{{ account.login }}</span>
+                    <view class="copy-btn" @click="copy(account.login)">
+                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
+                            stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                            <path
+                                d="M7 7m0 2.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667z" />
+                            <path
+                                d="M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1" />
+                        </svg>
+                    </view>
+                </view>
+
+                <!-- 更改交易密码按钮 -->
+                <view class="change-password-btn" @click="handleChangePassword">
+                    <span class="btn-icon">
+                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
+                            stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                            <path d="M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4" />
+                            <path d="M13.5 6.5l4 4" />
+                        </svg>
+                    </span>
+                    更改交易密码
+                </view>
+            </view>
+        </view>
+
+        <!-- 通知区域(预留) -->
+        <view class="notificators"></view>
+    </view>
+</template>
+
+<script setup lang="ts">
+import { ref, computed, onMounted, nextTick, onBeforeUnmount } from 'vue';
+import useRouter from "@/hooks/useRouter";
+const router = useRouter();
+import { useI18n } from 'vue-i18n';
+const { t, locale } = useI18n();
+
+
+// 定义账户数据类型
+export interface Account {
+    labels: string[];          // 标签数组,如 ['真实', 'MT4', 'Standard']
+    accountNumber: string;      // 账号,如 '85319215'
+    nickname: string;           // 昵称,如 '标准账户'
+    balance: number;            // 余额数字
+    currency: string;           // 货币,如 'USD'
+    actualLeverage: string;     // 实际杠杆,如 '1:2000'
+    maxLeverage: string;        // 调整杠杆,如 '1:2000'
+    floatingPL: string;         // 浮动盈亏,如 '0.00 USD'
+    creditWithSymbol: string;         // 可用保证金,如 '0.00 USD'
+    equityWithSymbol: string;             // 净值,如 '0.00 USD'
+    platform: string;           // 平台,如 'MT4'
+    server: string;             // 服务器,如 'Exness-Real28'
+    login: string;              // 登录名,如 '85319215'
+    balanceWithSymbol: string;              // 余额,如 '85319215'
+}
+
+const infoBottomRef = ref(null);
+const infoBottomHeight = ref(0);
+// 测量高度
+const updateSubmenuHeight = () => {
+    const el = infoBottomRef.value.$el;
+    if (el) {
+        // 获取内容实际高度(可能需要暂时移除过渡影响)
+        const height = el.scrollHeight || el.offsetHeight;
+        if (height > 0) {
+            infoBottomHeight.value = height;
+        }
+    }
+};
+
+// 折叠状态
+const isExpanded = ref(false);
+
+// 切换折叠
+const toggleExpand = () => {
+    isExpanded.value = !isExpanded.value;
+    if (isExpanded.value) {
+        nextTick(() => {
+            updateSubmenuHeight();
+        });
+    }
+};
+
+const props = defineProps<{
+    account: Account;
+}>();
+
+// 处理按钮操作
+const handleAction = (type: string) => {
+};
+
+// 复制文本
+const copy = (text: string) => {
+    uni.setClipboardData({ data: text });
+};
+
+// 按钮对应的操作方法
+const toDeposit = () => {
+    router.push(`/pages/customer/deposit?login=${props.accountlogin}&type=${props.accounttype}&balance=${props.accountbalance}&currency=${props.accountcurrency}`)
+}
+
+const toWithdraw = () => {
+    router.push(`/pages/customer/withdraw?login=${props.accountlogin}&type=${props.accounttype}&balance=${props.accountbalance}&currency=${props.accountcurrency}`)
+}
+
+const toTransfer = () => {
+    router.push(`/pages/customer/transfer?login=${props.accountlogin}&type=${props.accounttype}&balance=${props.accountbalance}&currency=${props.accountcurrency}`)
+}
+
+// 更改交易密码
+const handleChangePassword = () => {
+    const close = props.accountcloseFunctions?.indexOf('4') !== -1 ? 1 : 0
+    router.push(`/pages/customer/settings?login=${props.accountlogin}&platform=${props.accountplatform}&type=${props.accounttype}&currency=${props.accountcurrency}&leverage=${props.accountleverage}&close=${close}`)
+}
+
+const toStandardRebate = () => {
+    router.push(`/pages/customer/standard/rebate?login=${props.accountlogin}`)
+}
+// 格式化余额,拆分为整数和小数部分
+const balanceInteger = computed(() => {
+    return Math.floor(props.account.balance).toString();
+});
+const balanceDecimal = computed(() => {
+    const parts = props.account.balance.toFixed(2).split('.');
+    return parts[1] ? '.' + parts[1] : '.00';
+});
+// 在组件挂载后初始化高度
+onMounted(() => {
+    nextTick(() => {
+        updateSubmenuHeight();
+    });
+    window.addEventListener('resize', handleResize);
+    isExpanded.value = props.account.isExpanded;
+});
+// 监听窗口 resize
+const handleResize = () => {
+    if (isExpanded.value) {
+        updateSubmenuHeight();
+    }
+};
+onBeforeUnmount(() => {
+    window.removeEventListener('resize', handleResize);
+});
+</script>
+
+<style scoped lang="scss">
+@import '@/uni.scss';
+
+.account-card {
+    border-radius: px2rpx(16);
+    padding: px2rpx(16);
+    margin-bottom: px2rpx(16);
+    position: relative;
+    border: 1px solid rgba(108, 133, 149, 0.12);
+    color: #2e3a47;
+
+    .collapse-btn {
+        position: absolute;
+        top: px2rpx(12);
+        right: px2rpx(12);
+        background: transparent;
+        border: none;
+        padding: 0;
+        cursor: pointer;
+        color: #6c8595;
+        width: px2rpx(32);
+        height: px2rpx(32);
+        display: flex;
+        align-items: center;
+        justify-content: center;
+
+        .chevron-icon {
+            transition: transform 0.3s;
+
+            &.expanded {
+                transform: rotate(180deg);
+            }
+        }
+    }
+
+    .labels-container {
+        display: flex;
+        align-items: center;
+        flex-wrap: wrap;
+        gap: px2rpx(8);
+
+        margin-bottom: px2rpx(16);
+        padding-right: px2rpx(40); // 为折叠按钮留出空间
+
+        .labels {
+            display: flex;
+            gap: px2rpx(8);
+        }
+
+        .label-badge {
+            background-color: rgba(108, 133, 149, 0.08);
+            border-radius: px2rpx(4);
+            padding: px2rpx(4) px2rpx(8);
+            font-size: px2rpx(12);
+            color: #6c8595;
+            font-weight: 500;
+        }
+
+        .account-number {
+            font-size: px2rpx(18);
+            font-weight: 600;
+            line-height: 1.3;
+        }
+
+        .account-nickname {
+            font-size: px2rpx(14);
+            color: #6c8595;
+        }
+    }
+
+    .main-content {
+        .balance {
+            margin-bottom: px2rpx(16);
+
+            .balance-number {
+                font-size: px2rpx(32);
+                font-weight: 700;
+            }
+
+            .balance-decimal {
+                font-size: px2rpx(16);
+                color: #6c8595;
+                margin-left: px2rpx(4);
+            }
+        }
+
+        // 移动端按钮组(默认显示)
+        .mobile-buttons {
+            display: flex;
+            justify-content: center;
+            gap: px2rpx(0);
+            margin-bottom: px2rpx(16);
+            flex-wrap: wrap;
+
+            .circle-btn {
+                display: flex;
+                flex-direction: column;
+                align-items: center;
+                cursor: pointer;
+                width: px2rpx(64);
+
+                .circle-icon {
+                    width: px2rpx(48);
+                    height: px2rpx(48);
+                    border-radius: 50%;
+                    background-color: #f5f7f9;
+                    display: flex;
+                    align-items: center;
+                    justify-content: center;
+                    color: #2e3a47;
+                    transition: background-color 0.2s;
+
+                    &:hover {
+                        background-color: #e9ecef;
+                    }
+
+                    svg {
+                        width: px2rpx(24);
+                        height: px2rpx(24);
+                    }
+                }
+
+                .circle-label {
+                    font-size: px2rpx(12);
+                    margin-top: px2rpx(4);
+                    color: #6c8595;
+                }
+            }
+        }
+
+        // 桌面端按钮组(默认隐藏,屏幕>1100px时显示)
+        .desktop-buttons {
+            display: none;
+
+            .action-btn {
+                background: transparent;
+                border: 1px solid rgba(108, 133, 149, 0);
+                border-radius: px2rpx(8);
+                padding: px2rpx(8) px2rpx(20);
+                font-size: px2rpx(14);
+                color: #2e3a47;
+                display: inline-flex;
+                align-items: center;
+                justify-content: center;
+                gap: px2rpx(8);
+                cursor: pointer;
+                transition: all 0.2s;
+                height: px2rpx(40);
+                box-sizing: border-box;
+                background-color: rgba(108, 133, 149, 0.08);
+
+                &.primary {
+                    background-color: var(--color-navy-700);
+                    color: #fff;
+
+                    svg {
+                        stroke: #fff;
+                    }
+
+                    &:hover {
+                        background-color: var(--color-navy-600);
+                    }
+                }
+
+                &:hover {
+                    border: 1px solid rgba(108, 133, 149, 0.2);
+                }
+
+                .btn-icon {
+                    display: flex;
+                    align-items: center;
+
+                    svg {
+                        width: px2rpx(18);
+                        height: px2rpx(18);
+                    }
+                }
+
+                &.icon-only {
+                    padding: px2rpx(8);
+                }
+            }
+        }
+    }
+
+    .info-section {
+        display: flex;
+        gap: px2rpx(24);
+        padding: px2rpx(16) 0;
+        border-top: 1px solid rgba(108, 133, 149, 0.12);
+        border-bottom: 1px solid rgba(108, 133, 149, 0.12);
+        margin: px2rpx(16) 0;
+
+        .info-column {
+            flex: 1;
+            display: flex;
+            flex-direction: column;
+            gap: px2rpx(12);
+        }
+
+        .info-item {
+            display: flex;
+            justify-content: space-between;
+            align-items: flex-end;
+            font-size: px2rpx(14);
+
+            .label {
+                color: #6c8595;
+            }
+
+            .line {
+                flex: 1;
+                height: 1px;
+                border-top: 1px dashed rgba(108, 133, 149, 0.5);
+                margin-bottom: px2rpx(1);
+
+            }
+
+            .value {
+                font-weight: 500;
+                color: #2e3a47;
+            }
+        }
+    }
+
+    .extra-actions {
+        display: flex;
+        align-items: center;
+        gap: px2rpx(8);
+        margin-bottom: px2rpx(12);
+
+        .copy-row {
+            display: flex;
+            align-items: center;
+            gap: px2rpx(8);
+
+            font-size: px2rpx(14);
+
+            .label {
+                color: #6c8595;
+                min-width: px2rpx(70);
+            }
+
+            .value {
+                flex: 1;
+                color: #2e3a47;
+                font-family: monospace;
+            }
+
+            .copy-btn {
+                background: transparent;
+                border: 1px solid rgba(108, 133, 149, 0);
+                padding: 0;
+                cursor: pointer;
+                color: #6c8595;
+                width: px2rpx(32);
+                height: px2rpx(32);
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                box-sizing: border-box;
+
+                svg {
+                    width: px2rpx(20);
+                    height: px2rpx(20);
+                }
+
+                &:hover {
+                    background-color: rgba(108, 133, 149, 0.05);
+                    border: 1px solid rgba(108, 133, 149, 0.2);
+                }
+            }
+        }
+
+        .change-password-btn {
+            background: transparent;
+            box-sizing: border-box;
+            border: 1px solid rgba(108, 133, 149, 0);
+            border-radius: px2rpx(8);
+            padding: px2rpx(8) px2rpx(16);
+            font-size: px2rpx(14);
+            color: #2e3a47;
+            display: inline-flex;
+            gap: px2rpx(8);
+            cursor: pointer;
+            margin: 0;
+            // transition: all 0.2s;
+
+            .btn-icon svg {
+                width: px2rpx(16);
+                height: px2rpx(16);
+            }
+
+            &:hover {
+                background-color: rgba(108, 133, 149, 0.05);
+                border: 1px solid rgba(108, 133, 149, 0.2);
+            }
+        }
+    }
+
+    .info-bottom {
+        overflow: hidden;
+    }
+
+    .notificators {
+        // 预留通知区域
+    }
+}
+
+// 响应式:屏幕宽度 > 1100px 时,隐藏移动端按钮,显示桌面端按钮
+@media screen and (min-width: 1100px) {
+    .account-card {
+        .main-content {
+            .mobile-buttons {
+                display: none;
+            }
+
+            .desktop-buttons {
+                display: flex;
+                gap: px2rpx(8);
+                justify-content: flex-end;
+            }
+        }
+    }
+}
+</style>

+ 66 - 100
pages/customer/components/AccountList.vue

@@ -14,33 +14,9 @@
             </view>
         </view>
         <cwg-tabs v-model:cativeIndex="cativeIndex" :tabs="tabs" class="tabs-class" />
-        <cwg-tabel ref="tableRef" :columns="columns" :queryParams="search" :api="listApi"
-            headerBackground="var(--color-navy-900)" headerColor="#fff" :showPagination="false"
-            @expand-change="toggleRowExpand" class="account-table">
-            <template #avatar="{ row }">
-                <image :src="row.avatar" class="avatar" mode="widthFix" />
-                <cwg-file :path="row.path" />
-            </template>
-            <template #type="{ row }">
-                <view class="status-badge">{{ typeMap[row.type] }}
-                </view>
-            </template>
-            <template #action="{ row, index }">
-                <view class="expand-btn" :class="{ 'expanded': expanded === index }" @click="toggleExpand(index)">
-                    <cwg-icon name="crm-chevron-down" :size="16" color="#1d293d" />
-                </view>
-            </template>
-            <template #expand="{ row, index }">
-                <view class="action-buttons">
-                    <view v-for="(btn, btnIndex) in createActionButtons(row).value" :key="btnIndex"
-                        :class="[btn.class, 'action-btn', { 'disabled': btn.disabled }]"
-                        @click="!btn.disabled && handleActionBtn(btn.action, row)">
-                        <cwg-icon :name="btn.icon" :size="16" color="#fff" />
-                        <text>{{ btn.text }}</text>
-                    </view>
-                </view>
-            </template>
-        </cwg-tabel>
+        <AccountCard v-for="acc in accounts" :key="acc.accountNumber" :account="acc" @action="handleAction"
+            @copy="handleCopy" @change-password="handleChangePassword" />
+
         <DeleteAccountDialogs ref="deleteAccountDialogRef" v-model:visible="deleteAccountDialogVisible" />
     </view>
 </template>
@@ -55,7 +31,10 @@ import { customApi } from '@/service/custom';
 import { userApi } from '@/api/user';
 import useUserStore from "@/stores/use-user-store";
 const userStore = useUserStore();
+import AccountCard from './AccountCard.vue'
 import DeleteAccountDialogs from './DeleteAccountDialogs.vue'
+import { useFilters } from '@/composables/useFilters'
+const { numberFormat, numberDecimal } = useFilters()
 const search = ref({ platform: 'MT4' })
 const isAfterJuly28 = () => {
     const now = new Date();
@@ -63,6 +42,11 @@ const isAfterJuly28 = () => {
 
     return now >= july28;
 }
+
+
+const handleAction = (type) => { /* 处理交易/入金等 */ };
+const handleCopy = (text) => { uni.setClipboardData({ data: text }); };
+const handleChangePassword = () => { /* 跳转修改密码 */ };
 const typeMap = computed(() => ({
     1: t('AccountType.ClassicAccount'),
     2: t('AccountType.SeniorAccount'),
@@ -157,28 +141,7 @@ const handleActionBtn = (action, row) => {
     }
 }
 
-// 按钮对应的操作方法
-const toDeposit = (row) => {
-    router.push(`/pages/customer/deposit?login=${row.login}&type=${row.type}&balance=${row.balance}&currency=${row.currency}`)
-}
-
-const toWithdraw = (row) => {
-    router.push(`/pages/customer/withdraw?login=${row.login}&type=${row.type}&balance=${row.balance}&currency=${row.currency}`)
-}
-
-const toTransfer = (row) => {
-    router.push(`/pages/customer/transfer?login=${row.login}&type=${row.type}&balance=${row.balance}&currency=${row.currency}`)
-}
-
 
-const toSettings = (row) => {
-    const close = row.closeFunctions?.indexOf('4') !== -1 ? 1 : 0
-    router.push(`/pages/customer/settings?login=${row.login}&platform=${row.platform}&type=${row.type}&currency=${row.currency}&leverage=${row.leverage}&close=${close}`)
-}
-
-const toStandardRebate = (row) => {
-    router.push(`/pages/customer/standard/rebate?login=${row.login}`)
-}
 const deleteAccountDialogVisible = ref(false)
 const openDeleteAccountDialogs = () => {
     deleteAccountDialogVisible.value = true
@@ -187,59 +150,12 @@ const createAccount = () => {
     getCustomLoginInfo()
 }
 const isZh = computed(() => ['cn', 'zh', 'zhHant'].includes(locale.value));
-// 表格列配置
-const columns = ref([
-    {
-        prop: 'status',
-        label: t('PersonalManagement.Label.State'),
-        slot: 'status',
-        align: 'left'
-    },
-    {
-        prop: 'login',
-        label: t('Label.TradingAccount'),
-        align: 'left'
-    },
-    {
-        prop: 'type',
-        label: t('Label.AccountType'),
-        align: 'left',
-        slot: 'type',
-    },
-
-    {
-        prop: 'leverage',
-        label: t('Label.Leverage'),
-        align: 'left',
-        formatter: ({ row }) => row.leverage ? '1:' + row.leverage : '--',
-    },
-    {
-        prop: 'equityWithSymbol',
-        label: t('Label.Equity'),
-        align: 'left',
-        formatter: ({ row }) => row.equityWithSymbol || '0',
-    },
-    {
-        prop: 'creditWithSymbol',
-        label: t('Label.Credit'),
-        align: 'left',
-        formatter: ({ row }) => row.creditWithSymbol || '0',
-    },
-    {
-        prop: 'balanceWithSymbol',
-        label: t('Label.Balance'),
-        align: 'left',
-        formatter: ({ row }) => row.balanceWithSymbol || '0',
-    },
-    {
-        label: t('Label.Action'),
-        // align: 'left',
-        slot: 'action'
-    }
-])
+
 watch(cativeIndex, (newVal) => {
     search.value.platform = tabs.value[newVal].id
+    getAccountList()
 })
+
 // 获取客户登录信息
 async function getCustomLoginInfo() {
     try {
@@ -259,8 +175,58 @@ async function getCustomLoginInfo() {
         //  console.log(error, 111);
     }
 }
-const listApi = ref(null)
-listApi.value = customApi.AccountList
+const AccountList = ref([])
+const getAccountList = async () => {
+    const res = await customApi.AccountList({
+        page: {
+            current: 1,
+            size: 100
+        }, ...search.value
+    })
+    if (res.code === 200) {
+        AccountList.value = res.data
+    }
+}
+// 格式化数值函数
+function formatMoney(value) {
+    if (value === null || value === undefined) value = 0;
+    const sign = value >= 0 ? '' : '-';
+    const absoluteValue = Math.abs(value);
+    return sign + '$' + absoluteValue.toFixed(2);
+}
+
+// 转换数组
+const accounts = computed(() =>
+    AccountList.value.map((acc, index) => {
+        const currency = acc.currency || 'USD';
+        const floating = acc.floating ?? 0;
+        let labels = ['真实', 'MT4', 'Standard'];
+        labels[1] = acc.platform || 'MT4';
+        labels[2] = typeMap.value[acc.type];
+        let nickname = typeMap.value[acc.type];
+        const balance = acc.balance
+        return {
+            ...acc,
+            labels,
+            isExpanded: index == 0,
+            balance,
+            accountNumber: acc.login.toString(),
+            nickname,
+            balanceWithSymbol: acc.balanceWithSymbol ?? '$0', // 余额
+            creditWithSymbol: acc.creditWithSymbol ?? '$0',//信用
+            equityWithSymbol: acc.equityWithSymbol ?? '$0',//净值
+            currency,
+            actualLeverage: '1:' + (acc.leverage ?? 0), // 实际杠杆
+            floatingPL: formatMoney(floating), // 盈亏
+            platform: acc.platform || 'MT4',
+            server: acc.groupCode || '',
+            login: acc.login.toString()
+        };
+    })
+)
+onMounted(async () => {
+    await getAccountList()
+})
 </script>
 
 <style scoped lang="scss">