瀏覽代碼

feature: card页面

ljc 7 月之前
父節點
當前提交
e99dca96f2

+ 2 - 0
package.json

@@ -42,6 +42,8 @@
     "pinia-plugin-persistedstate": "^2.1.1",
     "pinyin-pro": "^3.27.0",
     "print-js": "^1.6.0",
+    "qrcodejs2": "^0.0.2",
+    "qrcodejs2-fix": "^0.0.1",
     "raf": "^3.4.1",
     "resize-observer-polyfill": "^1.5.1",
     "sass": "^1.54.0",

+ 141 - 0
src/components/QRCode/index.vue

@@ -0,0 +1,141 @@
+<template>
+  <div>
+    <div ref="qrCodeRef"></div>
+    <div v-if="download" class="btn" @click="downloadQrCode">
+      <span class="crm-cursor">{{ $t('Raffle.RegistrationForm.item8') }}</span>
+    </div>
+  </div>
+</template>
+
+<script setup>
+  import { ref, watch, onMounted, nextTick } from 'vue'
+  import QRCode from 'qrcodejs2-fix'
+
+  // Props
+  const props = defineProps({
+    text: {
+      type: String,
+      default: '',
+    },
+    width: {
+      type: Number,
+      default: 200,
+    },
+    height: {
+      type: Number,
+      default: 200,
+    },
+    colorDark: {
+      type: String,
+      default: '#333333',
+    },
+    colorLight: {
+      type: String,
+      default: '#ffffff',
+    },
+    logoImage: {
+      type: String,
+      default: '',
+    },
+    download: {
+      type: Boolean,
+      default: false,
+    },
+  })
+
+  // Refs
+  const qrCodeRef = ref(null)
+  const qrcode = ref(null)
+
+  // Methods
+  const createQrCode = () => {
+    if (!props.text) return
+
+    // 先清空
+    if (qrcode.value && qrCodeRef.value) {
+      qrCodeRef.value.innerHTML = ''
+    }
+
+    // 生成二维码
+    qrcode.value = new QRCode(qrCodeRef.value, {
+      text: props.text,
+      width: props.width,
+      height: props.height,
+      colorDark: props.colorDark,
+      colorLight: props.colorLight,
+      correctLevel: QRCode.CorrectLevel.H,
+    })
+
+    // 添加二维码中间的图片
+    if (props.logoImage) {
+      const logo = new Image()
+      logo.setAttribute('crossOrigin', 'Anonymous')
+      logo.src = props.logoImage
+      logo.onload = () => {
+        const qrImg = qrcode.value._el.getElementsByTagName('img')[0]
+        const canvas = qrcode.value._el.getElementsByTagName('canvas')[0]
+        qrcode.value._el.title = ''
+        canvas.style.display = 'inline-block'
+        const ctx = canvas.getContext('2d')
+        // 设置logo的大小为二维码图片缩小的3.7倍
+        ctx.drawImage(logo, (300 - 300 / 4.5) / 2, (300 - 300 / 4.5) / 2, 300 / 4.5, 300 / 4.5)
+        qrImg.src = canvas.toDataURL()
+        qrImg.style.display = 'none'
+        qrCodeRef.value.appendChild(qrcode.value._el)
+      }
+    }
+  }
+
+  const downloadQrCode = () => {
+    const canvasData = qrCodeRef.value.getElementsByTagName('canvas')
+    if (canvasData.length > 0) {
+      const a = document.createElement('a')
+      const event = new MouseEvent('click')
+      a.href = canvasData[0].toDataURL('image/png')
+      a.download = 'qrcode.png'
+      a.dispatchEvent(event)
+    }
+  }
+
+  // Watchers
+  watch(
+    () => props.text,
+    () => {
+      nextTick(() => {
+        createQrCode()
+      })
+    }
+  )
+
+  // Lifecycle
+  onMounted(() => {
+    createQrCode()
+  })
+
+  // 给父组件暴露方法
+  defineExpose({
+    download: downloadQrCode,
+  })
+</script>
+
+<style scoped lang="scss">
+  .btn {
+    display: flex;
+    justify-content: center;
+
+    span {
+      display: inline-block;
+      margin: 10px 15px;
+      padding: 6px 15px;
+      border-radius: 2px;
+      background-color: #6b7188;
+      color: #ffffff;
+      cursor: pointer;
+      transition: background-color 0.3s ease;
+
+      &:hover {
+        background-color: #5a6074;
+      }
+    }
+  }
+</style>

