Ver Fonte

feat:跟单

ljc há 1 mês atrás
pai
commit
7f699a32d5

+ 21 - 14
components/cwg-payment.vue

@@ -57,7 +57,7 @@
             <switch :checked="!isShow" @change="toggleShow" color="#6c8595" style="transform:scale(0.7)" />
           </view>
           <view class="drawer-content">
-            <view class="balance-amount">{{t('Documentary.console.item15')}}{{ followBalance }} USD</view>
+            <view class="balance-amount">{{ t('Documentary.console.item15') }}{{ followBalance }} USD</view>
 
           </view>
           <view class="drawer-actions">
@@ -70,7 +70,7 @@
 </template>
 
 <script setup lang="ts">
-  import { computed, ref, onMounted, watch } from 'vue'
+  import { computed, ref, onMounted, onUnmounted, watch } from 'vue'
   import { newsApi } from '@/service/news'
   import { storeToRefs } from 'pinia'
   import useRouter from '@/hooks/useRouter'
@@ -214,7 +214,7 @@
   }
 
   const goIbPages = (type) => {
-    let path,query
+    let path, query
     if (type == 1) {
       path = '/pages/ib/withdraw-select'
     } else if (type == 2) {
@@ -223,13 +223,13 @@
       path = '/pages/ib/transfer'
       query = { tab: 2 }
     }
-    router.push({ path,query })
+    router.push({ path, query })
     close()
   }
 
 
   const toPaymentHistory = () => {
-    router.push({ path: '/pages/customer/payment-history',query:{fromPending: "true"} })
+    router.push({ path: '/pages/customer/payment-history', query: { fromPending: 'true' } })
   }
 
   const getIbData = async () => {
@@ -241,22 +241,29 @@
       uni.showToast({ title: res.msg, icon: 'none' })
     }
   }
-  watch(() => mode.value, (newMode) => {
-    if (!userToken.value) return
-      console.log(newMode,'mode')
+  const getPay = (newMode) => {
     if (newMode == 'customer') {
       getWalletList()
       getPendingWithdrawAmount()
-    }else if (newMode == 'ib') {
+    } else if (newMode == 'ib') {
       getIbData()
-    }else if (newMode == 'follow') {
+    } else if (newMode == 'follow') {
       getMoneyList()
     }
-  },
-  { immediate: true })
+  }
+  watch(() => mode.value, (newMode) => {
+      if (!userToken.value) return
+      console.log(newMode, 'mode')
+      getPay(newMode)
+    },
+    { immediate: true })
   onMounted(() => {
-
-
+    uni.$on('updatePayment', () => {
+      getPay(mode.value)
+    })
+  })
+  onUnmounted(() => {
+    uni.$off('updatePayment')
   })
 </script>
 

+ 25 - 12
components/cwg-sidebar.vue

@@ -221,18 +221,6 @@ const getMoneyList = async () => {
   }
 }
 
-watch(() => mode.value, (newMode) => {
-  if (!userToken.value) return
-  if (newMode == 'customer') {
-    getWalletList()
-    getPendingWithdrawAmount()
-  } else if (newMode == 'ib') {
-    getIbData()
-  } else if (newMode == 'follow') {
-    getMoneyList()
-  }
-}, { immediate: true })
-
 const toggleShow = (e: any) => {
   isShow.value = !e.detail.value
 }
@@ -263,6 +251,31 @@ const goIbPages = (type: number) => {
   }
   if (path) router.push({ path, query })
 }
+
+const getPay = (newMode) => {
+  if (newMode == 'customer') {
+    getWalletList()
+    getPendingWithdrawAmount()
+  } else if (newMode == 'ib') {
+    getIbData()
+  } else if (newMode == 'follow') {
+    getMoneyList()
+  }
+}
+watch(() => mode.value, (newMode) => {
+    if (!userToken.value) return
+    console.log(newMode, 'mode')
+    getPay(newMode)
+  },
+  { immediate: true })
+onMounted(() => {
+  uni.$on('updatePayment', () => {
+    getPay(mode.value)
+  })
+})
+onUnmounted(() => {
+  uni.$off('updatePayment')
+})
 </script>
 
 <style scoped lang="scss">

