|  | @@ -4,12 +4,17 @@
 | 
	
		
			
				|  |  |   * @Description: 关联广告活动-选择定向弹窗
 | 
	
		
			
				|  |  |   * @Author: xinyan
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  | -import { provide, 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,
 | 
	
	
		
			
				|  | @@ -41,9 +46,10 @@ const targetColumn = ref([
 | 
	
		
			
				|  |  |    { field: 'expressionDesc', title: '品牌', slots: { default: 'expressionDesc_default' } },
 | 
	
		
			
				|  |  |    { type: 'checkbox', align: 'right', width: 55 }
 | 
	
		
			
				|  |  |  ]);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const keyWordData = [];
 | 
	
		
			
				|  |  | -const targetData = [];
 | 
	
		
			
				|  |  | +const productColumn = ref([
 | 
	
		
			
				|  |  | +  { field: 'itemName', title: '商品/分类', slots: { default: 'itemName_default' } },
 | 
	
		
			
				|  |  | +  { type: 'checkbox', align: 'right', width: 55 }
 | 
	
		
			
				|  |  | +]);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  const gridOptions = reactive({
 | 
	
		
			
				|  |  |    height: 550,
 | 
	
	
		
			
				|  | @@ -57,6 +63,14 @@ const gridOptions = reactive({
 | 
	
		
			
				|  |  |    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;
 | 
	
	
		
			
				|  | @@ -67,19 +81,48 @@ async function fetchTargetRuleList() {
 | 
	
		
			
				|  |  |        matchType: matchType.value,
 | 
	
		
			
				|  |  |        search: keyWord.value,
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      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.data = resp.data.targetData;
 | 
	
		
			
				|  |  |      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('请求商品数据失败');
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -107,6 +150,15 @@ async function confirm() {
 | 
	
		
			
				|  |  |    });
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// 打开指定 URL 的方法
 | 
	
		
			
				|  |  | +const openProductUrl = (url) => {
 | 
	
		
			
				|  |  | +  if (url) {
 | 
	
		
			
				|  |  | +    window.open(url, '_blank');  // 在新标签页中打开链接
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    console.warn('Product URL is not available');
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  const headerCellStyle = () => {
 | 
	
		
			
				|  |  |    return {
 | 
	
		
			
				|  |  |      fontSize: '13px',
 | 
	
	
		
			
				|  | @@ -144,22 +196,28 @@ watch(() => props.selectedTargetedRow, () => {
 | 
	
		
			
				|  |  |               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" />
 | 
	
		
			
				|  |  | +    <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 }">
 | 
	
	
		
			
				|  | @@ -172,6 +230,20 @@ watch(() => props.selectedTargetedRow, () => {
 | 
	
		
			
				|  |  |          </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">
 |