+ 6 - 8
src/lib/service.js

@@ -1,6 +1,5 @@
 import axios from 'axios'
 import Config from '../config'
-import { useRouter } from 'vue-router'
 import { useStore } from 'vuex'
 // axios.defaults.baseURL = Config.Host
 
@@ -17,7 +16,6 @@ if (sessionStorage.getItem('CLIENT')) {
 class Service {
   constructor() {
     this.axio = axios
-    this.router = useRouter()
   }
 
   // session过期
@@ -30,12 +28,12 @@ class Service {
   }
 
   // 统一登出
-  Logout() {
-    this.router.push({
-      name: 'login',
-    })
-    location.reload()
-  }
+  // Logout() {
+  //   this.router.push({
+  //     name: 'login',
+  //   })
+  //   location.reload()
+  // }
 
   // method GET
   get(url, params) {

+ 2 - 1
src/routers/index.ts

@@ -68,11 +68,12 @@ export const constantRoutes: Array<RouteRecordRaw & extendRoute> = [
     path: '/',
     name: '',
     component: Home,
-    redirect: '/card/order',
+    // redirect: '/card/order',
     meta: {
       OnBreadCrumb: false,
       requiresAuth: true,
     },
+    children: [uCardRoute],
   },
 ]
 

+ 2 - 1
src/routers/modules/uCard.ts

@@ -13,7 +13,8 @@ const uCardRoute = {
       },
       path: 'order',
       name: 'R-CardOrder',
-      component: () => import(/* webpackChunkName: "CardOrder" */ '@/views/card/CardOrder.vue'),
+      component: () =>
+        import(/* webpackChunkName: "CardOrder" */ '@/views/card/CardOrder/index.vue'),
     },
     //
     //   {

+ 12 - 0
src/service/enter.ts

@@ -0,0 +1,12 @@
+import Service from '../lib/service.js'
+import axios from 'axios'
+import Config from '../config'
+
+class EnterService extends Service {
+  constructor() {
+    super()
+    axios.defaults.baseURL = Config.Host85
+  }
+}
+
+export default new EnterService()

+ 6 - 3
src/utils/export.js

@@ -1,4 +1,7 @@
 import axios from 'axios'
+import i18n from '../i18n'
+import pigeon from '@/lib/pigeon'
+
 export function exportExcel(that, url, params, name = 'Download') {
   axios
     .post(url, { ...params }, { responseType: 'blob' })
@@ -17,14 +20,14 @@ export function exportExcel(that, url, params, name = 'Download') {
             window.URL.revokeObjectURL(url)
           }
         } else {
-          that.$pigeon.MessageError(that.$i18n.t('Msg.Download'))
+          pigeon.MessageError(i18n.t('Msg.Download'))
         }
       } catch (error) {
-        that.$pigeon.MessageError(that.$i18n.t('Msg.Download'))
+        pigeon.MessageError(i18n.t('Msg.Download'))
       }
     })
     .catch(() => {
-      that.$pigeon.MessageError(that.$i18n.t('Msg.SystemError'))
+      pigeon.MessageError(i18n.t('Msg.SystemError'))
     })
 }
 function formatDate(date = new Date(), format = 'yyyyMMddHHmmss') {

+ 20 - 17
src/views/card/CardOrder/index.vue

@@ -124,7 +124,7 @@
 
       <div class="card-mock-demo" style="margin: 30px 0">
         <el-table :data="mock_tableData" stripe style="margin-top: 20px; width: 100%">
-          <el-table-column prop="" align="left" :label="$i18n.t('Label.CidAccount')">
+          <el-table-column prop="" align="left" :label="$t('Label.CidAccount')">
             <template #default="scope">
               <span
                 v-if="scope.row.cId && display['R-CardOrder-Btn1'].show"
@@ -135,7 +135,7 @@
               <span v-else>{{ scope.row.cId || '--' }}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="" align="left" :label="$i18n.t('Label.Name')">
+          <el-table-column prop="" align="left" :label="$t('Label.Name')">
             <template #default="scope">
               <span v-if="scope.row.firstName">{{ scope.row.firstName + ' ' }}</span>
               <span v-if="scope.row.middle">{{ scope.row.middle + ' ' }}</span>
@@ -145,7 +145,7 @@
               }}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="" align="left" :label="$i18n.t('Label.Email')">