+ 9 - 0
composables/useMenuSplit.ts

@@ -259,6 +259,15 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
                 { path: '/pages/ib/complexReport', label: 'Home.page_ib.item11', icon: 'icon-withdrawal' },
             ],
         },
+        {
+            isOpenMenu: false,
+            path: '/',
+            label: 'Home.page_ib.item12',
+            icon: 'crm-bulletin',
+            children: [
+                { path: '/pages/ib/promotion', label: 'Home.page_ib.item13', icon: 'icon-withdrawal' },
+            ],
+        },
     ])
 
     const followBaseMenus = computed<MenuItem[]>(() => [

+ 3 - 1
locale/cn.json

@@ -1109,7 +1109,9 @@
       "item8": "佣金模板",
       "item9": "代理内转",
       "item10": "账户管理",
-      "item11": "综合报告"
+      "item11": "综合报告",
+      "item12": "宣传",
+      "item13": "推广素材"
     },
     "page_shop": {
       "item1": "商城首页",

+ 7 - 0
pages.json

@@ -331,6 +331,13 @@
         "navigationStyle": "custom"
       }
     },
+    {
+      "path": "pages/ib/promotion",
+      "style": {
+        "navigationBarTitleText": "",
+        "navigationStyle": "custom"
+      }
+    },
     {
       "path": "pages/analytics/analystViews",
       "style": {

+ 12 - 2
pages/follow/components/applySignalDialog.vue

@@ -216,8 +216,18 @@ const groupTypeName = (type) => {
   return option ? option.text : type
 }
 
-const groupCurrency = (currency) => {
-  return currency ? ` (${currency}) ` : ' '
+const groupCurrency = (type) => {
+  if (type == "GBP") {
+    return ": £";
+  } else if (type == "USD") {
+    return ": $";
+  } else if (type == "EUR") {
+    return ": €";
+  } else if (type == "USC") {
+    return ": ¢";
+  } else {
+    return ": $";
+  }
 }
 
 const rules = {

+ 13 - 2
pages/follow/index.vue

@@ -339,6 +339,7 @@
   }
 
   const groupCurrency = (type) => {
+    console.log(type,'usd')
     if (type == 'GBP') {
       return ': £'
     } else if (type == 'USD') {
@@ -352,8 +353,18 @@
     }
   }
 
-  const groupCurrency1 = (currency) => {
-    return currency || ''
+  const groupCurrency1 = (type) => {
+    if (type == "GBP") {
+      return "£";
+    } else if (type == "USD") {
+      return "$";
+    } else if (type == "EUR") {
+      return "€";
+    } else if (type == "USC") {
+      return "¢";
+    } else {
+      return "$";
+    }
   }
 
   const handleCommand = ({ value }) => {

+ 425 - 0
pages/ib/promotion.vue

@@ -0,0 +1,425 @@
+<template>
+  <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
+    <cwg-header title="推广素材" />
+    
+    <!-- 顶部 Tabs -->
+    <cwg-asset-tabs v-model="activeTab" :tabs="tabsConfig" />
+
+    <view class="main-container">
+      <!-- 工具栏:筛选与排序 -->
+      <view class="toolbar">
+      </view>
+
+      <!-- 视频 (Tab 3) -->
+      <view v-if="activeTab === 3" class="media-grid">
+        <view class="media-card" v-for="item in videoList" :key="item.id">
+          <view class="media-cover">
+            <image class="cover-img" :src="item.cover" mode="aspectFill"></image>
+            <view class="play-btn">
+              <cwg-icon name="crm-play" :size="32" color="#fff" />
+            </view>
+            <view v-if="item.isNew" class="badge-new">新</view>
+          </view>
+          <view class="media-info">
+            <view class="info-row">
+              <text class="label">语言</text>
+              <text class="value">{{ item.languages }}</text>
+            </view>
+            <view class="info-row">
+              <text class="label">长宽比</text>
+              <text class="value tag">{{ item.aspectRatio }}</text>
+            </view>
+            <view class="info-row">
+              <text class="label">类型</text>
+              <text class="value tag">{{ item.type }}</text>
+            </view>
+          </view>
+          <view class="media-actions">
+            <checkbox class="action-checkbox" style="transform:scale(0.8)" />
+            <button class="action-btn main-btn">选择视频</button>
+            <button class="action-btn icon-btn">
+              <cwg-icon name="crm-download" :size="18" color="#333" />
+            </button>
+          </view>
+        </view>
+      </view>
+
+      <!-- GIFs (Tab 5) -->
+      <view v-if="activeTab === 5" class="media-grid">
+        <view class="media-card" v-for="item in gifList" :key="item.id">
+          <view class="media-cover checkerboard">
+            <image class="cover-img contain" :src="item.cover" mode="aspectFit"></image>
+            <view v-if="item.isNew" class="badge-new">新</view>
+          </view>
+          <view class="media-info">
+            <view class="info-title">{{ item.title }}</view>
+            <view class="info-desc">{{ item.desc }}</view>
+            <view class="info-row mt-10">
+              <text class="label">语言</text>
+              <text class="value">{{ item.languages }}</text>
+            </view>
+            <view class="info-row">
+              <text class="label">尺寸</text>
+              <text class="value">{{ item.size }}</text>
+            </view>
+            <view class="info-row">
+              <text class="label">类型</text>
+              <text class="value tag">{{ item.type }}</text>
+            </view>
+          </view>
+          <view class="media-actions">
+            <checkbox class="action-checkbox" style="transform:scale(0.8)" />
+            <button class="action-btn main-btn">选择GIF</button>
+            <button class="action-btn icon-btn">
+              <cwg-icon name="crm-download" :size="18" color="#333" />
+            </button>
+          </view>
+        </view>
+      </view>
+
+      <!-- 标志 (Tab 6) -->
+      <view v-if="activeTab === 6" class="media-grid logo-grid">
+        <view class="media-card logo-card" v-for="item in logoList" :key="item.id">
+          <view class="logo-cover" :class="item.theme">
+            <image class="logo-img" :src="item.cover" mode="aspectFit"></image>
+          </view>
+          <view class="media-actions logo-actions">
+            <button class="action-btn main-btn">下载</button>
+          </view>
+        </view>
+      </view>
+    </view>
+  </cwg-page-wrapper>
+</template>
+
+<script setup lang="ts">
+import { ref, computed } from 'vue'
+
+const activeTab = ref(3)
+
+const tabsConfig = computed(() => [
+  { text: '视频 (790)', value: 3 },
+  { text: 'GIFs (30)', value: 5 },
+  { text: '标志 (4)', value: 6 },
+])
+
+// 模拟数据:视频
+const videoList = ref([
+  {
+    id: 1,
+    isNew: true,
+    cover: 'https://coresg-normal.trae.ai/api/ide/v1/text_to_image?prompt=A%20person%20writing%20in%20a%20notebook%20on%20a%20wooden%20desk%20with%20a%20laptop%20and%20headphones%2C%20top-down%20view&image_size=landscape_16_9',
+    languages: '中文(简体)、孟加拉语、英语 +2',
+    aspectRatio: '纵向',
+    type: "Exness' unique features"
+  },
+  {
+    id: 2,
+    isNew: true,
+    cover: 'https://coresg-normal.trae.ai/api/ide/v1/text_to_image?prompt=A%20person%20using%20a%20trading%20app%20on%20a%20smartphone%20with%20a%20laptop%20in%20the%20background&image_size=landscape_16_9',
+    languages: '中文(简体)、孟加拉语、英语 +2',
+    aspectRatio: '纵向',
+    type: "Fast execution"
+  },
+  {
+    id: 3,
+    isNew: false,
+    cover: 'https://coresg-normal.trae.ai/api/ide/v1/text_to_image?prompt=A%20professional%20trading%20setup%20with%20multiple%20monitors%20displaying%20charts&image_size=landscape_16_9',
+    languages: '英语、西班牙语、葡萄牙语',
+    aspectRatio: '横向',
+    type: "Trading conditions"
+  }
+])
+
+// 模拟数据:GIFs
+const gifList = ref([
+  {
+    id: 1,
+    isNew: true,
+    title: '节省交易成本',
+    desc: '提供小点差和热门资产的无隔夜利息交易,助您保留更多收益。',
+    cover: 'https://coresg-normal.trae.ai/api/ide/v1/text_to_image?prompt=A%20clean%20financial%20trading%20chart%20with%20green%20and%20blue%20lines%20on%20a%20dark%20background%20with%20currency%20symbols&image_size=square',
+    languages: '英语、印尼语、西班牙语(拉丁美洲) +2',
+    size: '300x300、300x600、728x90',
+    type: 'Lower your trading cost'
+  },
+  {
+    id: 2,
+    isNew: true,
+    title: '掌控您的外汇交易',
+    desc: '以小点差和灵活杠杆交易直盘、交叉盘及小众外汇对。',
+    cover: 'https://coresg-normal.trae.ai/api/ide/v1/text_to_image?prompt=A%20minimalist%20blue%20line%20chart%20on%20a%20white%20background%20with%20UK%20and%20EU%20flags&image_size=square',
+    languages: '英语、印尼语、西班牙语(拉丁美洲) +2',
+    size: '300x300、300x600、728x90',
+    type: '外汇'
+  }
+])
+
+// 模拟数据:标志
+const logoList = ref([
+  {
+    id: 1,
+    theme: 'light',
+    cover: 'https://coresg-normal.trae.ai/api/ide/v1/text_to_image?prompt=The%20word%20EXNESS%20in%20black%20bold%20minimalist%20typography%20on%20a%20white%20background&image_size=landscape_16_9'
+  },
+  {
+    id: 2,
+    theme: 'dark',
+    cover: 'https://coresg-normal.trae.ai/api/ide/v1/text_to_image?prompt=The%20word%20EXNESS%20in%20white%20bold%20minimalist%20typography%20on%20a%20dark%20navy%20background&image_size=landscape_16_9'
+  },
+  {
+    id: 3,
+    theme: 'light',
+    cover: 'https://coresg-normal.trae.ai/api/ide/v1/text_to_image?prompt=The%20word%20IB%20EXNESS%20in%20black%20bold%20minimalist%20typography%20on%20a%20white%20background&image_size=landscape_16_9'
+  },
+  {
+    id: 4,
+    theme: 'dark',
+    cover: 'https://coresg-normal.trae.ai/api/ide/v1/text_to_image?prompt=The%20word%20IB%20EXNESS%20in%20white%20bold%20minimalist%20typography%20on%20a%20dark%20navy%20background&image_size=landscape_16_9'
+  }
+])
+</script>
+
+<style lang="scss" scoped>
+@import "@/uni.scss";
+
+.promotion-page {
+  background-color: #f7f8fa;
+  min-height: 100vh;
+}
+
+.main-container {
+  padding: px2rpx(20);
+}
+
+.toolbar {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: px2rpx(20);
+
+  .filter-btn {
+    display: flex;
+    align-items: center;
+    background-color: #f5f5f5;
+    padding: px2rpx(8) px2rpx(16);
+    border-radius: px2rpx(4);
+    font-size: px2rpx(14);
+    color: #333;
+  }
+
+  .sort-group {
+    display: flex;
+    border: 1px solid #e4e7ed;
+    border-radius: px2rpx(4);
+    overflow: hidden;
+    background-color: #fff;
+
+    .sort-item {
+      padding: px2rpx(8) px2rpx(16);
+      font-size: px2rpx(14);
+      color: #666;
+      border-right: 1px solid #e4e7ed;
+      cursor: pointer;
+
+      &:last-child {
+        border-right: none;
+      }
+
+      &.active {
+        background-color: #f5f5f5;
+        font-weight: 500;
+        color: #333;
+      }
+    }
+  }
+}
+
+.media-grid {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(px2rpx(320), 1fr));
+  gap: px2rpx(20);
+
+  &.logo-grid {
+    grid-template-columns: repeat(auto-fill, minmax(px2rpx(400), 1fr));
+  }
+}
+
+.media-card {
+  background: #fff;
+  border-radius: px2rpx(8);
+  border: 1px solid #ebeef5;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+
+  .media-cover {
+    position: relative;
+    height: px2rpx(220);
+    background-color: #000;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+    &.checkerboard {
+      background-image: linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee),
+        linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee);
+      background-size: 20px 20px;
+      background-position: 0 0, 10px 10px;
+      background-color: #fff;
+    }
+
+    .cover-img {
+      width: 100%;
+      height: 100%;
+
+      &.contain {
+        object-fit: contain;
+      }
+    }
+
+    .play-btn {
+      position: absolute;
+      width: px2rpx(50);
+      height: px2rpx(50);
+      background-color: rgba(255, 255, 255, 0.3);
+      border-radius: 50%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      backdrop-filter: blur(4px);
+    }
+
+    .badge-new {
+      position: absolute;
+      top: px2rpx(10);
+      right: px2rpx(10);
+      background-color: #d32f2f;
+      color: #fff;
+      font-size: px2rpx(12);
+      padding: px2rpx(2) px2rpx(8);
+      border-radius: px2rpx(4);
+    }
+  }
+
+  .media-info {
+    padding: px2rpx(16);
+    flex: 1;
+
+    .info-title {
+      font-size: px2rpx(16);
+      font-weight: bold;
+      color: #333;
+      margin-bottom: px2rpx(8);
+    }
+
+    .info-desc {
+      font-size: px2rpx(13);
+      color: #666;
+      line-height: 1.5;
+      margin-bottom: px2rpx(12);
+    }
+
+    .info-row {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: px2rpx(10) 0;
+      border-bottom: 1px solid #f0f0f0;
+      font-size: px2rpx(13);
+
+      &.mt-10 {
+        margin-top: px2rpx(10);
+      }
+
+      &:last-child {
+        border-bottom: none;
+        padding-bottom: 0;
+      }
+
+      .label {
+        color: #999;
+      }
+
+      .value {
+        color: #333;
+        font-weight: 500;
+        text-align: right;
+
+        &.tag {
+          background-color: #f5f5f5;
+          padding: px2rpx(2) px2rpx(8);
+          border-radius: px2rpx(12);
+          font-weight: normal;
+        }
+      }
+    }
+  }
+
+  .media-actions {
+    display: flex;
+    align-items: center;
+    padding: px2rpx(16);
+    gap: px2rpx(10);
+    border-top: 1px solid #ebeef5;
+
+    &.logo-actions {
+      justify-content: center;
+    }
+
+    .action-checkbox {
+      flex-shrink: 0;
+    }
+
+    .action-btn {
+      height: px2rpx(36);
+      line-height: px2rpx(36);
+      font-size: px2rpx(14);
+      margin: 0;
+      border-radius: px2rpx(4);
+      background-color: #f5f5f5;
+      color: #333;
+      border: none;
+
+      &::after {
+        border: none;
+      }
+
+      &.main-btn {
+        flex: 1;
+      }
+
+      &.icon-btn {
+        width: px2rpx(36);
+        padding: 0;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+  }
+}
+
+.logo-card {
+  .logo-cover {
+    height: px2rpx(260);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: px2rpx(40);
+
+    &.light {
+      background-color: #fff;
+    }
+
+    &.dark {
+      background-color: #0b101e;
+    }
+
+    .logo-img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+}
+</style>

+ 1 - 0
static/icons/crm-bulletin.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M525.2 82.9C536.7 88 544 99.4 544 112L544 528C544 540.6 536.7 552 525.2 557.1C513.7 562.2 500.4 560.3 490.9 552L444.3 511.3C400.7 473.2 345.6 451 287.9 448.3L287.9 544C287.9 561.7 273.6 576 255.9 576L223.9 576C206.2 576 191.9 561.7 191.9 544L191.9 448C121.3 448 64 390.7 64 320C64 249.3 121.3 192 192 192L276.5 192C338.3 191.8 397.9 169.3 444.4 128.7L491 88C500.4 79.7 513.9 77.8 525.3 82.9zM288 384L288 384.2C358.3 386.9 425.8 412.7 480 457.6L480 182.3C425.8 227.2 358.3 253 288 255.7L288 384z"/></svg>