浏览代码

feat: ✨ SP新建广告活动-细化分类dialog

WanGxC 1 年之前
父节点
当前提交
db55116be3
共有 2 个文件被更改,包括 210 次插入9137 次删除
  1. 8 9119
      package-lock.json
  2. 202 18
      src/views/adManage/sp/campaigns/CreateCampaigns/index.vue

文件差异内容过多而无法显示
+ 8 - 9119
package-lock.json


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

@@ -351,7 +351,7 @@
               <div>
                 <el-radio label="Goods" style="align-items: flex-start; margin-top: 20px">
                   <div style="margin-top: -4px">商品投放</div>
-                  <div>选择关键词以帮助您的商品出现在购物者搜索中</div>
+                  <div>选择特定的商品, 分类, 品牌或者其他商品功能来定向您的广告</div>
                 </el-radio>
               </div>
             </el-radio-group>
@@ -483,10 +483,12 @@
           <div style="font-size: 20px; font-weight: bold; margin-top: 30px" v-if="ruleForm.targetType == 'Goods'">商品定向</div>
           <hr v-if="ruleForm.targetType == 'Goods'" />
           <el-form-item style="width: 100%; margin-top: 20px" v-if="ruleForm.targetType == 'Goods'">
-            <div style="width: 100%; height: 520px; display: flex; border: 1px solid #c2c7cf; border-radius: 6px" v-loading="productOrientationLoading">
+            <div
+              style="width: 100%; height: 520px; display: flex; border: 1px solid #c2c7cf; border-radius: 6px"
+              v-loading="productOrientationLoading">
               <div style="width: 50%; border-right: 1px solid #c2c7cf">
-                <el-tabs type="border-card" stretch class="goods-orientation-tabs" style="border-bottom-left-radius: 6px;">
-                  <el-tab-pane label="品类" style="border-top-left-radius: 6px;">
+                <el-tabs type="border-card" stretch class="goods-orientation-tabs" style="border-bottom-left-radius: 6px">
+                  <el-tab-pane label="品类" style="border-top-left-radius: 6px">
                     <div style="display: flex; align-items: center">
                       <span style="width: 40px">竞价:</span>
                       <el-select v-model="categoryBiddingType" class="m-2" placeholder="Select">
@@ -500,9 +502,7 @@
                       <el-tab-pane label="建议" name="first">
                         <el-table :data="proposalTableData" style="width: 100%" height="342">
                           <el-table-column prop="proposal" label="建议" width="520">
-                            <template #header>
-                              0建议
-                            </template>
+                            <template #header> 0建议 </template>
                           </el-table-column>
                           <el-table-column prop="address" label="Address">
                             <template #header>
@@ -515,13 +515,63 @@
                         </el-table>
                       </el-tab-pane>
                       <el-tab-pane label="搜索" name="second">