+          <el-table-column prop="" align="left" :label="$t('Label.Email')">
             <template #default="scope">
               {{ scope.row.email || '--' }}
             </template>
@@ -243,7 +243,7 @@
               <span v-else>{{ scope.row.note || '--' }}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="" align="center" :label="$i18n.t('Label.Action')">
+          <el-table-column prop="" align="center" :label="$t('Label.Action')">
             <template #default="scope">
               <el-dropdown trigger="click" @command="handleCommand">
                 <span class="el-dropdown-link crm-cursor">
@@ -357,13 +357,16 @@
   import Service2 from '@/service/apply'
   import DetailedInfoCid from '@/views/components/DetailedInfoCid/index.vue'
   import VirtualCard from '@/views/components/VirtualCard/index.vue'
-  import ViewCardSingle from '@/views/global/ViewCardSingle/index.vue'
+  import ViewCardSingle from '@/views/components/ViewCardSingle/index.vue'
   import { exportExcel } from '@/utils/export.js'
+  import { useI18n } from 'vue-i18n'
   // 混入
   const Session = inject('session')
+  const pigeon = inject('pigeon')
   const { Code } = Config
   const router = useRouter()
 
+  const { t } = useI18n()
   // 响应式数据
   const reasons = ref({})
   const pictLoading = ref(false)
@@ -435,7 +438,7 @@
       })
       dInfo.value = res.data
     } catch (error) {
-      ElMessage.error('搜索失败')
+      pigeon.MessageError(t('Msg.SearchFail'))
     }
   }
 
@@ -457,7 +460,7 @@
         searchRealAll(cId)
       }
     } else {
-      ElMessage.error(res.msg)
+      pigeon.MessageError(res.msg)
     }
   }
 
@@ -474,7 +477,7 @@
       formInfo.value.realList = res.data
       dialogInfoCid.value = true
     } else {
-      ElMessage.error(res.msg)
+      pigeon.MessageError(res.msg)
     }
   }
 
@@ -521,7 +524,7 @@
         if (!(command.row.status == 'success' || command.row.status == 'fail')) {
           updateCardTypes(command.row)
         } else {
-          ElMessage.success('操作成功')
+          pigeon.MessageOK(t('Msg.Success9'))
         }
         break
       case 3:
@@ -544,7 +547,7 @@
         reasons.value = res.data
       }
     } else {
-      ElMessage.error(res.msg)
+      pigeon.MessageError(res.msg)
     }
   }
 
@@ -560,18 +563,18 @@
       id: row.id,
     })
     if (res.code == Code.StatusOK) {
-      ElMessage.success('搜索成功')
+      pigeon.MessageOK(t('Msg.SearchSuccess'))
       searchFunc()
     } else {
-      ElMessage.error(res.msg)
+      pigeon.MessageError(res.msg)
     }
   }
 
   // 列表
   const searchFunc = async () => {
-    pictLoading.value = true
+    // pictLoading.value = true
     if (!display.value['R-CardOrder-Search']?.show) {
-      ElMessage.warning('无显示权限')
+      pigeon.MessageWarning(t('Msg.NotDisplay'))
       pictLoading.value = false
       return
     }
@@ -592,12 +595,12 @@
         } else {
           pagerInfo.rowTotal = 0
         }
-        ElMessage.success('搜索成功')
+        pigeon.MessageOK(t('Msg.SearchSuccess'))
       } else {
-        ElMessage.error(res.msg)
+        pigeon.MessageError(res.msg)
       }
     } catch (error) {
-      ElMessage.error('搜索失败')
+      // pigeon.MessageError('搜索失败')
     } finally {
       pictLoading.value = false
     }

+ 84 - 0
src/views/components/ConsumerShareLink/index.scss

