浏览代码

✨ feat: 广告管理<推广商品SP>: 顶部搜索popover中的Table父ASIN表格数据展示

WanGxC 1 年之前
父节点
当前提交
a2b71733fc

+ 3 - 1
src/views/adManage/sd/targets/index.vue

@@ -146,7 +146,9 @@ watch(
           {{ scope.row.suggestedBid_upper ? `$${scope.row.suggestedBid_upper}` : '--' }}
         </div>
       </template>
-      <template #cell_MissedImpressions="scope"> {{ scope.row.MissedImpressionsLower ?? '0' }} ~ {{ scope.row.MissedImpressionsUpper ?? '0' }} </template>
+      <template #cell_MissedImpressions="scope">
+        {{ scope.row.MissedImpressionsLower ?? '0' }} ~ {{ scope.row.MissedImpressionsUpper ?? '0' }}
+      </template>
       <template #cell_MissedClicks="scope"> {{ scope.row.MissedClicksLower ?? '0' }} ~ {{ scope.row.MissedClicksUpper ?? '0' }}</template>
       <template #cell_MissedSales="scope"> {{ scope.row.MissedSalesLower ?? '0' }} ~ {{ scope.row.MissedSalesUpper ?? '0' }}</template>
 

+ 0 - 51
src/views/adManage/sp/TopFilter/PopoverFilter/InfinityList/index.vue

@@ -1,51 +0,0 @@
-<script setup lang="ts">
-import { reactive } from 'vue'
-
-const gridOptions = <any>reactive({
-  height: 500,
-  align: null,
-  columns: [
-    { type: 'checkbox', width: 60 },
-    { field: 'name', title: 'name' },
-  ],
-  data: [
-    { id: 10001, name: 'Test1', nickname: 'T1', role: 'Develop', sex: 'Man', age: 28, address: 'Shenzhen' },
-    { id: 10002, name: 'Test2', nickname: 'T2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
-  ],
-})
-
-const gridOptionsRight = <any>reactive({
-  height: 500,
-  align: null,
-  columns: [
-    { type: 'checkbox', width: 60 },
-    { field: 'name', title: 'name', width: '300' },
-    { field: 'role', title: 'role', width: '300' },
-    { field: 'sex', title: 'sex', width: '300' },
-    { field: 'age', title: 'age', width: '300' },
-    { field: 'address', title: 'address', width: '300' },
-  ],
-  data: [
-    { id: 10001, name: 'Test1', nickname: 'T1', role: 'Develop', sex: 'Man', age: 28, address: 'Shenzhen' },
-    { id: 10002, name: 'Test2', nickname: 'T2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
-    { id: 10002, name: 'Test2', nickname: 'T2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
-  ],
-})
-</script>
-
-<template>
-  <div class="flex">
-    <vxe-grid
-      v-bind="gridOptions"
-      class="ml-2 mb-2 mt-0 border border-r-0 rounded-bl-md rounded-tl-md overflow-hidden"
-      style="flex: 0 1 260px"></vxe-grid>
-    <vxe-grid v-bind="gridOptionsRight" class="mr-2 mb-2 mt-0 border rounded-br-md rounded-tr-md overflow-hidden w-0" style="flex: 2 1 0"> </vxe-grid>
-  </div>
-</template>
-
-<style scoped>
-/* 移除默认边框 */
-:deep(.vxe-table--render-default .vxe-table--border-line) {
-  border: none;
-}
-</style>

+ 9 - 2
src/views/adManage/sp/TopFilter/api.ts

@@ -5,13 +5,20 @@ export const apiPrefix = '/api/ad_manage/sp/search'
 export function getProductSelect() {
   return request({
     url: apiPrefix + '/item',
-    method: 'GET',
+    method: 'get',
   })
 }
 export function getProductline(query) {
   return request({
     url: '/api/sellers/productline/',
-    method: 'GET',
+    method: 'get',
     params: query,
   })
 }
+export function getParentAsin(body) {
+  return request({
+    url: apiPrefix + '/pasin',
+    method: 'post',
+    data: body,
+  })
+}

+ 137 - 0
src/views/adManage/sp/TopFilter/components/PopoverFilter/InfinityList/index.vue

@@ -0,0 +1,137 @@
+<script setup lang="ts">
+import { Ref, inject, onMounted, reactive } from 'vue'
+import { getParentAsin } from '/@/views/adManage/sp/TopFilter/api'
+import { Connection, Picture as IconPicture } from '@element-plus/icons-vue'
+
+const profile = <Ref>inject('profile')
+
+const gridOptions = <any>reactive({
+  height: 500,
+  align: null,
+  columns: [
+    { type: 'checkbox', width: 30 },
+    { field: 'parentAsin', title: '父ASIN', slots: { default: 'parentAsin_default' } },
+  ],
+  data: [],
+})
+
+const gridOptionsRight = <any>reactive({
+  height: 500,
+  align: null,
+  columns: [
+    { type: 'checkbox', width: 30 },
+    { field: 'name', title: 'name', width: '300' },
+    { field: 'role', title: 'role', width: '300' },
+    { field: 'sex', title: 'sex', width: '300' },
+    { field: 'age', title: 'age', width: '300' },
+    { field: 'address', title: 'address', width: '300' },
+  ],
+  data: [
+    { id: 10001, name: 'Test1', nickname: 'T1', role: 'Develop', sex: 'Man', age: 28, address: 'Shenzhen' },
+    { id: 10002, name: 'Test2', nickname: 'T2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
+    { id: 10003, name: 'Test3', nickname: 'T3', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
+  ],
+})
+
+async function fetchParentAsin() {
+  const body = { profileId: profile.value.profile_id }
+  try {
+    const response = await getParentAsin(body)
+    gridOptions.data = response.data
+  } catch (error) {
+    console.log('error:', error)
+  }
+}
+
+function changeheaderCellStyle(value) {
+  return {
+    // backgroundColor: '#eef0f7',
+    padding: '3px',
+  }
+}
+
+onMounted(() => {
+  fetchParentAsin()
+})
+</script>
+
+<template>
+  <div class="flex">
+    <vxe-grid
+      v-bind="gridOptions"
+      :header-row-style="changeheaderCellStyle"
+      :header-cell-style="changeheaderCellStyle"
+      class="ml-2 mb-2 mt-0 border border-r-0 rounded-bl-md rounded-tl-md overflow-hidden"
+      style="flex: 0 1 260px">
+      <template #parentAsin_default="{ row }">
+        <div style="display: flex">
+          <el-image class="w-14 h-14 mr-1 border rounded" v-if="row.Image" :src="row.Image" alt="" fit="contain" />
+          <el-image v-else class="w-12 h-12 mr-1 border rounded">
+            <template #error>
+              <div class="image-slot">
+                <el-icon><icon-picture /></el-icon>
+              </div>
+            </template>
+          </el-image>
+
+          <div class="flex flex-col justify-center">
+            <div class="font-medium text-black">{{ row.parentAsin }}</div>
+            <div>
+              ASIN:<span class="text-black">{{ row.asinNum }}</span>
+              <el-link
+                :href="row.amazonUrl"
+                target="_blank"
+                :disabled="!row.amazonUrl"
+                :underline="false"
+                :icon="Connection"
+                :style="{ marginLeft: '2px', marginBottom: '2px', color: row.amazonUrl ? '#3a83f7' : '#c0c4cc' }">
+              </el-link>
+              <span class="text-gray-300 mx-1">|</span>
+              SKU:<span class="text-black">{{ row.skuNum }}</span>
+            </div>
+          </div>
+        </div>
+      </template>
+    </vxe-grid>
+    <vxe-grid
+      v-bind="gridOptionsRight"
+      :header-cell-style="changeheaderCellStyle"
+      class="mr-2 mb-2 mt-0 border rounded-br-md rounded-tr-md overflow-hidden w-0"
+      style="flex: 2 1 0">
+    </vxe-grid>
+  </div>
+</template>
+
+<style scoped>
+/* 移除默认边框 */
+:deep(.vxe-table--render-default .vxe-table--border-line) {
+  border: none;
+}
+.img-part {
+  width: 65px;
+  height: 65px;
+  margin: 0 5px 0 0;
+  border: 1px solid #e5e6eb;
+  border-radius: 4px;
+}
+.image-slot {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 65px;
+  height: 65px;
+  background: var(--el-fill-color-light);
+  color: var(--el-text-color-secondary);
+  font-size: 30px;
+}
+.image-slot .el-icon {
+  font-size: 30px;
+}
+.custom-bg {
+  background-color: black;
+}
+/* 修改表头填充颜色 默认会有空隙 */
+:deep(.vxe-table--header-wrapper.body--wrapper) {
+  background-color: #eef0f7;
+}
+</style>

+ 5 - 4
src/views/adManage/sp/TopFilter/PopoverFilter/index.vue → src/views/adManage/sp/TopFilter/components/PopoverFilter/index.vue

@@ -1,15 +1,16 @@
 <script setup lang="ts">
 import { Search } from '@element-plus/icons-vue'
 import { Ref, inject, onMounted, ref } from 'vue'
-import { getProductline } from '../api'
+import { getProductline } from '../../api'
 import InfinityList from './InfinityList/index.vue'
 
 const profile = <Ref>inject('profile')
 
 const activeName = ref('search')
 const searchInput = ref('')
-const options = ref([])
+const options = <any>ref([])
 const textarea = ref('')
+const productLineSelect = ref('')
 
 async function fetchProductLine() {
   try {
@@ -32,7 +33,7 @@ onMounted(() => {
         <el-tab-pane label="搜索" name="search">
           <div class="flex gap-1 p-2">
             <el-input v-model="searchInput" placeholder="输入产品标题/父ASIN/ASIN查询" :prefix-icon="Search" style="width: 360px" />
-            <el-select>
+            <el-select v-model="productLineSelect" multiple collapse-tags>
               <el-option v-for="item in options" :key="item.productlineId" :label="item.productlineName" :value="item.productlineId" />
             </el-select>
             <el-select></el-select>
@@ -52,7 +53,7 @@ onMounted(() => {
 
 <style scoped>
 /* Tab栏 */
-::v-deep(.el-tabs__nav-scroll) {
+:deep(.el-tabs__nav-scroll) {
   overflow: hidden;
   margin-left: 10px;
 }

+ 59 - 0
src/views/adManage/sp/TopFilter/components/PopoverFilterParent/index.vue

@@ -0,0 +1,59 @@
+<script setup lang="ts">
+import { Search } from '@element-plus/icons-vue'
+import { Ref, inject, onMounted, ref } from 'vue'
+import { getProductline } from '../../api'
+// import InfinityList from './InfinityList/index.vue'
+
+const profile = <Ref>inject('profile')
+
+const activeName = ref('search')
+const searchInput = ref('')
+const options = <any>ref([])
+const textarea = ref('')
+
+async function fetchProductLine() {
+  try {
+    const response = await getProductline({ profileId: profile.value.profile_id })
+    options.value = response.data
+  } catch (error) {
+    console.log('error:', error)
+  }
+}
+
+onMounted(() => {
+  fetchProductLine()
+})
+</script>
+
+<template>
+  <div class="flex justify-between border border-solid border-inherit rounded-md">
+    <div style="flex: 2 1 0; border-right: 1px solid #e6e6e6">
+      <el-tabs v-model="activeName" class="demo-tabs">
+        <el-tab-pane label="搜索" name="search">
+          <div class="flex gap-1 p-2">
+            <el-input v-model="searchInput" placeholder="输入产品标题/父ASIN/ASIN查询" :prefix-icon="Search" style="width: 360px" />
+            <el-select>
+              <el-option v-for="item in options" :key="item.productlineId" :label="item.productlineName" :value="item.productlineId" />
+            </el-select>
+            <el-select></el-select>
+          </div>
+          <!-- <InfinityList></InfinityList> -->
+        </el-tab-pane>
+        <el-tab-pane label="输入" name="input" class="w-full p-2">
+          <el-input v-model="textarea" :autosize="{ minRows: 10, maxRows: 100 }" type="textarea" placeholder="Please input" />
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+    <div style="flex: 1 1 0">
+      <div class="h-10" style="background-color: #edf0f8">已添加:</div>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+/* Tab栏 */
+:deep(.el-tabs__nav-scroll) {
+  overflow: hidden;
+  margin-left: 10px;
+}
+</style>

+ 24 - 6
src/views/adManage/sp/TopFilter/index.vue

@@ -1,8 +1,10 @@
 <script setup lang="ts">
-import {onMounted, ref} from 'vue'
-import PopoverFilter from './PopoverFilter/index.vue'
-import {getProductSelect} from './api'
-import {CloseBold} from '@element-plus/icons-vue'
+import { CloseBold } from '@element-plus/icons-vue'
+import { computed, onMounted, ref } from 'vue'
+import PopoverFilter from './components/PopoverFilter/index.vue'
+import PopoverFilterParent from './components/PopoverFilterParent/index.vue'
+import { getProductSelect } from './api'
+
 
 const isVisible = ref(false)
 
@@ -20,6 +22,18 @@ async function fetchProductSelect() {
   }
 }
 
+const currentComponent = computed(() => {
+  switch (productFilterSelect.value) {
+    case 'PASIN':
+      return PopoverFilterParent
+    case 'SKU':
+    case 'ASIN':
+      return PopoverFilter
+    default:
+      return null // 或者是一个默认的组件
+  }
+})
+
 onMounted(() => {
   fetchProductSelect()
 })
@@ -38,12 +52,16 @@ onMounted(() => {
         </el-input>
       </template>
       <div class="flex justify-between">
-        <div class="pb-3 font-bold text-slate-950 text-base">切换商品</div>
+        <div class="pb-3 font-bold text-slate-950 text-base">搜索</div>
         <el-icon class="cursor-pointer" @click="isVisible = false">
           <CloseBold/>
         </el-icon>
       </div>
-      <PopoverFilter></PopoverFilter>
+      <component :is="currentComponent"></component>
+      <div class="flex justify-end mt-2">
+        <el-button>取消</el-button>
+        <el-button type="primary" color="#3c58af">应用</el-button>
+      </div>
     </el-popover>
   </div>
 </template>