Просмотр исходного кода

Merge branch 'xinyan' into test

# Conflicts:
#	src/views/demo/index.vue
xinyan 8 месяцев назад
Родитель
Сommit
c88b78f3ba

+ 589 - 11
src/views/demo/index.vue

@@ -1,20 +1,598 @@
-<template>
-  <el-button :loading="loading" v-bind="props" @click="handleClick"><slot>z</slot></el-button>
-</template>
-
 <script lang="ts" setup>
-import { ref } from 'vue';
-import type { ButtonProps } from 'element-plus';
+/**
+ * @Name: adActivityDialog.vue
+ * @Description:广告关联活动弹窗
+ * @Author: xinyan
+ */
+import { computed, onMounted, ref, watch } from 'vue';
+import { getAdGroupList, getRelationCampaign } from '/@/views/efTools/automation/api';
+import { storeToRefs } from 'pinia';
+import { useShopInfo } from '/@/stores/shopInfo';
+import { ElMessage } from 'element-plus';
+import TargetRuleDialog from '/@/views/efTools/automation/components/targetRuleDialog.vue';
+
+const props = defineProps({
+  templateId: {
+    type: [String, Number],
+    required: true,
+  },
+  activeModel: {
+    type: String,
+  },
+  modelValue: {
+    type: Boolean,
+    required: true,
+  },
+});
+const emits = defineEmits(['update:modelValue']);
+const shopInfo = useShopInfo();
+const { profile } = storeToRefs(shopInfo);
+const { templateId } = toRefs(props);
+// const { activeModel } = toRefs(props);
+const activeModel = ref('specified');
+
+const dialogVisible = ref(true);
+const targetRuleDialogVisible = ref(false);
 
+// 定向规则
+//const adGroupId = ref('')
+//const campaignId = ref('')
+const selectedTargetedRow = ref(null);
+
+// 筛选条件
+const searchAdCampaign = ref('');
+const selectedCampaignType = ref('sp');
+const selectedAdGroup = ref('');
+const selectedStatus = ref('');
+
+const adCampaignName = ref([]);
+const campaignType = [
+  { value: 'sb', label: 'SB' },
+  { value: 'sp', label: 'SP' },
+  { value: 'sd', label: 'SD' },
+];
+const adGroups = ref([]);
+const campaignStatus = [
+  { value: 0, label: '未存档' },
+  { value: 'ENABLED', label: '已启用' },
+  { value: 'PAUSED', label: '已暂停' },
+];
+
+// 表格
+const currentPage = ref(1);
+const pageSize = ref(25);
+const total = ref(0);
 
 const loading = ref(false);
-const props = defineProps<Partial<Omit<ButtonProps, 'loading'>>>();
+const refTable = ref(null);
+let selectedAds = ref([]);
+let selections = []; // 添加选中的项
 