@@ -0,0 +1,84 @@
+#ib_index {
+  // 基础变量
+  $border-color: #dcdfe6;
+  $text-color: #303133;
+  $primary-color: #409eff;
+  $spacing-unit: 10px;
+
+  // 通用样式
+  .chartSetting {
+    &.active {
+      right: 0;
+    }
+  }
+
+  // 二维码相关样式
+  .qrCode {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+  }
+
+  // 对话框样式
+  .dialogLink {
+    .el-dialog__header {
+      font-weight: bold;
+      border-bottom: 1px solid $border-color;
+
+      .el-dialog__title {
+        font-size: 16px;
+      }
+    }
+
+    .content {
+      padding: 0 50px 20px;
+      border-bottom: 1px solid $border-color;
+
+      .el-select {
+        margin-bottom: $spacing-unit;
+      }
+
+      .link {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        border-top: 1px solid $border-color;
+        padding-top: $spacing-unit;
+        margin-top: $spacing-unit;
+
+        .el-input {
+          flex: 1;
+          margin: $spacing-unit 0;
+        }
+      }
+
+      .label {
+        margin: 8px;
+      }
+      .forms {
+        margin: 20px 8px;
+      }
+
+      .btn {
+        display: flex;
+        justify-content: center;
+
+        span {
+          display: inline-block;
+          margin: $spacing-unit 15px;
+          padding: 6px 15px;
+          background-color: rgb(84, 129, 214);
+          color: #fff;
+          border-radius: 2px;
+          cursor: pointer;
+          transition: all 0.3s ease;
+
+          &:hover {
+            opacity: 0.8;
+          }
+        }
+      }
+    }
+  }
+}

+ 438 - 0
src/views/components/ConsumerShareLink/index.vue

