Explorar el Código

✨ feat: 新增SB新建广告活动-广告组,广告格式

WanGxC hace 1 año
padre
commit
3f6b8edbea

+ 25 - 0
src/views/adManage/sb/campaigns/CreateCampaigns/api/index.ts

@@ -0,0 +1,25 @@
+import { request } from '/@/utils/service'
+
+
+export function getAdMixSelect() {
+  return request({
+      url: '/api/ad_manage/portfolios/select_list',
+      method: 'GET',
+  })
+}
+
+export function postCampaignsData(filteredRequestData) {
+  return request({
+      url: '/api/ad_manage/spcampaigns/create/',
+      method: 'post',
+      data: filteredRequestData,
+  })
+}
+
+export function postGroupData(filteredRequestData) {
+  return request({
+      url: '/api/ad_manage/sbgroups/create/',
+      method: 'post',
+      data: filteredRequestData,
+  })
+}

+ 56 - 35
src/views/adManage/sb/campaigns/CreateCampaigns/component/AdCampaigns.vue → src/views/adManage/sb/campaigns/CreateCampaigns/component/AdCampaign.vue

@@ -20,8 +20,7 @@
           </el-form-item>
           <el-form-item label="广告组合" prop="adMix" style="width: 48%">
             <el-select v-model="campaignRuleForm.adMix" placeholder="请选择" style="width: 100%">
-              <el-option label="Zone one" value="shanghai" />
-              <el-option label="Zone two" value="beijing" />
+              <el-option v-for="item in adMixOptions" :key="item.value" :label="item.label" :value="item.value" />
             </el-select>
           </el-form-item>
         </div>
@@ -86,17 +85,16 @@
 </template>
 
 <script lang="ts" setup>
-import { reactive, ref } from 'vue'
+import { onMounted, reactive, ref, watch, defineEmits } from 'vue'
 import type { FormInstance, FormRules } from 'element-plus'
 import { ElMessage } from 'element-plus'
 import { storeToRefs } from 'pinia'
 import { useRouter, useRoute } from 'vue-router'
-import { request } from '/@/utils/service'
 import { useShopInfo } from '/@/stores/shopInfo'
+import { postCampaignsData, getAdMixSelect } from '../api/index'
 
 const shopInfo = useShopInfo()
 const { profile } = storeToRefs(shopInfo)
-console.log('🚀 ~ profile-->>', profile)
 
 const formSize = ref('default')
 const campaignRuleFormRef = ref<FormInstance>()
@@ -128,7 +126,6 @@ const campaignRules = reactive<FormRules<campaignRuleForm>>({
     { pattern: /^(?:[1-9]\d{0,5}|1000000)(?:\.\d{1,2})?$/, message: '预算必须是1到1000000之间的数字,小数点后最多两位', trigger: 'blur' },
   ],
 })