-                        <el-input placeholder="请输入关键词过滤"  />
-                        <el-table :data="searchClassifyTableData" style="width: 100%" height="309">
-                          <el-table-column prop="categorie_name" label="亚马逊分类">
-                            
-                          </el-table-column>
-                          
-                        </el-table>
+                        <el-input placeholder="请输入关键词过滤" />
+                        <el-scrollbar height="309px">
+                          <el-tree :data="searchClassifyTableData" :props="defaultProps">
+                            <template #default="{ node, data }">
+                              <span class="custom-tree-node">
+                                <span style="width: 75%">{{ node.label }}</span>
+                                <span style="color: rgb(50, 108, 216)" v-if="data.ta == true">
+                                  <a @click="refine(data)"> 细化 </a>
+                                  <a style="margin-left: 8px" @click="orientate(node, data)"> 定向 </a>
+                                </span>
+                              </span>
+                            </template>
+                          </el-tree>
+                        </el-scrollbar>
+                        <el-dialog v-model="visible" :title="`细化分类: ${dialogTitle}`" >
+                          <div style="display: flex; justify-content: space-between;">
+                            <span>根据特定品牌、价格范围、星级和Prime配送资格,细化分类</span>
+                            <span>
+                              <el-checkbox v-model="dialogForm.isCount" label="显示商品数量" />
+                            </span>
+                          </div>
+                          <el-form :model="dialogForm" :rules="dialogRules" ref="dialogFormRef" style="margin-top:20px">
+                            <el-form-item style="padding-left: 140px;">
+                              <span style="margin-right: 10px; color:#616266; font-weight: 500;">品牌</span>
+                              <el-select v-model="dialogForm.dialogselectValue" placeholder="请选择">
+                                <el-option v-for="item in dialogForm.dialogOptions" :key="item.value" :label="item.label" :value="item.value" />
+                              </el-select>
+                            </el-form-item>
+                            <el-form-item prop="prices" style="padding-left: 112px; margin-top: 10px;">
+                              <span style="margin-right: 10px; color:#616266; font-weight: 500;">价格范围</span>
+                              <el-input-number v-model="dialogForm.prices.lowest" :min="1" :controls="false" placeholder="无最低商品价格" />
+                              --
+                              <el-input-number v-model="dialogForm.prices.highest" :min="1" :controls="false" placeholder="无最高商品价格" />
+                            </el-form-item>
+                            <el-form-item prop="starRating" style="padding-left: 85px; margin-top: 10px;">
+                              <span style="margin-right: 15px; color:#616266; font-weight: 500;">查看星级评定</span>
+                              <el-slider v-model="dialogForm.starRating" range show-stops :max="5" :marks="marks" style="width: 70%;"/>
+                            </el-form-item>
+                            <el-form-item prop="delivery" style="padding-left: 140px; margin-top: 30px;">
+                              <span style="margin-right: 10px; color:#616266; font-weight: 500;">配送</span>
+                              <el-radio-group v-model="dialogForm.delivery">
+                                <el-radio label="all" style="font-weight: 400;">具备</el-radio>
+                                <el-radio label="eligible" style="font-weight: 400;">具备Prime资格</el-radio>
+                                <el-radio label="diseligible" style="font-weight: 400;">不具备Prime资格</el-radio>
+                              </el-radio-group>
+                            </el-form-item>
+                          </el-form>
+                          <template #footer>
+                            <div style="display: flex; justify-content: space-between;">
+                              <span v-loading="countLoadig">定位到的商品数量: {{ commodityCount[0]?.min }} - {{ commodityCount[0]?.max }}</span>
+                              <span class="dialog-footer">
+                                <el-button @click="visible = false">取消</el-button>
+                                <el-button type="primary" @click="dialogFormSubmit">确定</el-button>
+                              </span>
+                            </div>
+                          </template>
+                        </el-dialog>
                       </el-tab-pane>
                     </el-tabs>
                   </el-tab-pane>
@@ -711,6 +761,7 @@
 
 <script lang="ts" setup>
 import { onMounted, reactive, ref, computed, watch } from 'vue'
+import type { CSSProperties } from 'vue'
 import { useRoute } from 'vue-router'
 import type { FormInstance, FormRules, TabsPaneContext } from 'element-plus'
 import { useShopInfo } from '/@/stores/shopInfo'
