Ver código fonte

否定词,否定商品

WanGxC 1 ano atrás
pai
commit
d995b41396

+ 1 - 1
.prettierrc.js

@@ -36,7 +36,7 @@ module.exports = {
 	// 指定HTML文件的全局空格敏感度 css\strict\ignore
 	htmlWhitespaceSensitivity: 'css',
 	// Vue文件脚本和样式标签缩进
-	vueIndentScriptAndStyle: true,
+	vueIndentScriptAndStyle: false,
 	// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
 	endOfLine: 'lf',
 };

+ 1 - 0
src/views/adManage/sd/campaigns/index.vue

@@ -71,6 +71,7 @@ import {getCardData, getLineData, getLineMonthData, getLineWeekData, getLineHour
 import {SdBaseColumn} from '/@/views/adManage/utils/commonTabColumn.js'
 import DataCompare from '/@/components/dataCompare/index.vue'
 
+
 const tabActiveName = ref('dataTendency')
 const shopInfo = useShopInfo()
 const publicData = usePublicData()

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

@@ -125,7 +125,7 @@
                       :header-cell-style="headerCellStyle"
                       @selection-change="handleSelectionChange">
                       <el-table-column type="selection" width="50" />
-                      <el-table-column prop="asin" label="ASIN" width="538">
+                      <el-table-column prop="asin" label="商品" width="538">
                         <template #default="scope">
                           <div style="display: flex; align-items: center">
                             <div style="margin-right: 8px; line-height: normal">
@@ -203,7 +203,7 @@
                   <template #header>
                     <div class="card-header">
                       <span style="font-weight: 550; font-size: 15px; color: #1f2128">已添加: {{ addedData.length }}</span>
-                      <el-button class="button" text @click="delAll">全部删除</el-button>
+                      <el-button class="button" text bg @click="delAll">全部删除</el-button>
                     </div>
                   </template>
                   <!-- <div v-for="o in 4" :key="o" class="text item">{{ 'List item ' + o }}</div> -->
@@ -260,7 +260,7 @@
           </el-form-item>
 
           <div class="column-item">
-            <p style="color: #606266; font-weight: 450">自动定向</p>
+            <p style="color: #606266; font-weight: 450"><span style="color: #e47470">*</span> 自动定向</p>
             <el-radio-group v-model="ruleForm.autoRedirect" @change="changeBid">
               <div style="display: flex">
                 <el-radio label="defaultBid">设置默认出价</el-radio>
@@ -275,7 +275,6 @@
               </div>
             </el-radio-group>
           </div>
-
           <el-card v-if="showCard" class="box-card">
             <div>
               <div style="color: #8e9095">
@@ -340,9 +339,160 @@
             <el-card>1233</el-card>
           </el-form-item>
 
+          <div style="font-size: 20px; font-weight: bold; margin-top: 30px">否定词</div>
+          <hr />
+          <el-form-item prop="matchType" style="width: 100%; margin-top: 20px">
+            <div style="width: 100%; height: 520px; display: flex; border: 1px solid #c2c7cf; border-radius: 6px">
+              <div style="width: 50%; border-right: 1px solid #c2c7cf">
+                <div style="margin: 10px 0">
+                  <span style="margin-left: 25px; color: #e47470">*</span>
+                  <span style="color: #666666; margin-right: 10px">匹配类型: </span>
+                  <el-checkbox v-model="ruleForm.phraseNegation" label="词组否定" />
+                  <el-checkbox v-model="ruleForm.preciseNegation" label="精确否定" />
+                </div>
+                <el-input
+                  v-model="ruleForm.negativeTextarea"
+                  :rows="17"
+                  type="textarea"
+                  placeholder="请输入关键词,多个关键词使用逗号或者换行符分隔。(最多添加1000个关键词)"
+                  maxlength="11000"
+                  style="padding: 0 20px" />
+                <div style="display: flex; flex-direction: row-reverse; margin-top: 10px">
+                  <el-button style="margin-right: 18px" type="primary" text bg @click="addNegative">添加</el-button>
+                </div>
+              </div>
+              <div style="width: 50%">
+                <el-card class="box-card" shadow="never">
+                  <template #header>
+                    <div class="card-header">
+                      <span style="font-weight: 550; font-size: 15px; color: #1f2128">已添加: {{ addedData.length }}</span>
+                      <el-button class="button" text bg @click="delAllNegative">全部删除</el-button>
+                    </div>
+                  </template>
+                  <div class="card-body">
+                    <el-table :data="tableData" style="width: 100%" :header-row-style="changeNegTableHeader">
+                      <el-table-column prop="negativeWords" label="否定词" width="628" />
+                      <el-table-column prop="operate" label="操作" width="60" align="right">
+                        <template #default="scope">
+                          <el-button type="primary" size="small" @click="delSingleNegative(scope)" text>删除</el-button>
+                        </template>
+                      </el-table-column>
+                    </el-table>
+                  </div>
+                </el-card>
+                <div style="padding: 0 10px 0 10px; margin-top: -12px"></div>
+              </div>
+            </div>
+          </el-form-item>
+
+          <div style="font-size: 20px; font-weight: bold; margin-top: 30px">否定商品</div>
+          <hr />
+          <el-form-item prop="matchType" style="width: 100%; margin-top: 20px">
+            <div style="width: 100%; height: 520px; display: flex; border: 1px solid #c2c7cf; border-radius: 6px">
+              <div style="width: 50%; border-right: 1px solid #c2c7cf">
+                <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
+                  <el-tab-pane label="搜索" name="first">
+                    <div style="margin-bottom: 10px">
+                      <el-input placeholder="按ASIN搜索" v-model="negativeInput" @change="searchNegative" clearable />
+                    </div>
+                    <el-table
+                      height="415"
+                      style="width: 100%"
+                      v-loading="loading"
+                      :data="negativeTableData"
+                      :header-cell-style="headerCellStyle"
+                      @selection-change="handleSelectionChange"
+                      :show-header="false">
+                      <el-table-column prop="asin" label="商品" width="588">
+                        <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>
+                              <span>
+                                ASIN: <span class="data-color" style="margin-right: 8px">{{ scope.row.asin ? scope.row.asin : '--' }}</span>
+                              </span>
+                            </div>
+                          </div>
+                        </template>
+                      </el-table-column>
+                      <el-table-column prop="name" label="Name" width="120" align="right">
+                        <template #header>
+
+                        </template>
+                        <template #default="scope">
+                          <el-button type="primary" size="small" @click="addSingleNegative(scope)" text>添加</el-button>
+                        </template>
+                      </el-table-column>
+                    </el-table>
+                  </el-tab-pane>
+                  <el-tab-pane label="输入" name="second">
+                    <el-input
+                      v-model="ruleForm.negativeGoodsTextarea"
+                      :rows="17"
+                      type="textarea"
+                      placeholder="请输入关键词,多个关键词使用逗号或者换行符分隔。(最多添加1000个关键词)"
+                      maxlength="11000"
+                      style="padding: 0 20px" />
+                    <div style="display: flex; flex-direction: row-reverse; margin-top: 10px">
+                      <el-button style="margin-right: 18px" type="primary" text bg @click="addNegativeGoods">添加</el-button>
+                    </div>
+                  </el-tab-pane>
+                </el-tabs>
+              </div>
+              <div style="width: 50%">
+                <el-card class="box-card" shadow="never">
+                  <template #header>
+                    <div class="card-header">
+                      <span style="font-weight: 550; font-size: 15px; color: #1f2128">已添加: {{ addedNegetiveTableData.length }}</span>
+                      <el-button class="button" text bg @click="delAllNegativeGoods">全部删除</el-button>
+                    </div>
+                  </template>
+                  <div class="card-body"></div>
+                </el-card>
+                <div style="padding: 0 10px 0 10px; margin-top: -12px">
+                  <el-table
+                    :data="addedNegetiveTableData"
+                    height="415"
+                    style="width: 100%"
+                    :header-cell-style="headerCellStyle"
+                    @selection-change="handleAddedChange">
+                    <el-table-column prop="asin" label="商品" width="588">
+                      <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>
+                            <span
+                              >ASIN:
+                              <span class="data-color" style="margin-right: 8px">{{ scope.row.asin ? scope.row.asin : '--' }}</span>
+                            </span>
+                          </div>
+                        </div>
+                      </template>
+                    </el-table-column>
+                    <el-table-column label="操作" width="120" align="right">
+                      <template #default="scope">
+                        <el-button type="primary" size="small" @click="delSingleNegativeGoods(scope)" text>删除</el-button>
+                      </template>
+                    </el-table-column>
+                  </el-table>
+                </div>
+              </div>
+            </div>
+          </el-form-item>
+
           <br />
           <el-form-item>
-            <el-button type="primary" @click="submitForm(ruleFormRef)">Create</el-button>
+            <el-button type="negativeGoods" @click="submitForm(ruleFormRef)">Create</el-button>
             <el-button @click="resetForm(ruleFormRef)">Reset</el-button>
           </el-form-item>
         </el-form>
@@ -352,526 +502,594 @@
 </template>
 
 <script lang="ts" setup>
-  import { onMounted, reactive, ref, computed, watch } from 'vue'
-  import { useRoute } from 'vue-router'
-  import type { FormInstance, FormRules, TabsPaneContext } from 'element-plus'
-  import { Search } from '@element-plus/icons-vue'
-  import { useShopInfo } from '/@/stores/shopInfo'
-  import { usePublicData } from '/@/stores/publicData'
-  import { storeToRefs } from 'pinia'
-  import { useRouter } from 'vue-router'
-  import axios from 'axios'
-  import { request } from '/@/utils/service'
-
-  const router = useRouter()
-  const route = useRoute()
-  const shopInfo = useShopInfo()
-  const { profile } = storeToRefs(shopInfo)
-  const loading = ref(true)
-  const fullTableData = ref([]) // 表格数据
-  let addedData = ref([]) // 已添加的商品数据
-  let selections = [] // 添加选中的项
-  let addedSels = [] // 删除选中的项
-  const currentPage = ref() // 当前页
-  const pageSize = ref(20) // 每页显示条目数
-  const totalItems = ref() // 数据总量
-  const showCard = ref(false)
-
-  // 当单选按钮变化时更新showCard状态
-  function changeBid() {
-    console.log(ruleForm.autoRedirect)
-    showCard.value = ruleForm.autoRedirect === 'targetBid'
-  }
-  // 切换投放类型
-  function changeType() {}
-
-  function setTableData(asin = '', sku = '') {
-    return request({
-      url: '/api/sellers/listings/',
-      method: 'GET',
-      params: {
-        page: currentPage.value,
-        limit: pageSize.value,
-        profile_id: profile.value.profile_id,
-        asin,
-        sku,
-      },
+import { onMounted, reactive, ref, computed, watch } from 'vue'
+import { useRoute } from 'vue-router'
+import type { FormInstance, FormRules, TabsPaneContext } from 'element-plus'
+import { useShopInfo } from '/@/stores/shopInfo'
+import { usePublicData } from '/@/stores/publicData'
+import { storeToRefs } from 'pinia'
+import { useRouter } from 'vue-router'
+import { request } from '/@/utils/service'
+
+const negativeTableData = ref([])
+const addedNegetiveTableData = ref([])
+const router = useRouter()
+const route = useRoute()
+const shopInfo = useShopInfo()
+const { profile } = storeToRefs(shopInfo)
+const loading = ref(true)
+const fullTableData = ref([]) // 表格数据
+let addedData = ref([]) // 已添加的商品数据
+let selections = [] // 添加选中的项
+let addedSels = [] // 删除选中的项
+const currentPage = ref() // 当前页
+const pageSize = ref(20) // 每页显示条目数
+const totalItems = ref() // 数据总量
+const showCard = ref(false)
+const activeName = ref('first')
+const searchInp = ref('')
+const select = ref('name')
+const select2 = ref('latest')
+const textarea = ref('')
+const buttons = [{ type: 'primary', text: '添加' }] as const
+const negativeInput = ref('')
+
+// 表单相关数据
+const formSize = ref('default')
+const labelPosition = ref('top')
+const ruleFormRef = ref<FormInstance>()
+interface RuleForm {
+  name: string
+  adMix: string
+  count: string
+  date1: string
+  date2: string
+  budget: string
+  delivery: boolean
+  type: string
+  bidStrategy: string
+  placeBid: string
+  firstPage: string
+  other: string
+  adGroupName: string
+  autoRedirect: string
+  defaultBidInp: string
+  closeMatch: boolean
+  broadMatch: boolean
+  similarProducts: boolean
+  relatedProducts: boolean
+  closeMatchInp: string
+  broadMatchInp: string
+  similarProductsInp: string
+  relatedProductsInp: string
+  phraseNegation: boolean
+  preciseNegation: boolean
+  negativeTextarea: string
+  negativeGoodsTextarea: string
+}
+const ruleForm = reactive<RuleForm>({
+  name: 'Hello',
+  adMix: '',
+  count: '',
+  date1: '',
+  date2: '',
+  budget: '',
+  delivery: false,
+  type: 'auto',
+  bidStrategy: 'dynamicBid_Low',
+  placeBid: '',
+  firstPage: '',
+  other: '',
+  adGroupName: '',
+  autoRedirect: 'defaultBid',
+  defaultBidInp: '',
+  closeMatch: true,
+  broadMatch: true,
+  similarProducts: true,
+  relatedProducts: true,
+  closeMatchInp: '666',
+  broadMatchInp: '666',
+  similarProductsInp: '666',
+  relatedProductsInp: '666',
+  phraseNegation: true,
+  preciseNegation: true,
+  negativeTextarea: '',
+  negativeGoodsTextarea: '',
+})
+const rules = computed(() => ({
+  name: [{ required: true, message: 'Please input Activity name', trigger: 'blur' }],
+  adMix: [{ required: false, message: 'Please select Activity zone', trigger: 'change' }],
+  count: [{ required: true, message: 'Please select Activity count', trigger: 'change' }],
+  date1: [{ required: true, type: 'date', message: 'Please pick a date', trigger: 'change' }],
+  date2: [{ required: false, type: 'date', message: 'Please pick a time', trigger: 'change' }],
+  budget: [
+    { required: true, message: '请输入预算', trigger: 'blur' },
+    { pattern: /^(?:[1-9]\d{0,5}|1000000)(?:\.\d{1,2})?$/, message: '预算必须是1到1000000之间的数字,小数点后最多两位', trigger: 'blur' },
+  ],
+  type: [{ required: false, trigger: 'change' }],
+  bidStrategy: [{ required: true, message: 'Please select activity resource', trigger: 'change' }],
+  placeBid: [{ required: false, pattern: /^[0-9]{1,3}$/, message: '必须是0~900之间的整数百分比', trigger: 'change' }],
+  firstPage: [{ required: false, pattern: /^[0-9]{1,3}$/, message: '必须是0~900之间的整数百分比', trigger: 'change' }],
+  other: [{ required: false, pattern: /^[0-9]{1,3}$/, message: '必须是0~900之间的整数百分比', trigger: 'change' }],
+  adGroupName: [{ required: true, message: 'Please input Activity name', trigger: 'blur' }],
+  autoRedirect: [{ required: true, trigger: 'change' }],
+  defaultBidInp: getValidationRules('defaultBidInp'),
+  relatedProductsInp: getValidationRules('relatedProductsInp'),
+  similarProductsInp: getValidationRules('similarProductsInp'),
+  broadMatchInp: getValidationRules('broadMatchInp'),
+  closeMatchInp: getValidationRules('closeMatchInp'),
+}))
+
+//------------------------------------------------------------------------------方法------------------------------------------------------------------------------
+
+// 当单选按钮变化时更新showCard状态
+function changeBid() {
+  console.log(ruleForm.autoRedirect)
+  showCard.value = ruleForm.autoRedirect === 'targetBid'
+}
+// 切换投放类型
+function changeType() {}
+
+function setTableData(asin = '', sku = '') {
+  return request({
+    url: '/api/sellers/listings/',
+    method: 'GET',
+    params: {
+      page: currentPage.value,
+      limit: pageSize.value,
+      profile_id: profile.value.profile_id,
+      asin,
+      sku,
+    },
+  })
+    .then((resp) => {
+      fullTableData.value = resp.data
+      totalItems.value = resp.total
+      currentPage.value = resp.page
+      loading.value = false
     })
-      .then((resp) => {
-        fullTableData.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
-      })
-  }
+    .catch((error) => {
+      console.error('Error fetching data:', error)
+      loading.value = false
+    })
+}
 
-  // 处理分页器当前页变化
-  function handleCurrentChange(newPage) {
-    currentPage.value = newPage
-    loading.value = true
-    setTableData()
+// 处理分页器当前页变化
+function handleCurrentChange(newPage) {
+  currentPage.value = newPage
+  loading.value = true
+  setTableData()
+}
+// 处理分页器每页显示条目数变化
+function handleSizeChange(newSize) {
+  pageSize.value = newSize
+  currentPage.value = 1 // 重置到第一页
+}
+
+// 点击表格选项触发事件
+function handleSelectionChange(selection) {
+  selections = selection
+}
+// 添加已选中的项
+function handleAdd() {
+  // 过滤掉已经存在于addedData.value中的项
+  const newSelections = selections.filter(
+    (sel) => !addedData.value.some((added) => added.sku === sel.sku) // 假设使用sku作为唯一标识
+  )
+  // 如果有新的不重复项,加入到addedData.value中
+  if (newSelections.length > 0) {
+    addedData.value.push(...newSelections)
   }
-  // 处理分页器每页显示条目数变化
-  function handleSizeChange(newSize) {
-    pageSize.value = newSize
-    currentPage.value = 1 // 重置到第一页
+  // console.log('addedData', addedData.value)
+}
+// 获取addedTable中已选中的项
+function handleAddedChange(selection) {
+  addedSels = selection
+}
+// 删除第二个table中已经选中的项
+function handleDel() {
+  addedData.value = addedData.value.filter((item) => !addedSels.includes(item))
+  addedSels = []
+}
+function addSingle(scope) {
+  console.log('scope', scope.row)
+
+  const isAlreadyAdded = addedData.value.some((item) => item.sku === scope.row.sku)
+  if (!isAlreadyAdded) {
+    addedData.value.push(scope.row)
+  } else {
+    console.log('Item is already added.')
   }
+}
+
 
-  // 点击表格选项触发事件
-  function handleSelectionChange(selection) {
-    selections = selection
+function addSingleNegative(scope) {
+  console.log('scope', scope.row)
+
+  const isAlreadyAdded = addedNegetiveTableData.value.some((item) => item.sku === scope.row.sku)
+  if (!isAlreadyAdded) {
+    addedNegetiveTableData.value.push(scope.row)
+  } else {
+    console.log('Item is already added.')
   }
-  // 添加已选中的项
-  function handleAdd() {
-    // 过滤掉已经存在于addedData.value中的项
-    const newSelections = selections.filter(
-      (sel) => !addedData.value.some((added) => added.sku === sel.sku) // 假设使用sku作为唯一标识
-    )
-    // 如果有新的不重复项,加入到addedData.value中
-    if (newSelections.length > 0) {
-      addedData.value.push(...newSelections)
-    }
-    // console.log('addedData', addedData.value)
+}
+
+function delSingle(scope) {
+  const index = addedData.value.findIndex((item) => item.sku === scope.row.sku)
+
+  if (index !== -1) {
+    addedData.value.splice(index, 1)
+    console.log('Item removed successfully.')
+  } else {
+    console.log('Item not found.')
   }
-  // 获取addedTable中已选中的项
-  function handleAddedChange(selection) {
-    addedSels = selection
+}
+
+function delSingleNegativeGoods(scope) {
+  const index = addedNegetiveTableData.value.findIndex((item) => item.sku === scope.row.sku)
+
+  if (index !== -1) {
+    addedNegetiveTableData.value.splice(index, 1)
+    console.log('Item removed successfully.')
+  } else {
+    console.log('Item not found.')
   }
-  // 删除第二个table中已经选中的项
-  function handleDel() {
-    addedData.value = addedData.value.filter((item) => !addedSels.includes(item))
-    addedSels = []
+}
+// 全部删除已添加商品列表
+function delAll() {
+  addedData.value = []
+  // addedData.value.splice(0, addedData.value.length)
+}
+
+function delAllNegativeGoods() {
+  addedNegetiveTableData.value = []
+}
+
+function inpChange(e) {
+  const value = e
+  if (select.value === 'asin') {
+    loading.value = true
+    setTableData(value)
+  } else if (select.value === 'sku') {
+    loading.value = true
+    setTableData('', value)
   }
-  function addSingle(scope) {
-    console.log('scope', scope.row)
+}
 
-    const isAlreadyAdded = addedData.value.some((item) => item.sku === scope.row.sku)
-    if (!isAlreadyAdded) {
-      addedData.value.push(scope.row)
-    } else {
-      console.log('Item is already added.')
-    }
+function selChange(e) {
+  console.log('e', e)
+  const value = e
+  if (select.value === 'asin' && searchInp.value) {
+    loading.value = true
+    setTableData(value)
+  } else if (select.value === 'sku' && searchInp.value) {
+    loading.value = true
+    setTableData('', value)
   }
-  function delSingle(scope) {
-    const index = addedData.value.findIndex((item) => item.sku === scope.row.sku)
+}
+
+let negativeList = reactive([])
+const tableData = negativeList
 
-    if (index !== -1) {
-      addedData.value.splice(index, 1)
-      console.log('Item removed successfully.')
+function addNegative() {
+  // 删除 negativeTextarea 前后的空格
+  const trimmedText = ruleForm.negativeTextarea.trim()
+  // 使用逗号和换行符分割文本
+  const items = trimmedText.split(/,|\n/)
+
+  // 遍历分割后的每个项目
+  items.forEach((item) => {
+    const trimmedItem = item.trim() // 删除每个项目前后的空格
+    if (trimmedItem) {
+      // 如果两者都是 true,则为每个创建两个条目
+      if (ruleForm.phraseNegation && ruleForm.preciseNegation) {
+        negativeList.push({ negativeWords: '词组: ' + trimmedItem })
+        negativeList.push({ negativeWords: '精确: ' + trimmedItem })
+      } else if (ruleForm.phraseNegation) {
+        negativeList.push({ negativeWords: '词组: ' + trimmedItem })
+      } else if (ruleForm.preciseNegation) {
+        negativeList.push({ negativeWords: '精确: ' + trimmedItem })
+      }
     } else {
-      console.log('Item not found.')
+      console.log('有空项目,未被添加到列表中')
     }
-  }
-  // 全部删除
-  function delAll() {
-    addedData.value = []
-  }
+  })
 
-  function inpChange(e) {
-    const value = e
-    if (select.value === 'asin') {
-      loading.value = true
-      setTableData(value)
-    } else if (select.value === 'sku') {
-      loading.value = true
-      setTableData('', value)
-    }
-  }
+  // 清空输入框
+  ruleForm.negativeTextarea = ''
+  console.log(negativeList)
+}
 
-  function selChange(e) {
-    console.log('e', e)
-    const value = e
-    if (select.value === 'asin' && searchInp.value) {
-      loading.value = true
-      setTableData(value)
-    } else if (select.value === 'sku' && searchInp.value) {
-      loading.value = true
-      setTableData('', value)
-    }
+function delSingleNegative(scope) {
+  const index = negativeList.findIndex((item) => item.negativeWords === scope.row.negativeWords)
+  if (negativeList.length) {
+    negativeList.splice(index, 1)
+    console.log(`已删除索引为 ${index} 的条目`)
+  } else {
+    console.log('无效的索引,无法删除条目')
   }
+}
+function delAllNegative() {
+  // negativeList.splice(0, negativeList.length)
+  negativeList.length = 0
+}
+function setNegativeTableData(asin = '',) {
+  return request({
+    url: '/api/sellers/listings/',
+    method: 'GET',
+    params: {
+      page: currentPage.value,
+      limit: pageSize.value,
+      profile_id: profile.value.profile_id,
+      asin,
+    },
+  })
+    .then((resp) => {
+      negativeTableData.value = resp.data
+      loading.value = false
+    })
+    .catch((error) => {
+      console.error('Error fetching data:', error)
+      loading.value = false
+    })
+}
 
-  // const size = ref('default')
-  // const labelPosition = ref('top')
-  interface RuleForm {
-    name: string
-    adMix: string
-    count: string
-    date1: string
-    date2: string
-    budget: string
-    delivery: boolean
-    type: string
-    bidStrategy: string
-    placeBid: string
-    firstPage: string
-    other: string
-    adGroupName: string
-    autoRedirect: string
-    defaultBidInp: string
-    closeMatch: boolean
-    broadMatch: boolean
-    similarProducts: boolean
-    relatedProducts: boolean
-    closeMatchInp: string
-    broadMatchInp: string
-    similarProductsInp: string
-    relatedProductsInp: string
+function searchNegative(e) {
+  if (e === '') {
+    negativeTableData.value = []
+  } else {
+    setNegativeTableData(e)
   }
+}
 
-  const formSize = ref('default')
-  const labelPosition = ref('top')
-  const ruleFormRef = ref<FormInstance>()
-  const ruleForm = reactive<RuleForm>({
-    name: 'Hello',
-    adMix: '',
-    count: '',
-    date1: '',
-    date2: '',
-    budget: '',
-    delivery: false,
-    type: 'auto',
-    bidStrategy: 'dynamicBid_Low',
-    placeBid: '',
-    firstPage: '',
-    other: '',
-    adGroupName: '',
-    autoRedirect: 'defaultBid',
-    defaultBidInp: '',
-    closeMatch: true,
-    broadMatch: true,
-    similarProducts: true,
-    relatedProducts: true,
-    closeMatchInp: '',
-    broadMatchInp: '',
-    similarProductsInp: '',
-    relatedProductsInp: '',
-  })
-  const rules = computed(() => ({
-    name: [{ required: true, message: 'Please input Activity name', trigger: 'blur' }],
-    adMix: [{ required: false, message: 'Please select Activity zone', trigger: 'change' }],
-    count: [{ required: true, message: 'Please select Activity count', trigger: 'change' }],
-    date1: [{ required: true, type: 'date', message: 'Please pick a date', trigger: 'change' }],
-    date2: [{ required: false, type: 'date', message: 'Please pick a time', trigger: 'change' }],
-    budget: [
-      { required: true, message: '请输入预算', trigger: 'blur' },
-      { pattern: /^(?:[1-9]\d{0,5}|1000000)(?:\.\d{1,2})?$/, message: '预算必须是1到1000000之间的数字,小数点后最多两位', trigger: 'blur' },
-    ],
-    type: [{ required: false, trigger: 'change' }],
-    bidStrategy: [{ required: true, message: 'Please select activity resource', trigger: 'change' }],
-    placeBid: [{ required: false, pattern: /^[0-9]{1,3}$/, message: '必须是0~900之间的整数百分比', trigger: 'change' }],
-    firstPage: [{ required: false, pattern: /^[0-9]{1,3}$/, message: '必须是0~900之间的整数百分比', trigger: 'change' }],
-    other: [{ required: false, pattern: /^[0-9]{1,3}$/, message: '必须是0~900之间的整数百分比', trigger: 'change' }],
-    adGroupName: [{ required: true, message: 'Please input Activity name', trigger: 'blur' }],
-    autoRedirect: [{ required: true, trigger: 'change' },],
-    defaultBidInp: getValidationRules('defaultBidInp'),
-    relatedProductsInp: getValidationRules('relatedProductsInp'),
-    similarProductsInp: getValidationRules('similarProductsInp'),
-    broadMatchInp: getValidationRules('broadMatchInp'),
-    closeMatchInp: getValidationRules('closeMatchInp'),
-  }))
-
-  function checkBid(value, callback, bidField) {
-    const bid = parseFloat(value)
-    const budget = parseFloat(ruleForm.budget)
-    // 检查值是否为最多两位小数的普通数字格式
-    const isNormalNumberWithTwoDecimals = /^-?\d+(\.\d{1,2})?$/.test(value)
-
-    if (!isNormalNumberWithTwoDecimals) {
-      callback(new Error('请输入数字值(最多两位小数)'))
-    } else if (isNaN(bid)) {
-      callback(new Error('请输入有效的数字'))
-    } else if (bid < 0.02 || bid > 1000) {
-      callback(new Error('值必须在0.02到1000之间'))
-    } else if (bid >= budget) {
-      callback(new Error('出价必须小于预算'))
-    } else {
-      callback()
-    }
-  }
+function addNegativeGoods(e) {
+  setNegativeTableData(e)
+}
 
-  // const validateDefaultBidInp = (rule: any, value: any, callback: any) => {
-  //   if (ruleForm.autoRedirect === 'defaultBid') {
-  //     checkBid(value, callback, 'defaultBidInp')
-  //   }  else {
-  //     ruleFormRef.value?.clearValidate('defaultBidInp')
-  //     callback()
-  //   }
-  // }
-
-  // 校验defaultBidInp
-  // const validateDefaultBidInp = (rule, value, callback) => {
-  //   if (ruleForm.autoRedirect === 'defaultBid') {
-  //     checkBid(value, callback, 'defaultBidInp');
-  //   } else {
-  //     callback();
-  //   }
-  // };
-
-  // 校验其他相关字段
-  // const validateRelatedFields = (rule, value, callback, fieldName) => {
-  //   if (ruleForm.autoRedirect === 'targetBid') {
-  //     checkBid(value, callback, fieldName);
-  //   } else {
-  //     callback();
-  //   }
-  // };
-
-  // 动态生成校验规则的函数
-  function getValidationRules(fieldName) {
-    // 默认校验规则
-    const commonRules = [
-      { required: true, message: '此项为必填项', trigger: 'blur' },
-      { validator: (rule, value, callback) => checkBid(value, callback, fieldName), trigger: 'blur' },
-    ]
-
-    // 根据不同字段和状态返回特定的校验规则
-    switch (fieldName) {
-      case 'defaultBidInp':
-        if (ruleForm.autoRedirect === 'defaultBid') {
-          return commonRules
-        }
-        break
-      case 'similarProductsInp':
-        if (ruleForm.autoRedirect === 'targetBid' && ruleForm.similarProducts) {
-          return commonRules
-        } else if (ruleForm.similarProducts == false) {
-          ruleFormRef.value?.clearValidate(fieldName)
-        }
-        break
-      case 'relatedProductsInp':
-        if (ruleForm.autoRedirect === 'targetBid' && ruleForm.relatedProducts) {
-          return commonRules
-        } else if (ruleForm.relatedProducts == false) {
-          ruleFormRef.value?.clearValidate(fieldName)
-        }
-        break
-      case 'broadMatchInp':
-        if (ruleForm.autoRedirect === 'targetBid' && ruleForm.broadMatch) {
-          return commonRules
-        } else if (ruleForm.broadMatch == false) {
-          ruleFormRef.value?.clearValidate(fieldName)
-        }
-        break
-      case 'closeMatchInp':
-        // 仅当autoRedirect为'targetBid'且closeMatch开启时校验closeMatchInp
-        if (ruleForm.autoRedirect === 'targetBid' && ruleForm.closeMatch) {
-          return commonRules
-        } else if (ruleForm.closeMatch == false) {
-          ruleFormRef.value?.clearValidate(fieldName)
-        }
-        break
-      default:
-        return []
-    }
-    // 如果不满足上述条件,则无需校验
-    return []
+function checkBid(value, callback, bidField) {
+  const bid = parseFloat(value)
+  const budget = parseFloat(ruleForm.budget)
+  // 检查值是否为最多两位小数的普通数字格式
+  const isNormalNumberWithTwoDecimals = /^-?\d+(\.\d{1,2})?$/.test(value)
+
+  if (!isNormalNumberWithTwoDecimals) {
+    callback(new Error('请输入数字值(最多两位小数)'))
+  } else if (isNaN(bid)) {
+    callback(new Error('请输入有效的数字'))
+  } else if (bid < 0.02 || bid > 1000) {
+    callback(new Error('值必须在0.02到1000之间'))
+  } else if (bid >= budget) {
+    callback(new Error('出价必须小于预算'))
+  } else {
+    callback()
   }
+}
 
-  watch(
-    [
-      () => ruleForm.autoRedirect,
-      () => ruleForm.closeMatch,
-      () => ruleForm.broadMatch,
-      () => ruleForm.similarProducts,
-      () => ruleForm.relatedProducts,
-    ],
-    () => {
-      // 更新每个受影响字段的校验规则
-      rules.value.defaultBidInp = getValidationRules('defaultBidInp')
-      rules.value.closeMatchInp = getValidationRules('closeMatchInp')
-      rules.value.broadMatchInp = getValidationRules('broadMatchInp')
-      rules.value.similarProductsInp = getValidationRules('similarProductsInp')
-      rules.value.relatedProductsInp = getValidationRules('relatedProductsInp')
-    }
-  )
+// 动态生成校验规则的函数
+function getValidationRules(fieldName) {
+  // 默认校验规则
+  const commonRules = [
+    { required: true, message: '此项为必填项', trigger: 'blur' },
+    { validator: (rule, value, callback) => checkBid(value, callback, fieldName), trigger: 'blur' },
+  ]
 
-  // watch(() => ruleForm.autoRedirect, (newVal) => {
-  //   if (newVal === 'defaultBid') {
-  //     // 当autoRedirect变为'defaultBid'时,清除其他字段的校验状态,并校验defaultBidInp
-  //     ['relatedProductsInp', 'similarProductsInp', 'broadMatchInp', 'closeMatchInp'].forEach(field => {
-  //       ruleFormRef.value?.clearValidate(field);
-  //     });
-  //     ruleFormRef.value?.validateField('defaultBidInp');
-  //   } else if (newVal === 'targetBid') {
-  //     // 当autoRedirect变为'targetBid'时,清除defaultBidInp的校验状态,并校验其他相关字段
-  //     ruleFormRef.value?.clearValidate('defaultBidInp');
-  //     ['relatedProductsInp', 'similarProductsInp', 'broadMatchInp', 'closeMatchInp'].forEach(field => {
-  //       ruleFormRef.value?.validateField(field);
-  //     });
-  //   }
-  // });
-
-  async function submitForm(formEl: FormInstance | undefined) {
-    if (!formEl) return
-    await formEl.validate((valid, fields) => {
-      if (valid) {
-        console.log('submit!')
-      } else {
-        console.log('error submit!', fields)
+  // 根据不同字段和状态返回特定的校验规则
+  switch (fieldName) {
+    case 'defaultBidInp':
+      if (ruleForm.autoRedirect === 'defaultBid') {
+        return commonRules
       }
-    })
+      break
+    case 'similarProductsInp':
+      if (ruleForm.autoRedirect === 'targetBid' && ruleForm.similarProducts) {
+        return commonRules
+      } else if (ruleForm.similarProducts == false) {
+        ruleFormRef.value?.clearValidate(fieldName)
+      }
+      break
+    case 'relatedProductsInp':
+      if (ruleForm.autoRedirect === 'targetBid' && ruleForm.relatedProducts) {
+        return commonRules
+      } else if (ruleForm.relatedProducts == false) {
+        ruleFormRef.value?.clearValidate(fieldName)
+      }
+      break
+    case 'broadMatchInp':
+      if (ruleForm.autoRedirect === 'targetBid' && ruleForm.broadMatch) {
+        return commonRules
+      } else if (ruleForm.broadMatch == false) {
+        ruleFormRef.value?.clearValidate(fieldName)
+      }
+      break
+    case 'closeMatchInp':
+      // 仅当autoRedirect为'targetBid'且closeMatch开启时校验closeMatchInp
+      if (ruleForm.autoRedirect === 'targetBid' && ruleForm.closeMatch) {
+        return commonRules
+      } else if (ruleForm.closeMatch == false) {
+        ruleFormRef.value?.clearValidate(fieldName)
+      }
+      break
+    default:
+      return []
   }
+  // 如果不满足上述条件,则无需校验
+  return []
+}
 
-  function resetForm(formEl: FormInstance | undefined) {
-    if (!formEl) return
-    formEl.resetFields()
+watch(
+  [() => ruleForm.autoRedirect, () => ruleForm.closeMatch, () => ruleForm.broadMatch, () => ruleForm.similarProducts, () => ruleForm.relatedProducts],
+  () => {
+    // 定义需要更新校验规则的字段
+    const fields = ['defaultBidInp', 'closeMatchInp', 'broadMatchInp', 'similarProductsInp', 'relatedProductsInp']
+    fields.forEach((field) => {
+      rules.value[field] = getValidationRules(field)
+    })
   }
+)
+
+async function submitForm(formEl: FormInstance | undefined) {
+  if (!formEl) return
+  await formEl.validate((valid, fields) => {
+    if (valid) {
+      console.log('submit!')
+    } else {
+      console.log('error submit!', fields)
+    }
+  })
+}
+
+function resetForm(formEl: FormInstance | undefined) {
+  if (!formEl) return
+  formEl.resetFields()
+}
 
-  // const options = Array.from({ length: 10000 }).map((_, idx) => ({
-  //   value: `${idx + 1}`,
-  //   label: `${idx + 1}`,
-  // }))
 
-  // 商品模块
-  const activeName = ref('first')
+const handleClick = (tab: TabsPaneContext, event: Event) => {
+  console.log(tab, event)
+}
 
-  const handleClick = (tab: TabsPaneContext, event: Event) => {
-    console.log(tab, event)
+// 修改表头样式
+const headerCellStyle = (args) => {
+  // console.log('args', args)
+  if (args.rowIndex === 0) {
+    return {
+      backgroundColor: 'rgba(245, 245, 245, 0.9)',
+    }
   }
+}
 
-  const searchInp = ref('')
-  const select = ref('name')
-  const select2 = ref('latest')
-  const textarea = ref('')
-  const buttons = [{ type: 'primary', text: '添加' }] as const
-
-  // 修改表头样式
-  const headerCellStyle = (args) => {
-    // console.log('args', args)
-    if (args.rowIndex === 0) {
-      return {
-        backgroundColor: 'rgba(245, 245, 245, 0.9)',
-      }
+function changeNegTableHeader(args) {
+  console.log('args', args)
+  if (args.rowIndex === 0) {
+    return {
+      color: '#505968',
     }
   }
+}
 
-  onMounted(() => {
-    setTableData()
-    // const myTest = route.query
-    // console.log('myTest', myTest)
-  })
+onMounted(() => {
+  setTableData()
+  // const myTest = route.query
+  // console.log('myTest', myTest)
+})
 
-  defineOptions({
-    name: 'SpCreateCampaigns',
-  })
+defineOptions({
+  name: 'SpCreateCampaigns',
+})
 </script>
 
 <style lang="scss" scoped>
-  ::v-deep(.el-form--default.el-form--label-top .el-form-item .el-form-item__label) {
-    font-weight: 500;
-  }
-  .column-item .el-radio-group {
-    display: inline-flex;
-    font-size: 0;
-    flex-direction: column;
-    align-items: flex-start;
-  }
-  .radio-description {
-    font-size: 12px;
-    color: #666;
-    margin-top: -18px;
-    margin-left: 22px;
-  }
-  .radio-description-2 {
-    font-size: 12px;
-    color: #666;
-    margin-top: -10px;
-  }
-  .column-margin-bottom label.el-radio.is-bordered {
-    margin-bottom: 10px;
-    padding: 35px;
-  }
-  ::v-deep(.column-margin-bottom label.el-radio.is-bordered span.el-radio__inner) {
-    margin-top: -18px;
-    margin-left: -15px;
-  }
-  .gap-items {
-    display: flex;
-    justify-content: flex-start;
-    width: 100%;
-    margin-bottom: 20px;
-  }
-  .gap-item {
-    width: 200px;
-    margin-left: 30px;
-    color: #0b0d0d;
-  }
+::v-deep(.el-form--default.el-form--label-top .el-form-item .el-form-item__label) {
+  font-weight: 500;
+}
+.column-item .el-radio-group {
+  display: inline-flex;
+  font-size: 0;
+  flex-direction: column;
+  align-items: flex-start;
+}
+.radio-description {
+  font-size: 12px;
+  color: #666;
+  margin-top: -18px;
+  margin-left: 22px;
+}
+.radio-description-2 {
+  font-size: 12px;
+  color: #666;
+  margin-top: -10px;
+}
+.column-margin-bottom label.el-radio.is-bordered {
+  margin-bottom: 10px;
+  padding: 35px;
+}
+::v-deep(.column-margin-bottom label.el-radio.is-bordered span.el-radio__inner) {
+  margin-top: -18px;
+  margin-left: -15px;
+}
+.gap-items {
+  display: flex;
+  justify-content: flex-start;
+  width: 100%;
+  margin-bottom: 20px;
+}
+.gap-item {
+  width: 200px;
+  margin-left: 30px;
+  color: #0b0d0d;
+}
 
-  .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-tabs__nav-wrap::after) {
-    height: 2px !important;
-  }
-  ::v-deep(.el-table__inner-wrapper::before) {
-    background-color: white;
-  }
-  // 表格内容边距
-  div {
-    & #pane-first,
-    & #pane-second {
-      margin: 10px;
-    }
-  }
-  // 输入底部样式
-  ::v-deep(.card-box .el-card__body) {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    padding: 12px;
-  }
-  .card-header {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-  }
-  .box-card {
-    width: 100%;
-    // margin: 10px 0 10px 10px;
-    margin-right: 10px;
-    border: none;
+.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-tabs__nav-wrap::after) {
+  height: 2px !important;
+}
+::v-deep(.el-table__inner-wrapper::before) {
+  background-color: white;
+}
+// 表格内容边距
+div {
+  & #pane-first,
+  & #pane-second {
+    margin: 10px;
   }
+}
+// 输入底部样式
+::v-deep(.card-box .el-card__body) {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 12px;
+}
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+.box-card {
+  width: 100%;
+  // margin: 10px 0 10px 10px;
+  margin-right: 10px;
+  border: none;
+}
 
-  .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;
-  }
-  .target-group-item {
-    margin-top: 15px;
-  }
-  .suggested-bid-item {
-    margin-left: 230px;
-    margin-right: 60px;
-  }
-  .bid-input {
-    width: 200px;
-    margin-left: 15px;
-  }
+.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;
+}
+.target-group-item {
+  margin-top: 15px;
+}
+.suggested-bid-item {
+  margin-left: 230px;
+  margin-right: 60px;
+}
+.bid-input {
+  width: 200px;
+  margin-left: 15px;
+}
 </style>