-function handleClick() {
+function handleCurrentChange(newPage) {
+  currentPage.value = newPage;
   loading.value = true;
-  console.log('props.disabled=> ', props);
-  setTimeout(() => {
+  fetchAdCampaign();
+}
+
+// 处理分页器每页显示条目数变化
+function handleSizeChange(newSize) {
+  pageSize.value = newSize;
+  currentPage.value = 1;
+  fetchAdCampaign();
+}
+
+let isRestoringSelection = false;
+
+async function fetchAdCampaign() {
+  try {
+    loading.value = true;
+    const cachedSelectedAds = [...selectedAds.value];
+    const resp = await getRelationCampaign({
+      profileId: profile.value.profile_id,
+      templateId: 51,
+      campaignName: searchAdCampaign.value,
+      portfolioId: selectedAdGroup.value,
+      campaignStatus: selectedStatus.value,
+      campaignType: selectedCampaignType.value,
+      page: currentPage.value,
+      limit: pageSize.value,
+    });
+    adCampaignName.value = resp.data;
+    total.value = resp.total;
+    currentPage.value = resp.page;
+    // 开始恢复勾选状态
+    isRestoringSelection = true;
+    nextTick(() => {
+      adCampaignName.value.forEach(item => {
+        if (cachedSelectedAds.some(ad => ad.campaignId === item.campaignId)) {
+          refTable.value.toggleRowSelection(item, true);
+        }
+      });
+      isRestoringSelection = false;
+    });
+  } catch (error) {
+    ElMessage.error('请求广告活动数据失败');
+  } finally {
     loading.value = false;
-  }, 2000);
+  }
 }
+
+function handleSelectionChange(selection) {
+  if (isRestoringSelection) return;
+
+  const newSelectedAds = [];
+
+  selection.forEach(item => {
+    if (item.campaignGroupInfo) {
+      // 这是父节点(广告活动)
+      newSelectedAds.push({
+        campaignId: item.campaignId,
+        campaignName: item.campaignName,
+        campaignType: item.campaignType,
+        isParent: true
+      });
+    } else {
+      // 这是子节点(广告组)
+      const parent = adCampaignName.value.find(ad =>
+          ad.campaignGroupInfo && ad.campaignGroupInfo.some(group => group.adGroupId === item.adGroupId)
+      );
+      if (parent) {
+        // 添加父节点(如果还没有添加)
+        if (!newSelectedAds.some(ad => ad.campaignId === parent.campaignId)) {
+          newSelectedAds.push({
+            campaignId: parent.campaignId,
+            campaignName: parent.campaignName,
+            campaignType: parent.campaignType,
+            isParent: true
+          });
+        }
+        // 添加子节点(广告组)
+        newSelectedAds.push({
+          adGroupId: item.adGroupId,
+          adGroupName: item.adGroupName,
+          parentCampaignId: parent.campaignId,
+          parentCampaignName: parent.campaignName,
+          campaignType: parent.campaignType
+        });
+      }
+    }
+  });
+  selectedAds.value = newSelectedAds;
+}
+
+const groupedSelectedAds = computed(() => {
+  const groups = {};
+  selectedAds.value.forEach(ad => {
+    if (ad.isParent) {
+      if (!groups[ad.campaignId]) {
+        groups[ad.campaignId] = {
+          id: ad.campaignId,
+          name: ad.campaignName,
+          campaignType: ad.campaignType,
+          campaignGroupInfo: []
+        };
+      }
+    } else {
+      if (!groups[ad.parentCampaignId]) {
+        groups[ad.parentCampaignId] = {
+          id: ad.parentCampaignId,
+          name: ad.parentCampaignName,
+          campaignType: ad.campaignType,
+          campaignGroupInfo: []
+        };
+      }
+      groups[ad.parentCampaignId].campaignGroupInfo.push({
+        id: ad.adGroupId,
+        name: ad.adGroupName
+      });
+    }
+  });
+  return Object.values(groups);
+});
+
+function removeSelectedAd(index) {
+  const removedAd = selectedAds.value.splice(index, 1)[0];
+
+  if (removedAd.parentCampaignId) {
+    // 查找同一父节点下的其他子节点
+    const remainingChildren = selectedAds.value.filter(ad => ad.parentCampaignId === removedAd.parentCampaignId);
+
+    // 如果父节点下还有其他子节点,父节点不删除
+    if (remainingChildren.length > 0) {
+      // 取消表格1中该子节点的勾选
+      const targetParent = adCampaignName.value.find(ad => ad.campaignId === removedAd.parentCampaignId);
+      if (targetParent) {
+        const targetChildIndex = targetParent.campaignGroupInfo.findIndex(group => group.adGroupId === removedAd.adGroupId);
+        if (targetChildIndex !== -1) {
+          const adTable = refTable.value;
+          adTable.toggleRowSelection(targetParent.campaignGroupInfo[targetChildIndex], false);
+        }
+      }
+    } else {
+      // 如果没有其他子节点了,移除父节点
+      const parentIndex = selectedAds.value.findIndex(ad => ad.campaignId === removedAd.parentCampaignId);
+      if (parentIndex !== -1) {
+        selectedAds.value.splice(parentIndex, 1);
+      }
+
+      // 取消表格1中父节点的勾选
+      const parentIndexInTable = adCampaignName.value.findIndex(ad => ad.campaignId === removedAd.parentCampaignId);
+      if (parentIndexInTable !== -1) {
+        const adTable = refTable.value;
+        adTable.toggleRowSelection(adCampaignName.value[parentIndexInTable], false);
+      }
+    }
+  } else {
+    // 如果删除的项是父节点
+    const targetIndex = adCampaignName.value.findIndex(ad => ad.campaignId === removedAd.campaignId);
+    if (targetIndex !== -1) {
+      const adTable = refTable.value;
+      adTable.toggleRowSelection(adCampaignName.value[targetIndex], false);
+    }
+  }
+}
+
+function removeAllSelectedAds() {
+  selectedAds.value = [];
+  const adTable = refTable.value;
+  adTable.clearSelection();
+}
+
+function cancel() {
+  dialogVisible.value = false;
+}
+
+//TODO: 确认按钮
+async function confirm() {
+  const campaignItems = selectedAds.value.map(ad => ({
+    campaignId: ad.campaignId,
+    campaignType: ad.campaignType
+  }));
+  const adGroupInfo = [];
+  const campaignTargetInfo = [
+    { targetId: '492707808377423', adGroup_id: '448117369011017', bid: 0.45 },
+  ];
+  const campaignKeywordInfo = [
+    { keywordId: '416969576305724', adGroup_id: '393554556566271', bid: 0.04 },
+  ];
+
+  const requestData = {
+    profileId: profile.value.profile_id,
+    templateId: templateId.value,
+    campaignItems,
+    adGroupInfo,
+    campaignTargetInfo,
+    campaignKeywordInfo
+  };
+  //console.log('requestData', requestData);
+}
+
+// 获取广告组下拉框
+async function fetchAdGroupList() {
+  try {
+    const resp = await getAdGroupList({
+      profileId: profile.value.profile_id,
+    });
+    adGroups.value = resp.data.map((item: any) => {
+      return {
+        label: item.name,
+        value: item.portfolioId
+      };
+    });
+  } catch (error) {
+    ElMessage.error('请求失败');
+  }
+}
+
+function handleSelectTarget(row) {
+  console.log("=>(adActivityDialog.vue:287) row", row);
+  // 获取父节点数据
+  const parent = adCampaignName.value.find(ad =>
+      ad.campaignGroupInfo && ad.campaignGroupInfo.some(group => group.adGroupId === row.adGroupId)
+  );
+
+  if (parent) {
+    // 构造包含父节点和子节点的数据对象
+    selectedTargetedRow.value = {
+      campaignId: parent.campaignId,
+      campaignName: parent.campaignName,
+      campaignType: parent.campaignType,
+      adGroupId: row.adGroupId,
+      adGroupName: row.adGroupName,
+      isSelected: row.isSelected || false, // 同步 isSelected 状态
+    };
+  }
+
+  targetRuleDialogVisible.value = true;
+}
+
+function handleConfirm(campaignKeywordInfo) {
+  selectedTargetedRow.value.keywordInfo = campaignKeywordInfo;
+  selectedTargetedRow.value.isSelected = true;
+
+  // 更新子节点状态
+  const parent = adCampaignName.value.find(ad =>
+      ad.campaignGroupInfo && ad.campaignGroupInfo.some(group => group.adGroupId === selectedTargetedRow.value.adGroupId)
+  );
+  console.log("=>(adActivityDialog.vue:306) parent", parent);
+
+  if (parent) {
+    const group = parent.campaignGroupInfo.find(group => group.adGroupId === selectedTargetedRow.value.adGroupId);
+    if (group) {
+      group.isSelected = true; // 更新子节点的 isSelected 状态
+    }
+  }
+
+  // 勾选子节点行
+  const table = refTable.value;
+  const targetRow = parent.campaignGroupInfo.find(group => group.adGroupId === selectedTargetedRow.value.adGroupId);
+
+  if (table && targetRow) {
+    table.toggleRowSelection(targetRow, true); // 勾选目标子节点行
+  }
+}
+
+const headerCellStyle = (args) => {
+  if (args.rowIndex === 0) {
+    return {
+      backgroundColor: 'rgba(245, 245, 245, 0.9)',
+      fontWeight: '500',
+    };
+  }
+};
+
+const cellStyle = () => {
+  return {
+    fontSize: '13px',
+    //fontWeight: '500',
+  };
+};
+
+//监控筛选条件变化
+watch(selectedCampaignType, () => {
+  fetchAdCampaign();
+});
+
+watch(selectedAdGroup, (newVal) => {
+  if (newVal) {
+    selectedAdGroup.value = newVal;
+    fetchAdCampaign();
+  }
+});
+
+watch(selectedStatus, () => {
+  fetchAdCampaign();
+});
+
+watch(templateId, () => {
+  fetchAdCampaign();
+  fetchAdGroupList();
+});
+
+watch(() => props.modelValue, (newValue) => {
+  dialogVisible.value = newValue;
+});
+
+watch(dialogVisible, (newValue) => {
+  emits('update:modelValue', newValue);
+});
+
+const treeProps = computed(() => {
+  if (activeModel.value === 'adGroup' || activeModel.value === 'specified') {
+    return {
+      children: 'campaignGroupInfo',
+      checkStrictly: false
+    };
+  }
+  return {};
+});
+
+onMounted(() => {
+  fetchAdGroupList();
+  fetchAdCampaign()
+});
+
 </script>
+
+<template>
+  <el-dialog
+      v-model="dialogVisible"
+      style="border-radius: 10px;"
+      title="关联广告活动"
+      width="1158px"
+  >
+    <div class="container">
+      <div class="container-left">
+        <el-input v-model="searchAdCampaign" clearable placeholder="请输入广告活动" style="width: 100%;"
+                  @change="fetchAdCampaign()"></el-input>
+        <div class="custom-inline">
+          <el-select v-model="selectedCampaignType" placeholder="选择广告类型">
+            <el-option v-for="item in campaignType"
+                       :key="item.value"
+                       :label="item.label"
+                       :value="item.value"
+            ></el-option>
+          </el-select>
+
+          <el-select v-model="selectedAdGroup" clearable placeholder="广告组合" style="margin-bottom: 10px;">
+            <el-option
+                v-for="item in adGroups"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+            ></el-option>
+          </el-select>
+
+          <el-select v-model="selectedStatus" placeholder="状态" style="margin-bottom: 10px;">
+            <el-option
+                v-for="item in campaignStatus"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+            ></el-option>
+          </el-select>
+        </div>
+        <el-table
+            ref="refTable"
+            v-loading="loading"
+            :cell-style="cellStyle"
+            :data="adCampaignName"
+            :header-cell-style="headerCellStyle"
+            :row-key="'adGroupId'"
+            :tree-props="treeProps"
+            height="400"
+            style="width: 100%;"
+            @selection-change="handleSelectionChange"
+        >
+          <el-table-column label="广告活动名称">
+            <template #default="scope">
+              <el-tag
+                  v-if="scope.row.campaignType"
+                  :color="scope.row.campaignType === 'sb' ? '#0163d2' : (scope.row.campaignType === 'sp' ? '#ff7424' : '#365672')"
+                  class="campaign-type"
+                  disable-transitions
+                  round>
+                {{ scope.row.campaignType }}
+              </el-tag>
+              {{ scope.row.campaignName }}
+              {{ scope.row.adGroupName }}
+              <el-button
+                  v-if="scope.row.adGroupName && activeModel==='specified'&&!scope.row.isSelected"
+                  class="btn-link"
+                  link
+                  @click="handleSelectTarget(scope.row)">
+                选择定向
+              </el-button>
+              <span v-else-if="scope.row.adGroupName">已选择</span>
+            </template>
+          </el-table-column>
+          <el-table-column type="selection" width="55"></el-table-column>
+        </el-table>
+        <div class="pagination-container mt-4">
+          <el-pagination
+              v-model:current-page="currentPage"
+              :page-size="pageSize"
+              :page-sizes="[10, 25, 50,100,200]"
+              :total="total"
+              background
+              layout="total,sizes,prev, next, jumper"
+              small
+              @size-change="handleSizeChange"
+              @current-change="handleCurrentChange"
+          />
+        </div>
+      </div>
+      <div class="container-right">
+        <h3>已选择({{ selectedAds.length }})</h3>
+        <el-table
+            :cell-style="cellStyle"
+            :data="groupedSelectedAds"
+            :header-cell-style="headerCellStyle"
+            :row-key="'id'"
+            :tree-props="treeProps"
+            height="484"
+            style="width: 100%; margin-top: 20px;"
+            v-bind="activeModel === 'adGroup' || activeModel === 'specified' ? treeProps : {}"
+        >
+          <el-table-column label="广告活动" prop="name">
+            <template #default="scope">
+              <el-tag
+                  v-if="scope.row.campaignType"
+                  :color="scope.row.campaignType === 'sb' ? '#0163d2' : (scope.row.campaignType === 'sp' ? '#ff7424' : '#365672')"
+                  class="campaign-type"
+                  disable-transitions
+                  round>
+                {{ scope.row.campaignType }}
+              </el-tag>
+              {{ scope.row.campaignName }}
+              {{ scope.row.name }}
+            </template>
+          </el-table-column>
+          <el-table-column
+              align="center"
+              label="操作"
+              width="100"
+          >
+            <template #header>
+              <el-button link size="default" style="color: #2077d7" @click="removeAllSelectedAds">删除全部</el-button>
+            </template>
+            <template #default="scope">
+              <el-button type="text" @click="removeSelectedAd(scope.$index)">
+                <CircleClose style="width:16px;color:#4b5765" />
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </div>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="cancel">取消</el-button>
+        <el-button type="primary" @click="confirm">确定</el-button>
+      </div>
+    </template>
+  </el-dialog>
+  <TargetRuleDialog v-if="activeModel === 'specified'"
+                    v-model="targetRuleDialogVisible"
+                    :selectedTargetedRow="selectedTargetedRow"
+                    @confirm:targetRule="handleConfirm"
+  ></TargetRuleDialog>
+</template>
+
+<style scoped>
+.pagination-container {
+  display: flex;
+  flex-direction: row-reverse;
+}
+
+.custom-inline {
+  display: flex;
+  justify-content: space-around;
+  margin: 12px 0;
+  gap: 4px;
+}
+
+.campaign-type {
+  width: 35px;
+  text-align: center;
+  height: 22px;
+  font-size: 13px;
+  font-weight: 400;
+  color: #fff;
+  border-color: #fff;
+  line-height: 22px;
+  border-radius: 12px;
+  margin-right: 4px;
+}
+
+.container {
+  width: 100%;
+  height: 100%;
+  border: 1px solid #d6dbe2;
+  border-radius: 4px;
+  display: flex;
+  overflow: hidden;
+  align-content: center;
+  flex-wrap: nowrap;
+  flex-direction: row;
+  /* padding: 10px; */
+}
+
+.container-left {
+  width: 50%;
+  border-right: 1px solid #d6dbe2;
+  padding: 15px
+}
+
+.container-right {
+  flex: 1;
+  padding: 15px
+}
+
+.btn-link {
+  font-size: 13px;
+  color: #0085ff;
+  /* ling-heigt: 23px; */
+}
+
+</style>

+ 10 - 0
src/views/efTools/automation/api.ts

@@ -78,3 +78,13 @@ export function getTargetingRuleList(query) {
   });
 }
 