@@ -861,9 +912,9 @@ function handleSizeChange(newSize) {
 
 // ------------------------------------------投放类型模块------------------------------------------
 async function changeTargetType() {
-  console.log(ruleForm.targetType)
+  // console.log(ruleForm.targetType)
   showCard.value = ruleForm.targetType === 'keyWords'
-  if(ruleForm.targetType === 'Goods') {
+  if (ruleForm.targetType === 'Goods') {
     productOrientationLoading.value = true
     await setProductOrientationData()
   }
@@ -887,6 +938,67 @@ const accurate = ref(false)
 const proposalTableData = ref([])
 const searchClassifyTableData = ref([])
 const productOrientationLoading = ref(false)
+const defaultProps = {
+  children: 'ch',
+  label: 'cna',
+}
+const countLoadig = ref(false)
+const visible = ref(false)
+let dialogTitle = ref('')
+let categoryId = ref('')
+const dialogselectValue = ref('')
+let dialogOptions: any = ref([])
+const dialogForm: any = reactive({
+  prices: {
+      lowest: undefined,
+      highest: undefined
+  },
+  starRating: [0,5],
+  dialogselectValue: [],
+  delivery: 'all',
+  isCount: false,
+})
+const dialogFormRef = ref()
+const dialogRules = reactive({
+  prices: [
+      { validator: validatePrices, trigger: 'blur' }
+    ]
+})
+
+interface Mark {
+  style: CSSProperties
+  label: string
+}
+type Marks = Record<number, Mark | string>
+const marks = reactive<Marks>({
+  0: '0',
+  1: '1',
+  2: '2',
+  3: '3',
+  4: '4',
+  5: '5',
+})
+let commodityCount = ref([])
+
+
+async function validatePrices(rule, value) {
+  if (value.highest !== '' && value.lowest !== '' && value.highest <= value.lowest) {
+    return Promise.reject('最高价格必须大于最低价格')
+  }
+  return Promise.resolve()
+}
+
+function dialogFormSubmit() {
+  dialogFormRef.value.validate((valid) => {
+    if (valid) {
+      console.log('表单提交')
+      visible.value = false
+    } else {
+      console.log('验证失败')
+    }
+  })
+}
+
 
 async function setProductOrientationData() {
   try {
@@ -898,15 +1010,72 @@ async function setProductOrientationData() {
       },
     })
     searchClassifyTableData.value = resp.data
-    console.log('searchClassifyTableData', searchClassifyTableData.value)
     productOrientationLoading.value = false
+  } catch (error) {
+    console.error('请求失败:', error)
+  }
+}
 
+async function setDialogOption() {
+  try {
+    const resp = await request({
+      url: '/api/ad_manage/categories/brands/',
+      method: 'GET',
+      params: {
+        profile_id: profile.value.profile_id,
+        category_id: categoryId.value,
+      },
+    })
+    const options = resp.data
+    dialogForm.dialogOptions = options.brands.map(brand => {
+      return {
+        label: brand.name,
+        value: brand.id
+      }
+    })
+    console.log('🚀 ~ setDialogOption ~ dialogOptions-->>', dialogOptions)
   } catch (error) {
-    console.error("请求失败:", error)
+    console.error('请求失败:', error)
   }
 }
 
 
+async function getCount() {
+  try {
+    const resp = await request({
+      url: '/api/ad_manage/products/count/',
+      method: 'POST',
+      data: {
+        profile_id: profile.value.profile_id,
+        category_id: categoryId.value,
+      },
+    })
+    commodityCount.value = resp.data.AsinCounts
+    countLoadig.value = false
+  } catch(error) {
+    console.error('请求失败:', error)
+  }
+}
+
+function refine(data) {
+  console.log('🚀 ~ refine ~ data-->>', data)
+  dialogTitle.value = data.cna
+  categoryId.value = data.cid
+  visible.value = true
+  setDialogOption()
+}
+
+function orientate(node, data) {
+}
+
+watch(() => dialogForm.isCount, (newValue, oldValue) => {
+    if (newValue === true) {
+      countLoadig.value = true
+      getCount()
+    } else {
+      commodityCount.value = []
+    }
+  })
 
 // ------------------------------------------关键词定向模块------------------------------------------
 const bidType = ref('customBid')
@@ -1455,4 +1624,19 @@ div {
 ::v-deep(.category-tabs .el-tabs__nav) {
   margin-left: 20px;
 }
+// el-tree自定义样式
+.custom-tree-node {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 14px;
+  padding-right: 8px;
+}
+/* 弹窗样式 */
+.dialog-head {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+}
 </style>

部分文件因为文件数量过多而无法显示