zhb 3 ماه پیش
والد
کامیت
c1a878e13c
5فایلهای تغییر یافته به همراه335 افزوده شده و 8 حذف شده
  1. 71 7
      components/cwg-page-wrapper.vue
  2. 112 0
      components/cwg-pc-header.vue
  3. 78 0
      components/cwg-sidebar.vue
  4. 73 0
      components/cwg-submenu.vue
  5. 1 1
      pages/login/index.vue

+ 71 - 7
components/cwg-page-wrapper.vue

@@ -1,24 +1,69 @@
 <template>
   <view class="page-wrapper">
+    <match-media :min-width="991" v-if="!isLoginPage">
+      <view class="left-sidebar">
+        <cwg-sidebar />
+        <cwg-submenu v-if="sidebarVisible" :items="submenuItems" @submenu-click="onSubmenuClick" />
+      </view>
+    </match-media>
     <cwg-progress />
-    <cwg-header v-if="!isHeaderFixed" />
-    <slot></slot>
-    <view :style="{ height: isTabBarPage ? '60px' : '0px' }" />
-    <cwg-tab-bar v-model:isTabBarPage="isTabBarPage" />
+    <view class="page-content">
+      <match-media :min-width="991" v-if="!isLoginPage">
+        <cwg-pc-header @toggle-sidebar="toggleSidebar" />
+      </match-media>
+      <match-media :max-width="991">
+        <cwg-header v-if="!isHeaderFixed" />
+      </match-media>
+      <view class="content-wrapper">
+        <slot />
+      </view>
+      <view :style="{ height: isTabBarPage ? '60px' : '0px' }" />
+    </view>
+    <match-media :max-width="991">
+      <cwg-tab-bar v-model:isTabBarPage="isTabBarPage" />
+    </match-media>
   </view>
 </template>
 
-<script setup>
+<script setup lang="ts">
 import { ref } from "vue";
 import { onLoad, onShow } from '@dcloudio/uni-app'
 import { updateRoute } from '@/hooks/useRoute'
+interface MenuItem {
+  key: string;
+  label: string;
+  icon?: string;
+  children?: MenuItem[];
+}
+
 const props = defineProps({
   isHeaderFixed: {
     type: Boolean,
     default: false
+  },
+  isLoginPage: {
+    type: Boolean,
+    default: false
   }
 })
 const isTabBarPage = ref(false)
+const submenuItems = ref<MenuItem[]>([{ key: 'client', label: 'Client Zone', icon: 'icon-client' },
+{ key: 'promotion', label: 'Promotion Center', icon: 'icon-promotion' },
+{ key: 'deposit', label: 'Deposit', icon: 'icon-deposit' },
+{ key: 'withdrawal', label: 'Withdrawal', icon: 'icon-withdrawal' },
+{ key: 'payment', label: 'Payment History', icon: 'icon-payment' },
+{ key: 'transfer', label: 'Internal Transfer', icon: 'icon-transfer' },
+{ key: 'application', label: 'Application History', icon: 'icon-application' },
+{ key: 'ib', label: 'IB Zone', icon: 'icon-ib' },
+{ key: 'copy', label: 'Copy Trading', icon: 'icon-copy' },
+{ key: 'platform', label: 'Trading Platform', icon: 'icon-platform' },
+{ key: 'chat', label: 'Online Chat', icon: 'icon-chat' },])
+const sidebarVisible = ref(true)
+
+function toggleSidebar() {
+  sidebarVisible.value = !sidebarVisible.value;
+}
+
 onLoad(() => {
   updateRoute()
 })