+export function getProductsList(query) {
+  return request({
+    url: '/api/ad_manage/template/target_select/products/',
+    method: 'GET',
+    params: query,
+  });
+}
+
+
+

+ 277 - 256
src/views/efTools/automation/components/adActivityDialog.vue

@@ -10,6 +10,8 @@ import { storeToRefs } from 'pinia';
 import { useShopInfo } from '/@/stores/shopInfo';
 import { ElMessage } from 'element-plus';
 import TargetRuleDialog from '/@/views/efTools/automation/components/targetRuleDialog.vue';
+import { DocumentAdd } from '@element-plus/icons-vue';
+
 
 const props = defineProps({
   templateId: {
@@ -28,15 +30,18 @@ const emits = defineEmits(['update:modelValue']);
 const shopInfo = useShopInfo();
 const { profile } = storeToRefs(shopInfo);
 const { templateId } = toRefs(props);
-const { activeModel } = toRefs(props);
+// const { activeModel } = toRefs(props);
+const activeModel = ref('specified');
 
-const dialogVisible = ref(props.modelValue);
+const dialogVisible = ref(true);
 const targetRuleDialogVisible = ref(false);
 
 // 定向规则
 //const adGroupId = ref('')
 //const campaignId = ref('')
 const selectedTargetedRow = ref(null);
+const targetLength = ref(0);
+let selectedGroups = [];
 
 // 筛选条件
 const searchAdCampaign = ref('');
@@ -56,16 +61,63 @@ const campaignStatus = [
   { value: 'ENABLED', label: '已启用' },
   { value: 'PAUSED', label: '已暂停' },
 ];
-
 // 表格
 const currentPage = ref(1);
 const pageSize = ref(25);
 const total = ref(0);
 
 const loading = ref(false);
-const refTable = ref(null);
+const xGridOne = ref(null);
+const xGridTwo = ref(null);
 let selectedAds = ref([]);
-let selections = []; // 添加选中的项
+
+const selectedColumns = computed(() => [
+  {
+    field: 'campaignName',
+    title: '广告活动',
+    slots: { default: 'campaignName_default' },
+    treeNode: activeModel.value == 'specified' || activeModel.value == 'adGroup'
+  },
+  { title: '操作', width: 100, align: 'center', slots: { header: 'header_operation', default: 'default_operation' } }
+]);
+
+const treeProps = computed(() => {
+  activeModel.value = 'specified';
+
+  if (activeModel.value === 'adGroup' || activeModel.value === 'specified') {
+    return {
+      rowField: 'campaignId',
+      childrenField: 'campaignGroupInfo',  // 子节点字段
+      expandAll: true,
+    };
+  }
+  return {};
+});
+
+const gridOptions = reactive({
+  border: 'inner',
+  height: 500,
+  rowConfig: {
+    isHover: true,
+    keyField: 'campaignId',
+  },
+  treeConfig: treeProps,
+  checkboxConfig: {
+    labelField: 'name',
+    reserve: true,
+    checkStrictly: false,
+  },
+  columns: computed(() => [
+    {
+      field: 'campaignName',
+      title: '广告活动',
+      slots: { default: 'campaignName_default' },
+      treeNode: activeModel.value == 'specified' || activeModel.value == 'adGroup'
+    },
+    { type: 'checkbox', width: 55, fixed: 'right' },
+  ]),
+  data: []
+});
 
 function handleCurrentChange(newPage) {
   currentPage.value = newPage;
@@ -80,15 +132,22 @@ function handleSizeChange(newSize) {
   fetchAdCampaign();
 }
 
-let isRestoringSelection = false;
+function handleAdCampaignChange() {
+  localStorage.setItem('searchAdCampaign', JSON.stringify(searchAdCampaign.value));
+  fetchAdCampaign();
+}
 
 async function fetchAdCampaign() {
+  const savedAdCampaign = localStorage.getItem('searchAdCampaign');
+  if (savedAdCampaign) {
+    searchAdCampaign.value = JSON.parse(savedAdCampaign);
+  }
   try {
     loading.value = true;
     const cachedSelectedAds = [...selectedAds.value];
     const resp = await getRelationCampaign({
       profileId: profile.value.profile_id,
-      templateId: templateId.value,
+      templateId: 51,
       campaignName: searchAdCampaign.value,
       portfolioId: selectedAdGroup.value,
       campaignStatus: selectedStatus.value,
@@ -96,19 +155,9 @@ async function fetchAdCampaign() {
       page: currentPage.value,
       limit: pageSize.value,
     });
-    adCampaignName.value = resp.data;
+    gridOptions.data = resp.data;
     total.value = resp.total;
     currentPage.value = resp.page;
-    // 开始恢复勾选状态
-    isRestoringSelection = true;
-    nextTick(() => {
-      adCampaignName.value.forEach(item => {
-        if (cachedSelectedAds.some(ad => ad.campaignId === item.campaignId)) {
-          refTable.value.toggleRowSelection(item, true);
-        }
-      });
-      isRestoringSelection = false;
-    });
   } catch (error) {
     ElMessage.error('请求广告活动数据失败');
   } finally {
@@ -116,132 +165,154 @@ async function fetchAdCampaign() {
   }
 }
 
-function handleSelectionChange(selection) {
-  if (isRestoringSelection) return;
+const handleGridChange = (event) => {
+  if (activeModel.value == 'specified' || activeModel.value == 'adGroup') {
+    handleSelectionChange(event);
+  } else {
+    handelSelect(event);
+  }
+};
 
-  const newSelectedAds = [];
+function handelSelect({ records }) {
+  selectedAds.value = [
+    ...selectedAds.value.filter(ad => ad.page !== currentPage.value),
+    ...records.map(ad => ({ ...ad, page: currentPage.value }))
+  ];
+}
 
-  selection.forEach(item => {
-    if (item.campaignGroupInfo) {
-      // 这是父节点(广告活动)
-      newSelectedAds.push({
-        campaignId: item.campaignId,
-        campaignName: item.campaignName,
-        campaignType: item.campaignType,
-        isParent: true
-      });
-    } else {
-      // 这是子节点(广告组)
-      const parent = adCampaignName.value.find(ad =>
-          ad.campaignGroupInfo && ad.campaignGroupInfo.some(group => group.adGroupId === item.adGroupId)
-      );
-      if (parent) {
-        // 添加父节点(如果还没有添加)
-        if (!newSelectedAds.some(ad => ad.campaignId === parent.campaignId)) {
-          newSelectedAds.push({
-            campaignId: parent.campaignId,
-            campaignName: parent.campaignName,
-            campaignType: parent.campaignType,
-            isParent: true
-          });
+function updateSelectedAds() {
+  selectedAds.value = gridOptions.data
+      .filter(ad => ad.campaignGroupInfo && ad.campaignGroupInfo.some(group => group.isSelected))
+      .map(ad => ({
+        ...ad,
+        campaignGroupInfo: ad.campaignGroupInfo.filter(group => group.isSelected),
+        page: currentPage.value
+      }));
+}
+
+function handleSelectionChange({ records, checked, reserve }) {
+  console.log("=>(adActivityDialog.vue:193) records", records);
+
+  if (records.length === 0 && !reserve) {
+    // 当所有项目被取消选择时,清空 selectedAds
+    selectedAds.value = [];
+  } else {
+    records.forEach(record => {
+      if (record.adGroupId) {
+        // 这是一个广告组(子节点)
+        const parentCampaign = gridOptions.data.find(campaign =>
+            campaign.campaignGroupInfo.some(group => group.adGroupId === record.adGroupId)
+        );
+        if (parentCampaign) {
+          const group = parentCampaign.campaignGroupInfo.find(group => group.adGroupId === record.adGroupId);
+          if (group) {
+            group.isSelected = checked;
+          }
         }
-        // 添加子节点(广告组)
-        newSelectedAds.push({
-          adGroupId: item.adGroupId,
-          adGroupName: item.adGroupName,
-          parentCampaignId: parent.campaignId,
-          parentCampaignName: parent.campaignName,
-          campaignType: parent.campaignType
+      } else {
+        // 这是一个广告活动(父节点)
+        record.campaignGroupInfo.forEach(group => {
+          group.isSelected = checked;
         });
       }
-    }
-  });
-  selectedAds.value = newSelectedAds;
+    });
+
+    updateSelectedAds();
+  }
+
+  console.log("=>(adActivityDialog.vue:224) selectedAds.value", selectedAds.value);
 }
 
-const groupedSelectedAds = computed(() => {
-  const groups = {};
-  selectedAds.value.forEach(ad => {
-    if (ad.isParent) {
-      if (!groups[ad.campaignId]) {
-        groups[ad.campaignId] = {
-          id: ad.campaignId,
-          name: ad.campaignName,
-          campaignType: ad.campaignType,
-          campaignGroupInfo: []
-        };
-      }
-    } else {
-      if (!groups[ad.parentCampaignId]) {
-        groups[ad.parentCampaignId] = {
-          id: ad.parentCampaignId,
-          name: ad.parentCampaignName,
-          campaignType: ad.campaignType,
-          campaignGroupInfo: []
-        };
+function handleSelectTarget(row) {
+  // 获取父节点数据
+  const parent = gridOptions.data.find(campaign =>
+      campaign.campaignGroupInfo.some(group => group.adGroupId === row.adGroupId)
+  );
+  selectedTargetedRow.value = {
+    campaignType: parent.campaignType,
+    campaignId: parent.campaignId,
+    adGroupId: row.adGroupId,
+    isSelected: row.isSelected || false, // 同步 isSelected 状态
+  };
+  targetRuleDialogVisible.value = true;
+}
+
+
+function handleConfirm({ campaignInfo, targetType }) {
+  if (!selectedTargetedRow.value) return;
+
+  // 找到父级广告活动
+  const parentCampaign = gridOptions.data.find(campaign =>
+      campaign.campaignGroupInfo.some(group => group.adGroupId === selectedTargetedRow.value.adGroupId)
+  );
+
+  if (parentCampaign) {
+    // 更新子节点(广告组)的信息
+    const group = parentCampaign.campaignGroupInfo.find(group => group.adGroupId === selectedTargetedRow.value.adGroupId);
+    if (group) {
+      if (targetType === 'keyword') {
+        group.keywordInfo = campaignInfo;
+      } else if (targetType === 'target') {
+        group.campaignTargetInfo = campaignInfo;
       }
-      groups[ad.parentCampaignId].campaignGroupInfo.push({
-        id: ad.adGroupId,
-        name: ad.adGroupName
-      });
+      group.isSelected = true;
+      group.targetLength = (group.keywordInfo?.length || 0) + (group.campaignTargetInfo?.length || 0);
     }
-  });
-  return Object.values(groups);
-});
+  }
 
-function removeSelectedAd(index) {
-  const removedAd = selectedAds.value.splice(index, 1)[0];
-
-  if (removedAd.parentCampaignId) {
-    // 查找同一父节点下的其他子节点
-    const remainingChildren = selectedAds.value.filter(ad => ad.parentCampaignId === removedAd.parentCampaignId);
-
-    // 如果父节点下还有其他子节点,父节点不删除
-    if (remainingChildren.length > 0) {
-      // 取消表格1中该子节点的勾选
-      const targetParent = adCampaignName.value.find(ad => ad.campaignId === removedAd.parentCampaignId);
-      if (targetParent) {
-        const targetChildIndex = targetParent.campaignGroupInfo.findIndex(group => group.adGroupId === removedAd.adGroupId);
-        if (targetChildIndex !== -1) {
-          const adTable = refTable.value;
-          adTable.toggleRowSelection(targetParent.campaignGroupInfo[targetChildIndex], false);
+  // 更新选中的广告
+  updateSelectedAds();
+
+  // 勾选表格1中的对应行
+  if (xGridOne.value) {
+    xGridOne.value.setCheckboxRow(selectedTargetedRow.value, true);
+  }
+}
+
+const removeSelectedAd = async (row) => {
+  console.log("=>(adActivityDialog.vue:274) row", row);
+  const $grid = xGridTwo.value;
+  if ($grid) {
+    console.log("=>(1) selectedAds.value", selectedAds.value);
+
+    if (row.adGroupId) {
+      // 删除子节点(广告组)
+      selectedAds.value = selectedAds.value.map(ad => {
+        if (ad.campaignGroupInfo) {
+          return {
+            ...ad,
+            campaignGroupInfo: ad.campaignGroupInfo.filter(group => group.adGroupId !== row.adGroupId)
+          };
         }
-      }
+        return ad;
+      }).filter(ad => ad.campaignGroupInfo && ad.campaignGroupInfo.length > 0);
     } else {
-      // 如果没有其他子节点了,移除父节点
-      const parentIndex = selectedAds.value.findIndex(ad => ad.campaignId === removedAd.parentCampaignId);
-      if (parentIndex !== -1) {
-        selectedAds.value.splice(parentIndex, 1);
-      }
-
-      // 取消表格1中父节点的勾选
-      const parentIndexInTable = adCampaignName.value.findIndex(ad => ad.campaignId === removedAd.parentCampaignId);
-      if (parentIndexInTable !== -1) {
-        const adTable = refTable.value;
-        adTable.toggleRowSelection(adCampaignName.value[parentIndexInTable], false);
-      }
-    }
-  } else {
-    // 如果删除的项是父节点
-    const targetIndex = adCampaignName.value.findIndex(ad => ad.campaignId === removedAd.campaignId);
-    if (targetIndex !== -1) {
-      const adTable = refTable.value;
-      adTable.toggleRowSelection(adCampaignName.value[targetIndex], false);
+      // 删除父节点(广告活动)
+      selectedAds.value = selectedAds.value.filter(ad => ad.campaignId !== row.campaignId);
     }
+
+    await $grid.remove(row);
+    console.log("=>(2) selectedAds.value", selectedAds.value);
   }
-}
+
+  if (xGridOne.value) {
+    await xGridOne.value.toggleCheckboxRow(row);
+  }
+};
 
 function removeAllSelectedAds() {
   selectedAds.value = [];
-  const adTable = refTable.value;
-  adTable.clearSelection();
+  const $grid = xGridOne.value;
+  if ($grid) {
+    $grid.clearCheckboxRow();
+  }
 }
 
 function cancel() {
   dialogVisible.value = false;
 }
 
-//TODO: 确认按钮
+//TODO: 确认按钮-商品
 async function confirm() {
   const campaignItems = selectedAds.value.map(ad => ({
     campaignId: ad.campaignId,
@@ -251,9 +322,13 @@ async function confirm() {
   const campaignTargetInfo = [
     { targetId: '492707808377423', adGroup_id: '448117369011017', bid: 0.45 },
   ];
-  const campaignKeywordInfo = [
-    { keywordId: '416969576305724', adGroup_id: '393554556566271', bid: 0.04 },
-  ];
+  console.log('=>(adActivityDialog.vue:291) selectedTargetedRow.value', selectedTargetedRow.value);
+
+  const campaignInfo = selectedTargetedRow.value.keywordInfo.map(keyword => ({
+    keywordId: keyword.keywordId,
+    adGroup_id: keyword.adGroup_id,
+    bid: keyword.bid
+  }));
 
   const requestData = {
     profileId: profile.value.profile_id,
@@ -261,9 +336,9 @@ async function confirm() {
     campaignItems,
     adGroupInfo,
     campaignTargetInfo,
-    campaignKeywordInfo
+    campaignInfo
   };
-  //console.log('requestData', requestData);
+  console.log('requestData', requestData);
 }
 
 // 获取广告组下拉框
@@ -283,51 +358,6 @@ async function fetchAdGroupList() {
   }
 }
 
-function handleSelectTarget(row) {
-  console.log("=>(adActivityDialog.vue:287) row", row);
-  // 获取父节点数据
-  const parent = adCampaignName.value.find(ad =>
-      ad.campaignGroupInfo && ad.campaignGroupInfo.some(group => group.adGroupId === row.adGroupId)
-  );
-  if (parent) {
-    // 构造包含父节点和子节点的数据对象
-    selectedTargetedRow.value = {
-      parentCampaignId: parent.campaignId,
-      parentCampaignName: parent.campaignName,
-      campaignType: parent.campaignType,
-      adGroupId: row.adGroupId,
-      adGroupName: row.adGroupName,
-      isSelected: row.isSelected || false, // 同步 isSelected 状态
-    };
-  }
-
-  targetRuleDialogVisible.value = true;
-}
-
-function handleConfirm(campaignKeywordInfo) {
-  selectedTargetedRow.value.keywordInfo = campaignKeywordInfo;
-  selectedTargetedRow.value.isSelected = true;
-
-  // 更新子节点状态
-  const parent = adCampaignName.value.find(ad =>
-      ad.campaignGroupInfo && ad.campaignGroupInfo.some(group => group.adGroupId === selectedTargetedRow.value.adGroupId)
-  );
-  if (parent) {
-    const group = parent.campaignGroupInfo.find(group => group.adGroupId === selectedTargetedRow.value.adGroupId);
-    if (group) {
-      group.isSelected = true; // 更新子节点的 isSelected 状态
-    }
-  }
-
-  // 勾选子节点行
-  const table = refTable.value;
-  const targetRow = parent.campaignGroupInfo.find(group => group.adGroupId === selectedTargetedRow.value.adGroupId);
-
-  if (table && targetRow) {
-    table.toggleRowSelection(targetRow, true); // 勾选目标子节点行
-  }
-}
-
 const headerCellStyle = (args) => {
   if (args.rowIndex === 0) {
     return {
@@ -373,18 +403,9 @@ watch(dialogVisible, (newValue) => {
   emits('update:modelValue', newValue);
 });
 
-const treeProps = computed(() => {
-  if (activeModel.value === 'adGroup' || activeModel.value === 'specified') {
-    return {
-      children: 'campaignGroupInfo',
-      checkStrictly: false
-    };
-  }
-  return {};
-});
-
 onMounted(() => {
   fetchAdGroupList();
+  fetchAdCampaign();
 });
 
 </script>
@@ -399,7 +420,7 @@ onMounted(() => {
     <div class="container">
       <div class="container-left">
         <el-input v-model="searchAdCampaign" clearable placeholder="请输入广告活动" style="width: 100%;"
-                  @change="fetchAdCampaign()"></el-input>
+                  @change="handleAdCampaignChange()"></el-input>
         <div class="custom-inline">
           <el-select v-model="selectedCampaignType" placeholder="选择广告类型">
             <el-option v-for="item in campaignType"
@@ -427,42 +448,31 @@ onMounted(() => {
             ></el-option>
           </el-select>
         </div>
-        <el-table
-            ref="refTable"
-            v-loading="loading"
-            :cell-style="cellStyle"
-            :data="adCampaignName"
-            :header-cell-style="headerCellStyle"
-            :row-key="'adGroupId'"
-            :tree-props="treeProps"
-            height="400"
-            style="width: 100%;"
-            @selection-change="handleSelectionChange"
-        >
-          <el-table-column label="广告活动名称">
-            <template #default="scope">
-              <el-tag
-                  v-if="scope.row.campaignType"
-                  :color="scope.row.campaignType === 'sb' ? '#0163d2' : (scope.row.campaignType === 'sp' ? '#ff7424' : '#365672')"
-                  class="campaign-type"
-                  disable-transitions
-                  round>
-                {{ scope.row.campaignType }}
-              </el-tag>
-              {{ scope.row.campaignName }}
-              {{ scope.row.adGroupName }}
-              <el-button
-                  v-if="scope.row.adGroupName && activeModel==='specified'&&!scope.row.isSelected"
-                  class="btn-link"
-                  link
-                  @click="handleSelectTarget(scope.row)">
-                选择定向
-              </el-button>
-              <span v-else-if="scope.row.adGroupName">已选择</span>
-            </template>
-          </el-table-column>
-          <el-table-column type="selection" width="55"></el-table-column>
-        </el-table>
+        <vxe-grid ref="xGridOne" :cell-style="cellStyle" :header-cell-style="headerCellStyle" v-bind="gridOptions"
+                  @checkbox-change="handleGridChange" @checkbox-all="handleGridChange">
+          <template #campaignName_default="{ row }">
+            <el-tag
+                v-if="row.campaignType"
+                :color="row.campaignType === 'sb' ? '#0163d2' : (row.campaignType === 'sp' ? '#ff7424' : '#365672')"
+                class="campaign-type"
+                disable-transitions
+                round>
+              {{ row.campaignType }}
+            </el-tag>
+            <span>  {{ row.campaignName }}</span>
+            <span class="flex-container">
+              {{ row.adGroupName }}
+            <el-button
+                v-if="row.adGroupName && activeModel==='specified'&&!row.isSelected"
+                class="btn-link"
+                link
+                @click="handleSelectTarget(row)">
+              选择定向
+            </el-button>
+            <span v-else-if="row.adGroupName">已选择定向</span>
+            </span>
+          </template>
+        </vxe-grid>
         <div class="pagination-container mt-4">
           <el-pagination
               v-model:current-page="currentPage"
@@ -479,45 +489,51 @@ onMounted(() => {
       </div>
       <div class="container-right">
         <h3>已选择({{ selectedAds.length }})</h3>
-        <el-table
-            :cell-style="cellStyle"
-            :data="groupedSelectedAds"
-            :header-cell-style="headerCellStyle"
-            :row-key="'id'"
-            :tree-props="treeProps"
-            height="484"
-            style="width: 100%; margin-top: 20px;"
-            v-bind="activeModel === 'adGroup' || activeModel === 'specified' ? treeProps : {}"
-        >
-          <el-table-column label="广告活动" prop="name">
-            <template #default="scope">
+        <vxe-grid ref="xGridTwo"
+                  :cell-style="cellStyle"
+                  :columns="selectedColumns"
+                  :data="selectedAds"
+                  :header-cell-style="headerCellStyle"
+                  :tree-config="treeProps"
+                  border="inner"
+                  height="484">
+          <template #campaignName_default="{ row }">
+            <template v-if="!row.adGroupId">
+              <!-- 父节点(广告活动) -->
               <el-tag
-                  v-if="scope.row.campaignType"
-                  :color="scope.row.campaignType === 'sb' ? '#0163d2' : (scope.row.campaignType === 'sp' ? '#ff7424' : '#365672')"
+                  v-if="row.campaignType"
+                  :color="row.campaignType === 'sb' ? '#0163d2' : (row.campaignType === 'sp' ? '#ff7424' : '#365672')"
                   class="campaign-type"
                   disable-transitions
                   round>
-                {{ scope.row.campaignType }}
+                {{ row.campaignType }}
               </el-tag>
-              {{ scope.row.campaignName }}
-              {{ scope.row.name }}
-            </template>
-          </el-table-column>
-          <el-table-column
-              align="center"
-              label="操作"
-              width="100"
-          >
-            <template #header>
-              <el-button link size="default" style="color: #2077d7" @click="removeAllSelectedAds">删除全部</el-button>
+              <span>{{ row.campaignName }}</span>
             </template>
-            <template #default="scope">
-              <el-button type="text" @click="removeSelectedAd(scope.$index)">
-                <CircleClose style="width:16px;color:#4b5765" />
-              </el-button>
+            <template v-else>
+              <!-- 子节点(广告组) -->
+              <div class="flex-container">
+                <span>{{ row.adGroupName }}</span>
+                <el-button
+                    v-if="row.isSelected"
+                    :icon="DocumentAdd"
+                    class="btn-link"
+                    link
+                    @click="handleSelectTarget(row)">
+                  共{{ row.targetLength }}个定向规则
+                </el-button>
+              </div>
             </template>
-          </el-table-column>
-        </el-table>
+          </template>
+          <template #header_operation>
+            <el-button link size="default" style="color: #2077d7" @click="removeAllSelectedAds">删除全部</el-button>
+          </template>
+          <template #default_operation="{row}">
+            <el-button type="text" @click="removeSelectedAd(row)">
+              <CircleClose style="width:16px;color:#4b5765" />
+            </el-button>
+          </template>
+        </vxe-grid>
       </div>
     </div>
     <template #footer>
@@ -548,14 +564,14 @@ onMounted(() => {
 }
 
 .campaign-type {
-  width: 35px;
-  text-align: center;
-  height: 22px;
-  font-size: 13px;
-  font-weight: 400;
+  /* width: 35px; */
+  /* text-align: center; */
+  /* height: 22px; */
+  /* font-size: 13px; */
+  /* font-weight: 400; */
   color: #fff;
   border-color: #fff;
-  line-height: 22px;
+  /* line-height: 21px; */
   border-radius: 12px;
   margin-right: 4px;
 }
@@ -590,4 +606,9 @@ onMounted(() => {
   /* ling-heigt: 23px; */
 }
 
+.flex-container {
+  display: flex;
+  justify-content: space-between;
+}
+
 </style>

+ 142 - 39
src/views/efTools/automation/components/targetRuleDialog.vue

@@ -4,11 +4,17 @@
  * @Description: 关联广告活动-选择定向弹窗
  * @Author: xinyan
  */
-import { onMounted, reactive, ref, watch } from 'vue';
+import { reactive, ref, watch } from 'vue';
 import { MatchType } from '../../utils/enum';
-import { getTargetingRuleList } from '/@/views/efTools/automation/api';
+import { getProductsList, getTargetingRuleList } from '/@/views/efTools/automation/api';
 import { ElMessage } from 'element-plus';
+import { storeToRefs } from 'pinia';
+import { useShopInfo } from '/@/stores/shopInfo';
+import { Share } from '@element-plus/icons-vue';
 
+
+const shopInfo = useShopInfo();
+const { profile } = storeToRefs(shopInfo);
 const props = defineProps({
   modelValue: {
     type: Boolean,
@@ -23,51 +29,105 @@ const emits = defineEmits(['update:modelValue', 'confirm:targetRule']);
 const targetRuleDialogVisible = ref(props.modelValue);
 const { selectedTargetedRow } = toRefs(props);
 const adGroupId = ref(props.adGroupId);
-const campaignKeywordInfo = ref(null);
+const campaignInfo = ref(null);
 
 // 查询、筛选条件
 const matchType = ref('');
 const keyWord = ref('');
 
+const targetType = ref(null);
+
+const keyWordColumn = ref([
+  { field: 'keywordText', title: '关键词', width: 220, },
+  { field: 'matchType', title: '匹配方式', formatter: ({ cellValue }) => getMatchTypeLabel(cellValue).label, },
+  { type: 'checkbox', align: 'right', width: 55 }
+]);
+const targetColumn = ref([
+  { field: 'expressionDesc', title: '品牌', slots: { default: 'expressionDesc_default' } },
+  { type: 'checkbox', align: 'right', width: 55 }
+]);
+const productColumn = ref([
+  { field: 'itemName', title: '商品/分类', slots: { default: 'itemName_default' } },
+  { type: 'checkbox', align: 'right', width: 55 }
+]);
+
 const gridOptions = reactive({
   height: 550,
   showOverflow: true,
   loading: false,
   rowConfig: {
     isHover: true,
-    height: 34
+    height: 85,
   },
-  columns: [
-    { field: 'keywordText', title: '关键词', width: 220 },
-    {
-      field: 'matchType',
-      title: '匹配方式',
-      formatter: ({ cellValue }) => getMatchTypeLabel(cellValue).label,
-    },
-    { type: 'checkbox', align: 'right', width: 55 }
-  ],
+  columns: [],
   data: []
 });
 
+const showProductSearch = computed(() => {
+  const columns = unref(gridOptions.columns);
+  return targetType.value === 'target' &&
+      Array.isArray(columns) &&
+      columns.length > 0 &&
+      columns[0].field === 'itemName';
+});
+
 async function fetchTargetRuleList() {
   try {
     gridOptions.loading = true;
     const resp = await getTargetingRuleList({
       campaignType: selectedTargetedRow.value.campaignType,
-      campaignId: selectedTargetedRow.value.parentCampaignId,
+      campaignId: selectedTargetedRow.value.campaignId,
       adGroupId: selectedTargetedRow.value.adGroupId,
       matchType: matchType.value,
       search: keyWord.value,
     });
-    gridOptions.data = resp.data.targetData;
+
+    targetType.value = resp.data.targetType;
+
+    // 动态设置表格列
+    if (resp.data.targetType === 'keyword') {
+      gridOptions.columns = keyWordColumn;
+      gridOptions.rowConfig.height = 34;
+      gridOptions.data = resp.data.targetData;
+
+    } else if (resp.data.targetType === 'target') {
+      gridOptions.rowConfig.height = 85;
+      gridOptions.columns = targetColumn;
+      gridOptions.data = resp.data.targetData;
+
+      // 检查是否有 ASIN_SAME_AS 字段
+      const asinSameAsList = resp.data.targetData
+          .filter(item => item.expressionDesc && item.expressionDesc.ASIN_SAME_AS) // 过滤存在 ASIN_SAME_AS 的项
+          .map(item => item.expressionDesc.ASIN_SAME_AS); // 提取所有 ASIN_SAME_AS
+
+      if (asinSameAsList.length > 0) {
+        gridOptions.columns = productColumn;
+        gridOptions.rowConfig.height = 120;
+        gridOptions.data = await fetchProductsList(asinSameAsList); // 传递 ASIN 列表
+      }
+    }
     gridOptions.loading = false;
   } catch (error) {
     ElMessage.error('请求定向数据失败');
+    gridOptions.loading = false; // 确保在错误情况下也关闭 loading 状态
+  }
+}
+
+// TODO: 待商品数据查询接口完成后,添加查询参数
+async function fetchProductsList(asinList) {
+  try {
+    const resp = await getProductsList({
+      asinList: asinList.join(','), // 将 ASIN 列表转换为逗号分隔的字符串
+      profileId: profile.value.profile_id,
+    });
+    return resp.data;
+  } catch (error) {
+    ElMessage.error('请求商品数据失败');
   }
 }
 
 function handleCheckChange({ records }) {
-  campaignKeywordInfo.value = records;
+  campaignInfo.value = records;
 }
 
 function getMatchTypeLabel(type: string) {
@@ -84,13 +144,25 @@ function cancel() {
 
 async function confirm() {
   targetRuleDialogVisible.value = false;
-  emits('confirm:targetRule', campaignKeywordInfo.value);
+  emits('confirm:targetRule', {
+    campaignInfo: campaignInfo.value,
+    targetType: targetType.value, // 将 targetType 作为参数传递给父组件
+  });
 }
 
+// 打开指定 URL 的方法
+const openProductUrl = (url) => {
+  if (url) {
+    window.open(url, '_blank');  // 在新标签页中打开链接
+  } else {
+    console.warn('Product URL is not available');
+  }
+};
+
 const headerCellStyle = () => {
   return {
     fontSize: '13px',
-    height: '34px',
+    // height: '34px',
   };
 };
 
@@ -113,9 +185,9 @@ watch(() => props.selectedTargetedRow, () => {
   fetchTargetRuleList();
 });
 
-onMounted(() => {
-  //fetchTargetRuleList();
-});
+// onMounted(() => {
+//   //fetchTargetRuleList();
+// });
 
 </script>
 
@@ -124,24 +196,55 @@ onMounted(() => {
              style="border-radius: 10px;"
              title="关联广告活动 > 选择定向"
              width="1158px">
-    <div>
-      <el-select
-          v-model="matchType"
-          placeholder="全部匹配方式"
-          style="width: 128px; margin-bottom: 10px"
-          @change="fetchTargetRuleList"
-      >
-        <el-option
-            v-for="item in MatchType"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value"
-        />
-      </el-select>
-    </div>
-    <el-input v-model="keyWord" class="mb-3" clearable placeholder="快速搜索关键词" @change="fetchTargetRuleList" />
-    <vxe-grid :cell-style="cellStyle" :header-cell-style="headerCellStyle" @checkbox-change="handleCheckChange"
-              v-bind="gridOptions"></vxe-grid>
+    <template v-if="targetType === 'keyword'">
+      <div>
+        <el-select
+            v-model="matchType"
+            placeholder="全部匹配方式"
+            style="width: 128px; margin-bottom: 10px"
+            @change="fetchTargetRuleList"
+        >
+          <el-option
+              v-for="item in MatchType"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+          />
+        </el-select>
+      </div>
+      <el-input v-model="keyWord" class="mb-3" clearable placeholder="快速搜索关键词" @change="fetchTargetRuleList" />
+    </template>
+    <template v-else-if="showProductSearch">
+      <el-input v-model="productName" class="mb-3" placeholder="快速搜索分类名称或商品名称" style="width: 517px"
+                @change="fetchProductsList"></el-input>
+    </template>
+    <vxe-grid :cell-style="cellStyle" :header-cell-style="headerCellStyle" v-bind="gridOptions"
+              v-on="gridEvents" @checkbox-change="handleCheckChange">
+      <template #expressionDesc_default="{ row }">
+        <div v-if="row.expressionDesc.ASIN_CATEGORY_SAME_AS">分类:{{ row.expressionDesc.ASIN_CATEGORY_SAME_AS }}</div>
+        <div v-if="row.expressionDesc.ASIN_BRAND_SAME_AS">品牌:{{ row.expressionDesc.ASIN_BRAND_SAME_AS }}</div>
+        <div v-if="row.expressionDesc.ASIN_PRICE_BETWEEN">商品价格:{{ row.expressionDesc.ASIN_PRICE_BETWEEN }}</div>
+        <div v-if="row.expressionDesc.ASIN_REVIEW_RATING_BETWEEN">评分:{{
+            row.expressionDesc.ASIN_REVIEW_RATING_BETWEEN
+          }}
+        </div>
+        <div v-if="row.expressionDesc.ASIN_SAME_AS">asin:{{ row.expressionDesc.ASIN_SAME_AS }}</div>
+      </template>
+      <template #itemName_default="{ row }">
+        <div style="display: flex; align-items: flex-start;">
+          <!-- 左边图片部分 -->
+          <div style="flex-shrink: 0;">
+            <img :src="row.main_image" alt="Product Image" height="53" width="53" />
+          </div>
+          <!-- 右边文字部分 -->
+          <div style="margin-left: 10px;">
+            <div><strong>{{ row.itemName }}</strong></div>
+            <span>ASIN: {{ row.asin }}</span>
+            <el-button :icon="Share" link type="primary" @click="openProductUrl(row.productUrl)"></el-button>
+          </div>
+        </div>
+      </template>
+    </vxe-grid>
     <template #footer>
       <div class="dialog-footer">
         <el-button @click="cancel">取消</el-button>

+ 13 - 0
src/views/efTools/utils/columns.ts

@@ -0,0 +1,13 @@
+export const targetColumn = [
+  { field: 'expressionDesc', title: '品牌', },];
+
+export const keyWordColumn = [
+
+  { field: 'keywordText', title: '关键词', width: 220 },
+  {
+    field: 'matchType',
+    title: '匹配方式',
+    formatter: ({ cellValue }) => getMatchTypeLabel(cellValue).label,
+  },
+  { type: 'checkbox', align: 'right', width: 55 }
+];