-
 const frequencyOptions = [
   {
     value: 'daily',
@@ -140,14 +137,12 @@ const frequencyOptions = [
     disabled: true,
   },
 ]
-
 const brandOptions = [
   {
     value: 'zosi',
     label: 'ZOSI',
   },
 ]
-
 const submitCampaignForm = async (formEl: FormInstance | undefined) => {
   if (!formEl) return
   await formEl.validate((valid, fields) => {
@@ -160,34 +155,47 @@ const submitCampaignForm = async (formEl: FormInstance | undefined) => {
   })
 }
 
+const adMixOptions = ref([])
+async function buildAdMix() {
+  try {
+    const response = await getAdMixSelect()
+    console.log('🚀 ~ buildAdMix ~ resp-->>', response)
+    adMixOptions.value = response.data.map((option) => {
+      return {
+        value: option.portfolioId,
+        label: option.name,
+      }
+    })
+  } catch (error) {
+    console.error('请求失败:', error)
+  }
+}
+
 const campaignLoading = ref(false)
+const respCampaignId = ref('')
+const respCampaignName = ref('')
 async function createCampaigns() {
   campaignLoading.value = true
+  // 构建请求体
+  const campaignData = {
+    profile_id: profile.value.profile_id,
+    budget: campaignRuleForm.budget,
+    budgetType: campaignRuleForm.frequency,
+    name: campaignRuleForm.campaignName,
+    bidOptimization: campaignRuleForm.isBid,
+    bidOptimizationStrategy: '',
+    startDate: campaignRuleForm.startDate,
+    endDate: campaignRuleForm.endDate,
+    goal: 'PAGE_VISIT',
+    state: 'PAUSED',
+  }
+  const filteredRequestData = Object.fromEntries(Object.entries(campaignData).filter(([_, v]) => v != null))
   try {
-    const requestData = {
-      profile_id: profile.value.profile_id,
-      budget: campaignRuleForm.budget,
-      budgetType: campaignRuleForm.frequency,
-      name: campaignRuleForm.campaignName,
-      bidOptimization: campaignRuleForm.isBid,
-      bidOptimizationStrategy: '',
-      startDate: campaignRuleForm.startDate,
-      endDate: campaignRuleForm.endDate,
-      goal: 'PAGE_VISIT',
-      state: 'PAUSED',
-    }
-
-    const filteredRequestData = Object.fromEntries(Object.entries(requestData).filter(([_, v]) => v != null))
-
-    const response = await request({
-      url: '/api/ad_manage/spcampaigns/create/',
-      method: 'POST',
-      data: filteredRequestData,
-    })
+    const response = await postCampaignsData(filteredRequestData)
+    respCampaignId.value = response.data.campaignId
+    respCampaignName.value = response.data.campaignName
     console.log('🚀 ~ createCampaigns ~ response-->>', response)
-    campaignLoading.value = false
-    if (response.code === 2000) {
-      // adGroupSave.value = false
+    if (response.data.campaignId) {
       ElMessage({
         message: '广告活动创建成功',
         type: 'success',
@@ -197,15 +205,28 @@ async function createCampaigns() {
     }
   } catch (error) {
     console.error('请求失败:', error)
+  } finally {
+    campaignLoading.value = false
   }
 }
+
+const emit = defineEmits(['update-campaign'])
+
+watch([respCampaignId, respCampaignName], () => {
+  if (respCampaignId.value && respCampaignName.value) {
+    emit('update-campaign', {
+      id: respCampaignId.value,
+      name: respCampaignName.value,
+    })
+  }
+})
+
+onMounted(() => {
+  buildAdMix()
+})
 </script>
 
 <style scoped>
-::v-deep(.el-form--default.el-form--label-top .el-form-item .el-form-item__label) {
-  font-weight: 500;
-  color: #505968;
-}
 .flex-between {
   display: flex;
   justify-content: space-between;

+ 171 - 0
src/views/adManage/sb/campaigns/CreateCampaigns/component/AdFormat.vue

@@ -0,0 +1,171 @@
+<template>
+  <div class="container">
+    <el-card body-style="padding: 20px 80px 20px 80px;">
+      <div style="font-weight: 700; padding-bottom: 18px">
+        <span style="color: #306cd7; font-size: 26px">|</span>
+        <span style="font-size: 18px; padding-left: 5px">广告格式</span>
+      </div>
+      <div class="ad-format-radios">
+        <el-radio-group v-model="adFormatRadio" style="display: flex; justify-content: space-between">
+          <el-radio class="ad-format-radio" label="productSet" border>
+            <div style="text-align: center">商品集</div>
+            <div style="background-color: #1e2128; width: 200px; height: 200px; margin: 0 auto"></div>
+            <div style="padding: 5px 0 10px 0">使用图片将流量引导至商品详情页面, 以推广多件商品</div>
+          </el-radio>
+          <el-radio class="ad-format-radio" label="focus" border>
+            <div style="text-align: center">品牌旗舰店焦点</div>
+            <div style="background-color: #4c649d; width: 200px; height: 200px; margin: 0 auto"></div>
+            <div style="padding: 5px 0 10px 0">将流量引流到品牌旗舰店, 包括子页面</div>
+          </el-radio>
+          <el-radio class="ad-format-radio" label="video" border>
+            <div style="text-align: center">视频</div>
+            <div style="background-color: #43abc3; width: 200px; height: 200px; margin: 0 auto"></div>
+            <div style="padding: 5px 0 10px 0">使用视频宣传您的品牌或产品, 将流量吸引至您的品牌旗舰店或商品详情页</div>
+          </el-radio>
+        </el-radio-group>
+      </div>
+      <div class="customize-font" v-if="adFormatRadio === 'productSet'">需要帮助创建图片或品牌旗舰店?</div>
+      <div class="customize-font" v-if="adFormatRadio === 'focus'">在创建或编辑品牌旗舰店时需要帮助?</div>
+      <div class="customize-font" v-if="adFormatRadio === 'video'">在创建或编辑视频时需要帮助?</div>
+
+      <div style="display: flex; align-items: center; margin: 20px 0 5px 0">
+        <div style="color: #616266; font-weight: 450">着陆页</div>
+        <el-tooltip content="顾客在与您的广告互动后将被引导至着陆页" placement="top">
+          <el-icon color="#616266"><InfoFilled /></el-icon>
+        </el-tooltip>
+      </div>
+
+      <div class="land-Page" v-if="adFormatRadio === 'productSet' || adFormatRadio === 'video'">
+        <el-radio-group v-model="arrivalsRadio" style="display: flex; justify-content: space-between">
+          <el-radio label="flagshipStore" border style="height: auto; width: 100%; flex: 2; align-items: flex-start; padding: 15px 10px 0 10px">
+            <div>亚马逊品牌旗舰店(包括子页面)</div>
+            <div>
+              <el-form
+                ref="flagshipStoreRuleFormRef"
+                :model="flagshipStoreRuleForm"
+                :rules="flagshipStoreRules"
+                label-position="top"
+                label-width="120px"
+                class="demo-ruleForm"
+                size="default"
+                status-icon>
+                <div style="display: flex; margin-top: 10px">
+                  <el-form-item label="选择一个店铺" prop="shop" style="width: 48%; margin-right: 10px">
+                    <el-select style="width: 100%">
+                      <el-option v-for="item in shopOptions" :key="item.value" :label="item.label" :value="item.value" />
+                    </el-select>
+                  </el-form-item>
+                  <el-form-item label="选择一个页面" prop="page" style="width: 48%">
+                    <el-select style="width: 100%">
+                      <el-option v-for="item in pageOptions" :key="item.value" :label="item.label" :value="item.value" />
+                    </el-select>
+                  </el-form-item>
+                </div>
+              </el-form>
+            </div>
+          </el-radio>
+          <el-radio class="land-page-radio" label="newArrivals" border v-if="adFormatRadio === 'productSet'">
+            <div>新着陆页</div>
+            <div>选择要推广的商品, 我们将为您创建一个落地页</div>
+          </el-radio>
+          <el-radio class="land-page-radio" label="productDetailsPage" border v-if="adFormatRadio === 'video'">
+            <div>商品详情页</div>
+          </el-radio>
+        </el-radio-group>
+      </div>
+
+      <div>
+        <div style="font-weight: 700; padding: 20px 0 10px 0" v-if="(adFormatRadio === 'productSet' && arrivalsRadio === 'newArrivals') || (adFormatRadio === 'video' && arrivalsRadio === 'productDetailsPage')">
+          <span style="color: #306cd7; font-size: 26px">|</span>
+          <span style="font-size: 18px; padding-left: 5px">商品</span>
+        </div>
+        <ProductSetCommodity v-if="adFormatRadio === 'productSet' && arrivalsRadio === 'newArrivals'"></ProductSetCommodity>
+        <VideoCommodity v-if="adFormatRadio === 'video' && arrivalsRadio === 'productDetailsPage'"></VideoCommodity>
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive } from 'vue'
+import type { FormInstance, FormRules } from 'element-plus'
+import ProductSetCommodity from '../component/ProductSetCommodity.vue'
+import VideoCommodity from '../component/VideoCommodity.vue'
+
+const adFormatRadio = ref('productSet')
+const arrivalsRadio = ref('flagshipStore')
+const flagshipStoreFormRef = ref<FormInstance>()
+interface flagshipStoreRuleForm {
+  shop: string
+  page: string
+}
+const flagshipStoreRuleForm = reactive<flagshipStoreRuleForm>({
+  shop: '',
+  page: '',
+})
+const flagshipStoreRules = reactive<FormRules<flagshipStoreRuleForm>>({
+  shop: {
+    required: true,
+  },
+  page: {
+    required: true,
+  },
+})
+
+const shopOptions = [
+  {
+    value: '1',
+    label: '1',
+  },
+  {
+    value: '2',
+    label: '2',
+  },
+]
+const pageOptions = [
+  {
+    value: '1',
+    label: '1',
+  },
+  {
+    value: '2',
+    label: '2',
+  },
+]
+</script>
+
+<style scoped>
+.customize-font {
+  color: #1e2128;
+  font-weight: 600;
+  margin-top: 10px;
+}
+.ad-format-radio {
+  height: auto;
+  width: 100%;
+  flex: 1;
+  flex-direction: column-reverse;
+  align-items: center;
+}
+.land-page-radio {
+  height: 132px;
+  flex: 1;
+  align-items: flex-start;
+  padding: 15px 10px 0 10px;
+}
+.container {
+  margin-top: 10px;
+}
+::v-deep(.ad-format-radios .el-radio-group .el-radio__inner) {
+  /* 广告格式单选按钮 */
+  margin-bottom: 3px;
+}
+
+::v-deep(.land-Page .el-radio-group .el-radio__inner) {
+  /* 着陆页单选按钮 */
+  margin-top: 3px;
+}
+::v-deep(.land-Page .el-radio__label) {
+  width: 100%;
+}
+</style>

+ 114 - 0
src/views/adManage/sb/campaigns/CreateCampaigns/component/AdGroup.vue

@@ -0,0 +1,114 @@
+<template>
+  <div class="container">
+    <el-card body-style="padding: 20px 80px 0 80px;" v-loading="groupLoading">
+      <div style="font-weight: 700; padding-bottom: 18px">
+        <span style="color: #306cd7; font-size: 26px">|</span>
+        <span style="font-size: 18px; padding-left: 5px">广告组</span>
+      </div>
+      <el-form
+        ref="groupRuleFormRef"
+        :model="groupRuleForm"
+        :rules="groupRules"
+        label-position="left"
+        label-width="120px"
+        class="demo-ruleForm"
+        :size="formSize"
+        status-icon>
+        <el-form-item label="广告组名称" prop="groupName" style="width: 100%">
+          <el-input v-model="groupRuleForm.groupName" style="width: 40%" />
+          <el-button type="primary" plain :disabled="!respAdGroupId" @click="submitGroupForm(groupRuleFormRef)" style="margin-left: 35px">保存</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, ref, inject, watch, Ref } from 'vue'
+import type { FormInstance, FormRules } from 'element-plus'
+import { ElMessage } from 'element-plus'
+import { storeToRefs } from 'pinia'
+import { useShopInfo } from '/@/stores/shopInfo'
+import { postGroupData } from '../api/index'
+
+const shopInfo = useShopInfo()
+const { profile } = storeToRefs(shopInfo)
+const respCampaignId = inject<Ref>('respCampaignId')
+const respCampaignName = inject<Ref>('respCampaignName')
+
+const groupLoading = ref(false)
+
+const formSize = ref('default')
+const groupRuleFormRef = ref<FormInstance>()
+interface groupRuleForm {
+  groupName: string
+}
+const groupRuleForm = reactive<groupRuleForm>({
+  groupName: 'AiTestGroupW04',
+})
+const groupRules = reactive<FormRules<groupRuleForm>>({
+  groupName: [{ required: true, message: '请输入广告活动', trigger: 'blur' }],
+})
+
+const submitGroupForm = async (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  await formEl.validate((valid, fields) => {
+    if (valid) {
+      console.log('submit!')
+      createGroups()
+    } else {
+      console.log('error submit!', fields)
+    }
+  })
+}
+
+const respAdGroupId = ref('')
+async function createGroups() {
+  groupLoading.value = true
+  const groupData = {
+    profile_id: profile.value.profile_id,
+    campaignId: respCampaignId.value,
+    name: respCampaignName.value,
+  }
+
+  const filteredRequestData = Object.fromEntries(Object.entries(groupData).filter(([_, v]) => v != null))
+  try {
+    const response = await postGroupData(filteredRequestData)
+    respAdGroupId.value = response.data.adGroupId
+    console.log('🚀 ~ createGroups ~ response-->>', response)
+    // if () {
+
+    // }
+    ElMessage({
+      message: '广告组创建成功',
+      type: 'success',
+    })
+  } catch (error) {
+    ElMessage.error('广告组创建失败!')
+    console.error('请求失败:', error)
+  } finally {
+    groupLoading.value = false
+  }
+}
+
+const emit = defineEmits(['update-groupId'])
+
+watch(respAdGroupId, () => {
+  if (respAdGroupId.value) {
+    emit('update-groupId', {
+      id: respAdGroupId.value,
+    })
+  }
+})
+
+</script>
+
+<style lang="scss" scoped>
+.container {
+  margin-top: 10px;
+}
+::v-deep(.el-form-item__label) {
+  font-weight: 500;
+  color: #505968;
+}
+</style>

+ 444 - 0
src/views/adManage/sb/campaigns/CreateCampaigns/component/ProductSetCommodity.vue

@@ -0,0 +1,444 @@
+<template>
+  <div prop="commodity" style="width: 100%" v-loading="productLoading">
+    <div style="width: 100%; height: 620px; display: flex; border: 1px solid #e5e7ec; border-radius: 6px">
+      <div style="width: 50%; border-right: 1px solid #e5e7ec">
+        <el-tabs v-model="productTabs" class="demo-tabs">
+          <el-tab-pane label="搜索" name="first">
+            <div style="margin-bottom: 10px">
+              <el-input v-model="searchInp" placeholder="Please input" class="input-with-select" @change="inpChange" clearable>
+                <template #prepend>
+                  <el-select v-model="leftSelect" style="width: 100px" @change="selChange">
+                    <el-option label="名称" value="name" />
+                    <el-option label="ASIN" value="asin" />
+                    <el-option label="SKU" value="sku" />
+                  </el-select>
+                </template>
+                <template #append>
+                  <el-select v-model="rightSelect" style="width: 100px">
+                    <el-option label="最新优先" value="latest" />
+                    <el-option label="最早优先" value="earliest" />
+                    <el-option label="优选广告" value="optimal" />
+                  </el-select>
+                </template>
+              </el-input>
+            </div>
+            <el-table
+              height="490"
+              style="width: 100%"
+              v-loading="loading"
+              :data="productTableData"
+              :header-cell-style="headerCellStyle"
+              @selection-change="handleSelectionChange">
+              <el-table-column type="selection" width="50" />
+              <el-table-column prop="asin" label="商品">
+                <template #default="scope">
+                  <div style="display: flex; align-items: center">
+                    <div style="margin-right: 8px; line-height: normal">
+                      <el-image class="img-box" :src="scope.row.image_link" />
+                    </div>
+                    <div>
+                      <el-tooltip class="box-item" effect="dark" :content="scope.row.title" placement="top">
+                        <div class="single-line">{{ scope.row.title ? scope.row.title : '--' }}</div>
+                      </el-tooltip>
+                      <div class="data-color">
+                        <span style="font-weight: 500; color: rgb(30, 33, 41)">${{ scope.row.price ? scope.row.price : '--' }}</span>
+                        <span style="margin: 0 5px; color: #cacdd4">|</span>
+                        <span style="color: #6d7784">{{ scope.row.quantity }}</span>
+                      </div>
+                      <span>
+                        ASIN: <span class="data-color" style="margin-right: 8px">{{ scope.row.asin ? scope.row.asin : '--' }}</span>
+                      </span>
+                      <span>
+                        SKU: <span class="data-color">{{ scope.row.sku ? scope.row.sku : '--' }}</span>
+                      </span>
+                    </div>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column prop="name" label="Name" width="120" align="right">
+                <template #header>
+                  <el-button type="primary" size="normal" link @click="handleGoodsAdd">添加已选中</el-button>
+                </template>
+                <template #default="scope">
+                  <el-button type="primary" size="small" @click="addSingleGoods(scope)" text>添加</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+            <el-pagination
+              @current-change="handleCurrentChange"
+              @size-change="handleSizeChange"
+              :current-page="currentPage"
+              :page-size="pageSize"
+              :total="totalItems"
+              layout="prev, pager, next" />
+          </el-tab-pane>
+          <el-tab-pane label="输入" name="second">
+            <el-input
+              style="padding: 10px"
+              v-model="productTextarea"
+              :rows="20"
+              type="textarea"
+              placeholder="请输入ASIN,多个ASIN使用逗号、空格或换行符分隔。(未完成)"
+              maxlength="11000" />
+            <div style="display: flex; flex-direction: row-reverse; margin-top: 10px">
+              <el-button v-for="button in buttons" :key="button.text" :type="button.type" link @click="addGods">{{ button.text }}</el-button>
+            </div>
+          </el-tab-pane>
+        </el-tabs>
+      </div>
+      <div style="width: 50%">
+        <el-card class="box-card" shadow="never" style="border: 0">
+          <template #header>
+            <div class="card-header">
+              <span style="font-weight: 550; font-size: 15px; color: #1f2128">已添加: {{ addedTableData.length }}</span>
+              <el-tooltip content="添加最少3件商品。我们建议添加至少5件商品,以降低在商品缺货时出现广告活动暂停的可能性。" placement="top">
+                <el-text type="warning" truncated style="width: 350px;">添加最少3件商品。我们建议添加至少5件商品,以降低在商品缺货时出现广告活动暂停的可能性</el-text>
+              </el-tooltip>
+              <el-button class="button" text bg @click="delAllGoods">全部删除</el-button>
+            </div>
+          </template>
+          <div class="card-body"></div>
+        </el-card>
+        <div style="padding: 0 10px 0 10px; margin-top: -12px">
+          <el-table
+            :data="addedTableData"
+            height="475"
+            style="width: 100%"
+            :header-cell-style="headerCellStyle"
+            @selection-change="handleAddedGoodsChange">
+            <el-table-column type="selection" width="50" />
+            <el-table-column prop="asin" label="ASIN">
+              <template #default="scope">
+                <div style="display: flex; align-items: center">
+                  <div style="margin-right: 8px; line-height: normal">
+                    <el-image class="img-box" :src="scope.row.image_link" />
+                  </div>
+                  <div>
+                    <el-tooltip class="box-item" effect="dark" :content="scope.row.title" placement="top">
+                      <div class="single-line">{{ scope.row.title ? scope.row.title : '--' }}</div>
+                    </el-tooltip>
+                    <div class="data-color">
+                      <span style="font-weight: 500; color: rgb(30, 33, 41)">${{ scope.row.price ? scope.row.price : '--' }}</span>
+                      <span style="margin: 0 5px; color: #cacdd4">|</span>
+                      <span style="color: #6d7784">{{ scope.row.quantity }}</span>
+                    </div>
+                    <span
+                      >ASIN:
+                      <span class="data-color" style="margin-right: 8px">{{ scope.row.asin ? scope.row.asin : '--' }}</span>
+                    </span>
+                    <span
+                      >SKU:
+                      <span class="data-color">{{ scope.row.sku ? scope.row.sku : '--' }}</span>
+                    </span>
+                  </div>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column prop="name" label="Name" width="120" align="right">
+              <template #header>
+                <el-button type="primary" size="normal" link @click="delSelectedGoods">删除已选中</el-button>
+              </template>
+              <template #default="scope">
+                <el-button type="primary" size="small" @click="delSingleGoods(scope)" text>删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+        <div style="display: flex; justify-content: space-around; padding-top: 5px">
+          <el-button type="primary" plain :disabled="productSave" @click="submitProductForm">保存</el-button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import type { TabsPaneContext } from 'element-plus'
+import { ElMessage } from 'element-plus'
+import { storeToRefs } from 'pinia'
+import type { Ref } from 'vue'
+import { inject, onMounted, ref, watch } from 'vue'
+import { useShopInfo } from '/@/stores/shopInfo'
+import { request } from '/@/utils/service'
+
+const shopInfo = useShopInfo()
+const { profile } = storeToRefs(shopInfo)
+const productTextarea = ref('')
+const productLoading = ref(false)
+let addedAdsTableItems = ref([])
+const currentPage = ref() // 当前页
+const pageSize = ref(20) // 每页显示条目数
+const totalItems = ref() // 数据总量
+const productTableData = ref([]) // 左侧表格数据
+const loading = ref(false)
+let addedTableData = ref([])
+let selections = []
+let addedSels = []
+const searchInp = ref('')
+const leftSelect = ref('name')
+let productSave = ref(true)
+const buttons = [{ type: 'primary', text: '添加' }] as const
+const productTabs = ref('first')
+const rightSelect = ref('latest')
+const respCampaignId = inject<Ref>('respCampaignId')
+const respCampaignName = inject<Ref>('respCampaignName')
+const respAdGroupId = inject<Ref>('respAdGroupId')
+
+function setTableData(asin = '', sku = '') {
+  return request({
+    url: '/api/sellers/listings/our/',
+    method: 'GET',
+    params: {
+      page: currentPage.value,
+      limit: pageSize.value,
+      profile_id: profile.value.profile_id,
+      asin,
+      sku,
+    },
+  })
+    .then((resp) => {
+      productTableData.value = resp.data
+      totalItems.value = resp.total
+      currentPage.value = resp.page
+      loading.value = false
+    })
+    .catch((error) => {
+      console.error('Error fetching data:', error)
+      loading.value = false
+    })
+}
+
+function addSingleGoods(scope) {
+  // console.log('scope', scope.row)
+  const isAlreadyAdded = addedTableData.value.some((item) => item.sku === scope.row.sku)
+  if (!isAlreadyAdded) {
+    addedTableData.value.push(scope.row)
+  } else {
+    console.log('Item is already added.')
+  }
+}
+
+function addGods() {
+  const inputData = productTextarea.value
+  const asins = inputData.split(/[\n,]+/)
+
+  asins.forEach((asin) => {
+    if (asin.trim()) {
+      setTableData(asin.trim())
+        .then((response) => {
+          console.log(`Data for ASIN ${asin}:`, response) // 更新这里来正确地访问数据
+        })
+        .catch((error) => {
+          console.error(`Error fetching data for ASIN ${asin}:`, error)
+        })
+    }
+  })
+}
+
+function delSingleGoods(scope) {
+  const index = addedTableData.value.findIndex((item) => item.sku === scope.row.sku)
+  if (index !== -1) {
+    addedTableData.value.splice(index, 1)
+    console.log('Item removed successfully.')
+  } else {
+    console.log('Item not found.')
+  }
+}
+
+function delAllGoods() {
+  addedTableData.value = []
+  // addedTableData.value.splice(0, addedTableData.value.length)
+}
+
+// 删除第二个table中已经选中的项
+function delSelectedGoods() {
+  addedTableData.value = addedTableData.value.filter((item) => !addedSels.includes(item))
+  addedSels = []
+}
+
+function inpChange(e) {
+  const value = e
+  if (leftSelect.value === 'asin') {
+    loading.value = true
+    setTableData(value)
+  } else if (leftSelect.value === 'sku') {
+    loading.value = true
+    setTableData('', value)
+  }
+}
+
+function selChange(e) {
+  console.log('e', e)
+  const value = e
+  if (leftSelect.value === 'asin' && searchInp.value) {
+    loading.value = true
+    setTableData(value)
+  } else if (leftSelect.value === 'sku' && searchInp.value) {
+    loading.value = true
+    setTableData('', value)
+  }
+}
+// 点击表格选项触发事件
+function handleSelectionChange(selection) {
+  selections = selection
+}
+// 获取addedTable中已选中的项
+function handleAddedGoodsChange(selection) {
+  addedSels = selection
+}
+// 添加已选中的项
+function handleGoodsAdd() {
+  // 过滤掉已经存在于addedData.value中的项
+  const newSelections = selections.filter(
+    (sel) => !addedTableData.value.some((added) => added.sku === sel.sku) // 使用sku作为唯一标识
+  )
+  // 如果有新的不重复项,加入到addedData.value中
+  if (newSelections.length > 0) {
+    addedTableData.value.push(...newSelections)
+  }
+}
+// 点击Tab
+const handleGoodsTabs = (tab: TabsPaneContext, event: Event) => {
+  console.log(tab, event)
+}
+
+function isItemInList(item, list) {
+  return list.some((listItem) => listItem.sku === item.sku && listItem.asin === item.asin)
+}
+// 监听商品右侧表格已添加的数据并转化数据格式
+watch(
+  addedTableData,
+  (newValue, oldValue) => {
+    newValue.forEach((item) => {
+      if (!isItemInList(item, addedAdsTableItems.value)) {
+        addedAdsTableItems.value.push({ sku: item.sku, asin: item.asin })
+      }
+    })
+    if (addedTableData.value.length !== 0) {
+      productSave.value = false
+    } else {
+      productSave.value = true
+    }
+  },
+  { deep: true }
+)
+
+async function createAds() {
+  try {
+    const requestData = {
+      profile_id: profile.value.profile_id,
+      campaignId: respCampaignId.value,
+      adGroupId: respAdGroupId.value,
+      asinsku: addedAdsTableItems.value,
+      state: 'PAUSED',
+    }
+    const filteredRequestData = Object.fromEntries(Object.entries(requestData).filter(([_, v]) => v != null))
+    const resp = await request({
+      url: '/api/ad_manage/spads/create/',
+      method: 'POST',
+      data: filteredRequestData,
+    })
+    console.log('🚀 ~ createAds ~ resp-->>', resp)
+    productLoading.value = false
+    if (resp.data.success.length > 0) {
+      productSave.value = false
+      addedTableData.value = []
+      ElMessage({
+        message: '商品创建成功',
+        type: 'success',
+      })
+    } else {
+      ElMessage.error('商品创建失败!')
+    }
+  } catch (error) {
+    console.error('请求失败:', error)
+  }
+}
+
+function submitProductForm() {
+  productLoading.value = true
+  createAds()
+}
+
+// 处理分页器当前页变化
+function handleCurrentChange(newPage) {
+  currentPage.value = newPage
+  loading.value = true
+  setTableData()
+}
+// 处理分页器每页显示条目数变化
+function handleSizeChange(newSize) {
+  pageSize.value = newSize
+  currentPage.value = 1 // 重置到第一页
+}
+
+const headerCellStyle = (args) => {
+  if (args.rowIndex === 0) {
+    return {
+      backgroundColor: 'rgba(245, 245, 245, 0.9)',
+    }
+  }
+}
+onMounted(() => {
+  setTableData()
+})
+</script>
+
+<style lang="scss" scoped>
+::v-deep(.el-form--default.el-form--label-top .el-form-item .el-form-item__label) {
+  font-weight: 500;
+}
+.demo-tabs > .el-tabs__content {
+  padding: 52px;
+  color: #6b778c;
+  font-size: 32px;
+  font-weight: 600;
+}
+/* 广告组商品Tab栏 */
+::v-deep(.el-tabs__nav-scroll) {
+  overflow: hidden;
+  margin-left: 20px;
+}
+::v-deep(.el-table__inner-wrapper::before) {
+  background-color: white;
+}
+// 表格内容边距
+div {
+  & #pane-first,
+  & #pane-second {
+    margin: 10px;
+  }
+}
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+.box-card {
+  width: 100%;
+  margin-right: 10px;
+}
+.single-line {
+  color: rgb(30, 33, 41);
+  overflow: hidden;
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+  -webkit-line-clamp: 1;
+  white-space: pre-wrap;
+  word-break: break-word;
+}
+.data-color {
+  color: rgb(30, 33, 41);
+}
+.img-box {
+  width: 60px;
+  height: 60px;
+  margin-top: 5px;
+  border: 1px solid rgb(194, 199, 207);
+  border-radius: 4px;
+}
+/* 商品定向Tab栏 */
+::v-deep(.goods-orientation-tabs #tab-1) {
+  border-right: 0;
+}
+</style>

+ 444 - 0
src/views/adManage/sb/campaigns/CreateCampaigns/component/VideoCommodity.vue

@@ -0,0 +1,444 @@
+<template>
+  <div prop="commodity" style="width: 100%" v-loading="productLoading">
+    <div style="width: 100%; height: 620px; display: flex; border: 1px solid #e5e7ec; border-radius: 6px">
+      <div style="width: 50%; border-right: 1px solid #e5e7ec">
+        <el-tabs v-model="productTabs" class="demo-tabs">
+          <el-tab-pane label="搜索" name="first">
+            <div style="margin-bottom: 10px">
+              <el-input v-model="searchInp" placeholder="Please input" class="input-with-select" @change="inpChange" clearable>
+                <template #prepend>
+                  <el-select v-model="leftSelect" style="width: 100px" @change="selChange">
+                    <el-option label="名称" value="name" />
+                    <el-option label="ASIN" value="asin" />
+                    <el-option label="SKU" value="sku" />
+                  </el-select>
+                </template>
+                <template #append>
+                  <el-select v-model="rightSelect" style="width: 100px">
+                    <el-option label="最新优先" value="latest" />
+                    <el-option label="最早优先" value="earliest" />
+                    <el-option label="优选广告" value="optimal" />
+                  </el-select>
+                </template>
+              </el-input>
+            </div>
+            <el-table
+              height="490"
+              style="width: 100%"
+              v-loading="loading"
+              :data="productTableData"
+              :header-cell-style="headerCellStyle"
+              @selection-change="handleSelectionChange">
+              <el-table-column type="selection" width="50" />
+              <el-table-column prop="asin" label="商品">
+                <template #default="scope">
+                  <div style="display: flex; align-items: center">
+                    <div style="margin-right: 8px; line-height: normal">
+                      <el-image class="img-box" :src="scope.row.image_link" />
+                    </div>
+                    <div>
+                      <el-tooltip class="box-item" effect="dark" :content="scope.row.title" placement="top">
+                        <div class="single-line">{{ scope.row.title ? scope.row.title : '--' }}</div>
+                      </el-tooltip>
+                      <div class="data-color">
+                        <span style="font-weight: 500; color: rgb(30, 33, 41)">${{ scope.row.price ? scope.row.price : '--' }}</span>
+                        <span style="margin: 0 5px; color: #cacdd4">|</span>
+                        <span style="color: #6d7784">{{ scope.row.quantity }}</span>
+                      </div>
+                      <span>
+                        ASIN: <span class="data-color" style="margin-right: 8px">{{ scope.row.asin ? scope.row.asin : '--' }}</span>
+                      </span>
+                      <span>
+                        SKU: <span class="data-color">{{ scope.row.sku ? scope.row.sku : '--' }}</span>
+                      </span>
+                    </div>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column prop="name" label="Name" width="120" align="right">
+                <template #header>
+                  <el-button type="primary" size="normal" link @click="handleGoodsAdd">添加已选中</el-button>
+                </template>
+                <template #default="scope">
+                  <el-button type="primary" size="small" @click="addSingleGoods(scope)" text>添加</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+            <el-pagination
+              @current-change="handleCurrentChange"
+              @size-change="handleSizeChange"
+              :current-page="currentPage"
+              :page-size="pageSize"
+              :total="totalItems"
+              layout="prev, pager, next" />
+          </el-tab-pane>
+          <el-tab-pane label="输入" name="second">
+            <el-input
+              style="padding: 10px"
+              v-model="productTextarea"
+              :rows="20"
+              type="textarea"
+              placeholder="请输入ASIN,多个ASIN使用逗号、空格或换行符分隔。(未完成)"
+              maxlength="11000" />
+            <div style="display: flex; flex-direction: row-reverse; margin-top: 10px">
+              <el-button v-for="button in buttons" :key="button.text" :type="button.type" link @click="addGods">{{ button.text }}</el-button>
+            </div>
+          </el-tab-pane>
+        </el-tabs>
+      </div>
+      <div style="width: 50%">
+        <el-card class="box-card" shadow="never" style="border: 0">
+          <template #header>
+            <div class="card-header">
+              <span style="font-weight: 550; font-size: 15px; color: #1f2128">已添加: {{ addedTableData.length }}</span>
+
+                <el-text type="warning" truncated>最多添加一个产品</el-text>
+
+              <el-button class="button" text bg @click="delAllGoods">全部删除</el-button>
+            </div>
+          </template>
+          <div class="card-body"></div>
+        </el-card>
+        <div style="padding: 0 10px 0 10px; margin-top: -12px">
+          <el-table
+            :data="addedTableData"
+            height="475"
+            style="width: 100%"
+            :header-cell-style="headerCellStyle"
+            @selection-change="handleAddedGoodsChange">
+            <el-table-column type="selection" width="50" />
+            <el-table-column prop="asin" label="ASIN">
+              <template #default="scope">
+                <div style="display: flex; align-items: center">
+                  <div style="margin-right: 8px; line-height: normal">
+                    <el-image class="img-box" :src="scope.row.image_link" />
+                  </div>
+                  <div>
+                    <el-tooltip class="box-item" effect="dark" :content="scope.row.title" placement="top">
+                      <div class="single-line">{{ scope.row.title ? scope.row.title : '--' }}</div>
+                    </el-tooltip>
+                    <div class="data-color">
+                      <span style="font-weight: 500; color: rgb(30, 33, 41)">${{ scope.row.price ? scope.row.price : '--' }}</span>
+                      <span style="margin: 0 5px; color: #cacdd4">|</span>
+                      <span style="color: #6d7784">{{ scope.row.quantity }}</span>
+                    </div>
+                    <span
+                      >ASIN:
+                      <span class="data-color" style="margin-right: 8px">{{ scope.row.asin ? scope.row.asin : '--' }}</span>
+                    </span>
+                    <span
+                      >SKU:
+                      <span class="data-color">{{ scope.row.sku ? scope.row.sku : '--' }}</span>
+                    </span>
+                  </div>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column prop="name" label="Name" width="120" align="right">
+              <template #header>
+                <el-button type="primary" size="normal" link @click="delSelectedGoods">删除已选中</el-button>
+              </template>
+              <template #default="scope">
+                <el-button type="primary" size="small" @click="delSingleGoods(scope)" text>删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+        <div style="display: flex; justify-content: space-around; padding-top: 5px">
+          <el-button type="primary" plain :disabled="productSave" @click="submitProductForm">保存</el-button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import type { TabsPaneContext } from 'element-plus'
+import { ElMessage } from 'element-plus'
+import { storeToRefs } from 'pinia'
+import type { Ref } from 'vue'
+import { inject, onMounted, ref, watch } from 'vue'
+import { useShopInfo } from '/@/stores/shopInfo'
+import { request } from '/@/utils/service'
+
+const shopInfo = useShopInfo()
+const { profile } = storeToRefs(shopInfo)
+const productTextarea = ref('')
+const productLoading = ref(false)
+let addedAdsTableItems = ref([])
+const currentPage = ref() // 当前页
+const pageSize = ref(20) // 每页显示条目数
+const totalItems = ref() // 数据总量
+const productTableData = ref([]) // 左侧表格数据
+const loading = ref(false)
+let addedTableData = ref([])
+let selections = []
+let addedSels = []
+const searchInp = ref('')
+const leftSelect = ref('name')
+let productSave = ref(true)
+const buttons = [{ type: 'primary', text: '添加' }] as const
+const productTabs = ref('first')
+const rightSelect = ref('latest')
+const respCampaignId = inject<Ref>('respCampaignId')
+const respCampaignName = inject<Ref>('respCampaignName')
+const respAdGroupId = inject<Ref>('respAdGroupId')
+
+function setTableData(asin = '', sku = '') {
+  return request({
+    url: '/api/sellers/listings/our/',
+    method: 'GET',
+    params: {
+      page: currentPage.value,
+      limit: pageSize.value,
+      profile_id: profile.value.profile_id,
+      asin,
+      sku,
+    },
+  })
+    .then((resp) => {
+      productTableData.value = resp.data
+      totalItems.value = resp.total
+      currentPage.value = resp.page
+      loading.value = false
+    })
+    .catch((error) => {
+      console.error('Error fetching data:', error)
+      loading.value = false
+    })
+}
+
+function addSingleGoods(scope) {
+  // console.log('scope', scope.row)
+  const isAlreadyAdded = addedTableData.value.some((item) => item.sku === scope.row.sku)
+  if (!isAlreadyAdded) {
+    addedTableData.value.push(scope.row)
+  } else {
+    console.log('Item is already added.')
+  }
+}
+
+function addGods() {
+  const inputData = productTextarea.value
+  const asins = inputData.split(/[\n,]+/)
+
+  asins.forEach((asin) => {
+    if (asin.trim()) {
+      setTableData(asin.trim())
+        .then((response) => {
+          console.log(`Data for ASIN ${asin}:`, response) // 更新这里来正确地访问数据
+        })
+        .catch((error) => {
+          console.error(`Error fetching data for ASIN ${asin}:`, error)
+        })
+    }
+  })
+}
+
+function delSingleGoods(scope) {
+  const index = addedTableData.value.findIndex((item) => item.sku === scope.row.sku)
+  if (index !== -1) {
+    addedTableData.value.splice(index, 1)
+    console.log('Item removed successfully.')
+  } else {
+    console.log('Item not found.')
+  }
+}
+
+function delAllGoods() {
+  addedTableData.value = []
+  // addedTableData.value.splice(0, addedTableData.value.length)
+}
+
+// 删除第二个table中已经选中的项
+function delSelectedGoods() {
+  addedTableData.value = addedTableData.value.filter((item) => !addedSels.includes(item))
+  addedSels = []
+}
+
+function inpChange(e) {
+  const value = e
+  if (leftSelect.value === 'asin') {
+    loading.value = true
+    setTableData(value)
+  } else if (leftSelect.value === 'sku') {
+    loading.value = true
+    setTableData('', value)
+  }
+}
+
+function selChange(e) {
+  console.log('e', e)
+  const value = e
+  if (leftSelect.value === 'asin' && searchInp.value) {
+    loading.value = true
+    setTableData(value)
+  } else if (leftSelect.value === 'sku' && searchInp.value) {
+    loading.value = true
+    setTableData('', value)
+  }
+}
+// 点击表格选项触发事件
+function handleSelectionChange(selection) {
+  selections = selection
+}
+// 获取addedTable中已选中的项
+function handleAddedGoodsChange(selection) {
+  addedSels = selection
+}
+// 添加已选中的项
+function handleGoodsAdd() {
+  // 过滤掉已经存在于addedData.value中的项
+  const newSelections = selections.filter(
+    (sel) => !addedTableData.value.some((added) => added.sku === sel.sku) // 使用sku作为唯一标识
+  )
+  // 如果有新的不重复项,加入到addedData.value中
+  if (newSelections.length > 0) {
+    addedTableData.value.push(...newSelections)
+  }
+}
+// 点击Tab
+const handleGoodsTabs = (tab: TabsPaneContext, event: Event) => {
+  console.log(tab, event)
+}
+
+function isItemInList(item, list) {
+  return list.some((listItem) => listItem.sku === item.sku && listItem.asin === item.asin)
+}
+// 监听商品右侧表格已添加的数据并转化数据格式
+watch(
+  addedTableData,
+  (newValue, oldValue) => {
+    newValue.forEach((item) => {
+      if (!isItemInList(item, addedAdsTableItems.value)) {
+        addedAdsTableItems.value.push({ sku: item.sku, asin: item.asin })
+      }
+    })
+    if (addedTableData.value.length !== 0) {
+      productSave.value = false
+    } else {
+      productSave.value = true
+    }
+  },
+  { deep: true }
+)
+
+async function createAds() {
+  try {
+    const requestData = {
+      profile_id: profile.value.profile_id,
+      campaignId: respCampaignId.value,
+      adGroupId: respAdGroupId.value,
+      asinsku: addedAdsTableItems.value,
+      state: 'PAUSED',
+    }
+    const filteredRequestData = Object.fromEntries(Object.entries(requestData).filter(([_, v]) => v != null))
+    const resp = await request({
+      url: '/api/ad_manage/spads/create/',
+      method: 'POST',
+      data: filteredRequestData,
+    })
+    console.log('🚀 ~ createAds ~ resp-->>', resp)
+    productLoading.value = false
+    if (resp.data.success.length > 0) {
+      productSave.value = false
+      addedTableData.value = []
+      ElMessage({
+        message: '商品创建成功',
+        type: 'success',
+      })
+    } else {
+      ElMessage.error('商品创建失败!')
+    }
+  } catch (error) {
+    console.error('请求失败:', error)
+  }
+}
+
+function submitProductForm() {
+  productLoading.value = true
+  createAds()
+}
+
+// 处理分页器当前页变化
+function handleCurrentChange(newPage) {
+  currentPage.value = newPage
+  loading.value = true
+  setTableData()
+}
+// 处理分页器每页显示条目数变化
+function handleSizeChange(newSize) {
+  pageSize.value = newSize
+  currentPage.value = 1 // 重置到第一页
+}
+
+const headerCellStyle = (args) => {
+  if (args.rowIndex === 0) {
+    return {
+      backgroundColor: 'rgba(245, 245, 245, 0.9)',
+    }
+  }
+}
+onMounted(() => {
+  setTableData()
+})
+</script>
+
+<style lang="scss" scoped>
+::v-deep(.el-form--default.el-form--label-top .el-form-item .el-form-item__label) {
+  font-weight: 500;
+}
+.demo-tabs > .el-tabs__content {
+  padding: 52px;
+  color: #6b778c;
+  font-size: 32px;
+  font-weight: 600;
+}
+/* 广告组商品Tab栏 */
+::v-deep(.el-tabs__nav-scroll) {
+  overflow: hidden;
+  margin-left: 20px;
+}
+::v-deep(.el-table__inner-wrapper::before) {
+  background-color: white;
+}
+// 表格内容边距
+div {
+  & #pane-first,
+  & #pane-second {
+    margin: 10px;
+  }
+}
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+.box-card {
+  width: 100%;
+  margin-right: 10px;
+}
+.single-line {
+  color: rgb(30, 33, 41);
+  overflow: hidden;
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+  -webkit-line-clamp: 1;
+  white-space: pre-wrap;
+  word-break: break-word;
+}
+.data-color {
+  color: rgb(30, 33, 41);
+}
+.img-box {
+  width: 60px;
+  height: 60px;
+  margin-top: 5px;
+  border: 1px solid rgb(194, 199, 207);
+  border-radius: 4px;
+}
+/* 商品定向Tab栏 */
+::v-deep(.goods-orientation-tabs #tab-1) {
+  border-right: 0;
+}
+</style>

+ 28 - 2
src/views/adManage/sb/campaigns/CreateCampaigns/index.vue

@@ -1,11 +1,33 @@
 <template>
   <div class="page-container">
-    <AdCampaigns></AdCampaigns>
+    <AdCampaign @update-campaign="handleCampaignUpdate"></AdCampaign>
+    <AdGroup @update-group-id="handleGroupIdUpdate"></AdGroup>
+    <AdFormat></AdFormat>
   </div>
 </template>
 
 <script lang="ts" setup>
-import AdCampaigns from './component/AdCampaigns.vue'
+import { provide, ref } from 'vue'
+import AdCampaign from './component/AdCampaign.vue'
+import AdGroup from './component/AdGroup.vue'
+import AdFormat from './component/AdFormat.vue'
+
+
+const respCampaignId = ref('')
+const respCampaignName = ref('')
+const respAdGroupId = ref('')
+
+provide('respCampaignId', respCampaignId)
+provide('respCampaignName', respCampaignName)
+provide('respAdGroupId', respAdGroupId)
+
+const handleCampaignUpdate = (data) => {
+  respCampaignId.value = data.id
+  respCampaignName.value = data.name
+}
+const handleGroupIdUpdate = (data) => {
+  respAdGroupId.value = data.id
+}
 </script>
 
 <style scoped>
@@ -13,4 +35,8 @@ import AdCampaigns from './component/AdCampaigns.vue'
   padding: 12px;
   background-color: #fafafa;
 }
+::v-deep(.el-form--default.el-form--label-top .el-form-item .el-form-item__label) {
+  font-weight: 500;
+  color: #505968;
+}
 </style>

+ 2 - 2
src/views/adManage/sp/campaigns/CreateCampaigns/index.vue

@@ -597,7 +597,8 @@
                                 @change="dialogSelectChange"
                                 multiple
                                 placeholder="请选择"
-                                v-loading="dialogSelectLoading">
+                                :loading="dialogSelectLoading"
+                                >
                                 <el-option v-for="item in dialogForm.dialogOptions" :key="item.value" :label="item.label" :value="item.value" />
                               </el-select>
                             </el-form-item>
@@ -892,7 +893,6 @@ import { usePublicData } from '/@/stores/publicData'
 import { storeToRefs } from 'pinia'
 import { useRouter } from 'vue-router'
 import { request } from '/@/utils/service'
-import { number } from 'echarts'
 
 const negativeTableData = ref([])
 const addedNegetiveTableData = ref([])