@@ -33,8 +78,27 @@ onShow(() => {
 @import "@/uni.scss";
 
 .page-wrapper {
-  padding: 0 px2rpx(24) px2rpx(0) px2rpx(24);
+  display: flex;
+  flex-direction: row;
+  height: 100vh;
+  overflow: hidden;
+}
+
+.left-sidebar {
+  display: flex;
+  flex-direction: row;
+}
+
+.page-content {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+}
+
+.content-wrapper {
+  flex: 1;
+  // padding: 0 px2rpx(24) px2rpx(0) px2rpx(24);
   box-sizing: border-box;
-  border: 1px solid rgba(0, 0, 0, 0);
+  overflow-y: auto;
 }
 </style>

+ 112 - 0
components/cwg-pc-header.vue

@@ -0,0 +1,112 @@
+<template>
+    <header class="cwg-pc-header">
+        <div class="left">
+            <span class="back-arrow" @click="$emit('toggle-sidebar')">&#8592;</span>
+        </div>
+        <div class="center"></div>
+        <div class="right">
+            <div class="lang-select">
+                <img src="/static/flag-en.png" alt="en" class="flag" />
+                <span>English</span>
+                <span class="arrow">▼</span>
+            </div>
+            <span class="icon sun">🌞</span>
+            <span class="icon bell">🔔<span class="dot"></span></span>
+            <span class="icon avatar"><img src="/static/avatar.png" alt="avatar" /></span>
+            <span class="icon logo"><img src="/static/logo.png" alt="logo" /></span>
+        </div>
+    </header>
+</template>
+
+<script setup lang="ts">
+// 可根据需要添加交互逻辑
+// 通过 $emit('toggle-sidebar') 触发父组件事件
+</script>
+
+<style scoped>
+.cwg-pc-header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    height: 56px;
+    background: #fff;
+    border-bottom: 1px solid #f0f0f0;
+    padding: 0 32px;
+    position: relative;
+    z-index: 10;
+}
+
+.left {
+    display: flex;
+    align-items: center;
+}
+
+.back-arrow {
+    color: #e74c3c;
+    font-size: 22px;
+    cursor: pointer;
+    margin-right: 16px;
+}
+
+.center {
+    flex: 1;
+}
+
+.right {
+    display: flex;
+    align-items: center;
+    gap: 18px;
+}
+
+.lang-select {
+    display: flex;
+    align-items: center;
+    background: #f5f7fa;
+    border-radius: 18px;
+    padding: 4px 12px;
+    font-size: 14px;
+    cursor: pointer;
+}
+
+.flag {
+    width: 22px;
+    height: 16px;
+    margin-right: 6px;
+}
+
+.arrow {
+    margin-left: 4px;
+    font-size: 12px;
+}
+
+.icon {
+    font-size: 20px;
+    position: relative;
+    cursor: pointer;
+}
+
+.bell .dot {
+    position: absolute;
+    top: 0;
+    right: -2px;
+    width: 7px;
+    height: 7px;
+    background: #27ae60;
+    border-radius: 50%;
+    display: inline-block;
+}
+
+.avatar img {
+    width: 32px;
+    height: 32px;
+    border-radius: 50%;
+    background: #eee;
+}
+
+.logo img {
+    width: 36px;
+    height: 36px;
+    border-radius: 50%;
+    background: #fff;
+}
+</style>

+ 78 - 0
components/cwg-sidebar.vue

@@ -0,0 +1,78 @@
+<template>
+    <view class="cwg-sidebar">
+        <image class="logo" src="/static/images/logo3.png" mode="widthFix" />
+        <view class="menu">
+            <view class="menu-item" v-for="item in menu" :key="item.key" @click="handleClick(item)">
+                <cwg-icon color="#fff" icon="chevron-right" class="arrow" />
+            </view>
+        </view>
+    </view>
+</template>
+
+<script lang="ts" setup>
+import { ref } from 'vue';
+interface MenuItem {
+    key: string;
+    label: string;
+    icon?: string;
+    children?: MenuItem[];
+}
+
+const emit = defineEmits(['menu-click']);
+
+const menu = ref<MenuItem[]>([
+    { key: 'client', label: 'Client Zone', icon: 'icon-client' },
+    { key: 'promotion', label: 'Promotion Center', icon: 'icon-promotion' },
+    { key: 'deposit', label: 'Deposit', icon: 'icon-deposit' },
+    { key: 'withdrawal', label: 'Withdrawal', icon: 'icon-withdrawal' },
+]);
+
+function handleClick(item: MenuItem) {
+    emit('menu-click', item);
+}
+</script>
+
+<style scoped lang="scss">
+@import "@/uni.scss";
+
+.cwg-sidebar {
+    width: px2rpx(100);
+    background: #11224d;
+    color: #fff;
+    height: 100vh;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding-top: px2rpx(20);
+    box-sizing: border-box;
+
+    .logo {
+        width: px2rpx(54);
+    }
+
+    .menu {
+        display: flex;
+        flex-direction: column;
+        gap: px2rpx(20);
+        align-items: center;
+        padding-top: px2rpx(30);
+    }
+
+    .menu-item {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: px2rpx(54);
+        height: px2rpx(54);
+        border-radius: px2rpx(12);
+        cursor: pointer;
+        background: #122D6B;
+        transition: background 0.2s;
+
+        &:hover {
+            background: #24325e;
+        }
+
+    }
+}
+</style>

+ 73 - 0
components/cwg-submenu.vue

@@ -0,0 +1,73 @@
+<template>
+    <view class="cwg-submenu">
+        <view class="cwg-submenu-title">
+            <text>
+                CWG Markets
+            </text>
+        </view>
+        <view class="submenu">
+            <view class="cwg-submenu-item" v-for="item in items" :key="item.key" @click="handleClick(item)">
+                <text>{{ item.label }}</text>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script lang="ts" setup>
+interface MenuItem {
+    key: string;
+    label: string;
+    icon?: string;
+    children?: MenuItem[];
+}
+const props = defineProps<{ items: MenuItem[] }>();
+const emit = defineEmits(['submenu-click']);
+function handleClick(item: MenuItem) {
+    emit('submenu-click', item);
+}
+</script>
+
+<style scoped lang="scss">
+@import "@/uni.scss";
+
+.cwg-submenu {
+    background: #fff;
+    position: relative;
+    z-index: 11;
+
+    padding: 0;
+    margin: 0;
+    box-shadow: 4px 0 12px rgba(15, 23, 43, 0.08);
+    border-left: 1px solid #E2E8F0;
+
+    .cwg-submenu-title {
+        padding: 20px;
+        font-size: 16px;
+        font-weight: 700;
+        border-bottom: 1px solid #E2E8F0;
+        color: #0F172B;
+    }
+
+    .submenu {
+        margin: 0 px2rpx(20);
+        width: px2rpx(200);
+    }
+
+    .cwg-submenu-item {
+        padding: 20px 0px;
+        cursor: pointer;
+        color: #0F172B;
+        font-weight: 600;
+        transition: background 0.2s;
+        display: flex;
+        align-items: center;
+        gap: 10px;
+        font-size: 14px;
+        border-bottom: 1px solid #E2E8F0;
+    }
+
+    .cwg-submenu-item:hover {
+        // background: #f0f0f0;
+    }
+}
+</style>

+ 1 - 1
pages/login/index.vue

@@ -132,7 +132,7 @@ const inputType = ref("password");
 </script>
 
 <template>
-  <cwg-page-wrapper class="login-page" :isHeaderFixed="true">
+  <cwg-page-wrapper class="login-page" :isHeaderFixed="true" :isLoginPage="true">
     <uni-row class="demo-uni-row">
       <match-media :min-width="991">
         <uni-col :xs="24" :sm="24" :md="12" :lg="14" :xl="16" class="left-bg">