@@ -0,0 +1,438 @@
+<template>
+  <div class="views" id="ib_index">
+    <el-dialog
+      v-model:visible="dialogLink"
+      center
+      :modal-append-to-body="false"
+      :title="$t('Ib.Index.CreateLink')"
+      custom-class="dialog_header_w dialogLink"
+    >
+      <div class="dia-content">
+        <div class="content" style="font-size: 14px; text-align: left">
+          <template v-if="type == 1">
+            <div class="label forms">{{ $t('Label.Name') }} :{{ form.name }}</div>
+            <div class="label forms">{{ $t('Label.UserNames') }} :{{ form.username }}</div>
+            <div class="label forms">{{ $t('Label.Email') }} :{{ form.email }}</div>
+          </template>
+          <template v-if="type == 2">
+            <div class="label forms">
+              {{ $t('Apply_info.UserInfo.CID') }} :{{ form.cId || '--' }}
+            </div>
+            <div class="label forms">
+              {{ $t('Label.UserNames') }} :<span v-if="form.firstName">{{
+                form.firstName + ' '
+              }}</span>
+              <span v-if="form.middle">{{ form.middle + ' ' }}</span>
+              <span v-if="form.lastName">{{ form.lastName }}</span>
+              <span v-if="!form.firstName && !form.lastName && !form.middle">{{ '--' }}</span>
+            </div>
+            <div class="label forms">{{ $t('Label.Email') }} :{{ form.email }}</div>
+          </template>
+
+          <template>
+            <div class="label">{{ $t('Ib.Index.Spread5') }} :</div>
+            <el-select
+              v-model="excludeShowLoginTypes"
+              multiple
+              size="mini"
+              :placeholder="$t('Placeholder.Choose')"
+              style="width: 100%"
+            >
+              <el-option
+                v-for="(item, index) in excludeList"
+                :label="item.label"
+                :value="item.value"
+                :key="index"
+              ></el-option>
+            </el-select>
+            <div class="label">{{ $t('Ib.Index.Spread4') }} :</div>
+            <el-select
+              v-model="selectedSpreadId"
+              size="mini"
+              :placeholder="$t('Placeholder.Choose')"
+              style="width: 100%"
+            >
+              <el-option
+                v-for="(item, index) in spreadList"
+                :label="
+                  $t('Ib.Index.Commission') +
+                  ':' +
+                  item.comPoint +
+                  '-' +
+                  $t('Ib.Index.Hide') +
+                  ':' +
+                  item.hide
+                "
+                :value="item.id"
+                :key="index"
+              ></el-option>
+            </el-select>
+            <div class="label">{{ $t('Ib.Index.IbInvalid') }}</div>
+            <el-select
+              v-model="ibInvalid"
+              size="mini"
+              :placeholder="$t('Placeholder.Choose')"
+              style="width: 100%"
+            >
+              <el-option :label="$t('ibTemplate.Allow')" value="B0"></el-option>
+              <el-option :label="$t('ibTemplate.NotAllow')" value="B1"></el-option>
+            </el-select>
+            <div>
+              <span style="line-height: 1.5">{{ $t('ApplicationDialog.item1') }}</span>
+            </div>
+            <div>
+              <span style="line-height: 1.5">{{ $t('ApplicationDialog.item2') }}</span>
+              <template v-if="type == 1">
+                <a
+                  :href="`pdf/pdf6/all/Account Type Allocation Table-${lang}.pdf`"
+                  target="_blank"
+                  >{{ $t('ApplicationDialog.item3') }}</a
+                >
+              </template>
+              <template v-else>
+                <a
+                  :href="`pdf/pdf6/all/Account Type Allocation Table-${lang}.pdf`"
+                  target="_blank"
+                  v-if="country == 'NG' || country == 'TH' || country == 'LA' || isAfterJuly7()"
+                  >{{ $t('ApplicationDialog.item3') }}</a
+                >
+                <a
+                  :href="`pdf/pdf6/no/Account Type Allocation Table-${lang}.pdf`"
+                  target="_blank"
+                  v-else
+                  >{{ $t('ApplicationDialog.item3') }}</a
+                >
+              </template>
+            </div>
+            <div class="btn">
+              <span class="crm-cursor" @click="CreateLink">{{ $t('Ib.Index.CreateLink') }}</span>
+            </div>
+            <div class="link qrCode" v-if="link">
+              <QrCode ref="qrCode" :text="link" :width="200" :height="200"></QrCode>
+              <div class="btn">
+                <span class="crm-cursor" style="height: 16px" @click="downloadQrCode">{{
+                  $t('ibTemplate.item9')
+                }}</span>
+              </div>
+            </div>
+            <div class="link">
+              <el-input
+                readonly
+                size="mini"
+                v-model.trim="link"
+                placeholder=""
+                id="custom_link"
+              ></el-input>
+              <div class="btn">
+                <span class="crm-cursor" @click="CopyShareLink('custom_link')">{{
+                  $t('Ib.Index.Copy')
+                }}</span>
+              </div>
+            </div>
+
+            <div class="link" style="align-items: center">
+              <div style="margin-right: 10px">{{ $t('ibTemplate.item2') }}</div>
+              <el-input
+                readonly
+                size="mini"
+                v-model.trim="getInfoId"
+                placeholder=""
+                id="custom_link_tj"
+              ></el-input>
+              <div class="btn">
+                <span class="crm-cursor" @click="CopyShareLink('custom_link_tj')">{{
+                  $t('Ib.Index.Copy')
+                }}</span>
+              </div>
+            </div>
+          </template>
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script lang="ts" setup>
+  import QrCode from '@/components/QRCode/index.vue'
+  import Service from '@/service/enter'
+  import Config from '@/config/index'
+  import { ref, computed, watch, nextTick, inject } from 'vue'
+  import { useI18n } from 'vue-i18n'
+
+  const { t } = useI18n()
+  const pigeon = inject('pigeon')
+  const Session = inject('session')
+  const { Code, Host80 } = Config
+
+  // 响应式数据
+  const dialogLink = ref(false)
+  const linkActivity = ref('')
+  const hide = ref(0)
+  const country = ref('')
+  const getInfoId = ref('')
+  const commission = ref(0)
+  const excludeList = ref([])
+  const spreadList = ref([])
+  const excludeShowLoginTypes = ref([])
+  const selectedSpreadId = ref('')
+  const loginTypes = ref('')
+  const ibInvalid = ref('B0')
+  const link = ref('')
+  const form = ref({})
+  const type = ref(0)
+  const qrCode = ref(null)
+
+  // 计算属性
+  const lang = computed(() => Session.Get('lang'))
+  const user = computed(() => JSON.parse(Session.Get('user', true)))
+
+  // 方法
+  const isAfterJuly7 = () => {
+    const currentDate = new Date()
+    const july7 = new Date(currentDate.getFullYear(), 6, 7)
+    return currentDate >= july7
+  }
+
+  const LinkActivity1 = async ({ form: formData, type: typeData }) => {
+    console.log(typeData)
+    form.value = formData
+    type.value = typeData
+    switch (typeData) {
+      case 0:
+        getInfoId.value = JSON.parse(Session.Get('user', true)).id
+        break
+      case 1:
+        getInfoId.value = formData.id
+        break
+      case 2:
+        getInfoId.value = formData.ibId
+        break
+    }
+    country.value = typeData == 0 ? JSON.parse(Session.Get('user', true)).country : formData.country
+    switch (typeData) {
+      case 1:
+        excludeList.value = [
+          { label: t('AccountType.SeniorAccount'), value: '2' },
+          { label: t('AccountType.StandardAccount'), value: '7' },
+          { label: t('AccountType.CentAccount'), value: '8' },
+        ]
+        break
+      default:
+        if (
+          country.value == 'NG' ||
+          country.value == 'TH' ||
+          country.value == 'LA' ||
+          isAfterJuly7()
+        ) {
+          excludeList.value = [
+            { label: t('AccountType.SeniorAccount'), value: '2' },
+            { label: t('AccountType.StandardAccount'), value: '7' },
+            { label: t('AccountType.CentAccount'), value: '8' },
+          ]
+        } else {
+          excludeList.value = [
+            { label: t('AccountType.SeniorAccount'), value: '2' },
+            { label: t('AccountType.StandardAccount'), value: '7' },
+          ]
+        }
+        break
+    }
+
+    excludeList.value = excludeList.value.filter(
+      (item) => !user.value.excludeShowLoginTypes.includes(item.value)
+    )
+    await loginTypeList()
+    excludeShowLoginTypes.value = []
+    selectedSpreadId.value = ''
+
+    commission.value = 0
+    hide.value = 0
+    link.value = ''
+    dialogLink.value = true
+  }
+
+  const downloadQrCode = () => {
+    qrCode.value.download()
+  }
+
+  const CopyShareLink = (linkId) => {
+    let linkEle = document.getElementById(linkId)
+    linkEle.select()
+    document.execCommand('Copy')
+  }
+
+  const CreateLink = async () => {
+    const linkValue = await getLink1()
+    if (!linkValue) return
+    link.value = `${Host80}/#/signup/${getInfoId.value}/${linkValue}/${ibInvalid.value}?oc=${form.value.serial}`
+  }
+
+  const getValidAccountTypes = (selectedExcludeValues, selectedSpreadId) => {
+    const spread = spreadList.value.find((item) => item.id === selectedSpreadId)
+    let data = {
+      hide: '',
+      commission: '',
+      excludeShowLoginTypes: [],
+    }
+    if (!spread) return data
+
+    const validValues = selectedExcludeValues.filter((value) => spread.loginTypes.includes(value))
+    const invalidValues = selectedExcludeValues.filter(
+      (value) => !spread.loginTypes.includes(value)
+    )
+
+    const invalidLabels = excludeList.value
+      .filter((item) => invalidValues.includes(item.value))
+      .map((item) => item.label)
+
+    const excludeShowLoginTypes = excludeList.value
+      .filter((item) => !validValues.includes(item.value))
+      .map((item) => item.value)
+
+    loginTypes.value = invalidLabels.join('、')
+
+    return {
+      hide: spread.hide,
+      commission: spread.comPoint,
+      excludeShowLoginTypes,
+      invalidLabels,
+      invalidValues,
+    }
+  }
+
+  const getLink1 = async () => {
+    if (excludeShowLoginTypes.value.length === 0) {
+      pigeon.MessageWarning(t('Ib.Index.Spread5'))
+      link.value = ''
+      return
+    }
+    if (!selectedSpreadId.value) {
+      pigeon.MessageWarning(t('Ib.Index.Spread4'))
+      link.value = ''
+      return
+    }
+
+    const validList = getValidAccountTypes(excludeShowLoginTypes.value, selectedSpreadId.value)
+
+    if (validList.excludeShowLoginTypes.length === excludeList.value.length) {
+      pigeon.MessageError(t('Ib.Index.Spread3'))
+      link.value = ''
+      return
+    }
+
+    if (validList.invalidLabels.length > 0) {
+      return new Promise((resolve) => {
+        pigeon.MessageConfirm(
+          `${t('Ib.Index.Spread1')}${loginTypes.value}${t('')}`,
+          t('Msg.SystemPrompt'),
+          t('Btn.Confirm'),
+          t('Btn.Cancel'),
+          async () => {
+            const res = await Service.customLink(validList)
+            if (res.code === Code.StatusOK) {
+              pigeon.MessageOK(res.msg)
+              resolve(res.data)
+            } else {
+              pigeon.MessageError(res.msg)
+              resolve('')
+            }
+          },
+          () => resolve('')
+        )
+      })
+    } else {
+      const res = await Service.customLink(validList)
+      if (res.code === Code.StatusOK) {
+        pigeon.MessageOK(res.msg)
+        return res.data
+      } else {
+        pigeon.MessageError(res.msg)
+        return ''
+      }
+    }
+  }
+
+  const loginTypeList = async () => {
+    let res = await Service.loginTypeList({
+      page: {
+        current: 1,
+        row: 100,
+      },
+    })
+    if (res.code == Code.StatusOK) {
+      spreadList.value = res.data
+    } else {
+      pigeon.MessageError(res.msg)
+    }
+  }
+
+  // 生命周期
+  nextTick(() => {})
+
+  // 监听器
+  watch(commission, () => {
+    link.value = ''
+  })
+
+  watch(ibInvalid, () => {
+    link.value = ''
+  })
+
+  // 暴露方法给父组件
+  defineExpose({
+    LinkActivity1,
+  })
+</script>
+
+<style lang="scss" scoped>
+  @import 'index.scss';
+</style>
+
+<style lang="scss">
+  #ib_index {
+    // 对话框全局样式
+    .dialog_header_w.dialogLink {
+      .el-dialog__header {
+        font-weight: bold;
+        border-bottom: 1px solid #dcdfe6;
+
+        .el-dialog__title {
+          font-size: 16px;
+        }
+      }
+    }
+
+    // 图表设置样式
+    .chartSetting {
+      .el-input__inner {
+        height: 30px;
+        line-height: 30px;
+        background-color: transparent;
+      }
+
+      .el-form-item {
+        margin-bottom: 15px;
+
+        &__label {
+          padding-bottom: 0;
+        }
+      }
+    }
+
+    // 图表框样式
+    .chart-box {
+      .el-input__inner {
+        border: none;
+        border-bottom: 1px solid #dcdfe6;
+        border-radius: 0;
+      }
+    }
+
+    // 链接容器样式
+    .con-link {
+      .el-select {
+        width: 100%;
+      }
+    }
+  }
+</style>

+ 2 - 2
src/views/components/DetailedInfoCid/index.vue

@@ -685,7 +685,7 @@
         </div>
       </template>
     </el-dialog>
-    <ConsumerShareLink ref="consumerShareLink" />
+    <ConsumerShareLink ref="consumerShareLinkRef" />
   </div>
 </template>
 
@@ -693,7 +693,7 @@
   import { ref, reactive, computed, watch, nextTick, inject } from 'vue'
   import Service from '@/service/customer'
   import Config from '@/config'
-  import ConsumerShareLink from '@/views/global/ConsumerShareLink.vue'
+  import ConsumerShareLink from '@/views/components/ConsumerShareLink/index.vue'
   import { useI18n } from 'vue-i18n'
 
   const Session = inject('session')

+ 2 - 3
src/views/components/VirtualCard/index.vue

@@ -656,9 +656,8 @@
   </div>
 </template>
 
-<script setup>
-  import { ref, reactive, computed, watch, onMounted } from 'vue'
-  import { ElMessageBox } from 'element-plus'
+<script lang="ts" setup>
+  import { ref, reactive, computed, watch, onMounted, inject } from 'vue'
   import Config from '@/config'
   import Service from '@/service/ucard'
   import Service2 from '@/service/apply'