|
@@ -0,0 +1,448 @@
|
|
|
+<script lang="ts" setup>
|
|
|
+/**
|
|
|
+ * @Name: view-target-rules.vue
|
|
|
+ * @Description: 点击选择定向按钮弹窗
|
|
|
+ * @Author: xinyan
|
|
|
+ */
|
|
|
+
|
|
|
+import { DocumentAdd } from '@element-plus/icons-vue';
|
|
|
+import { computed, onMounted, reactive, ref, watch } from 'vue';
|
|
|
+import { ElMessage } from 'element-plus';
|
|
|
+import { getCampaignRuleList } from '/@/views/components/auto/auto-campaigns/api';
|
|
|
+import SelectTarget from '/@/views/components/auto/auto-campaigns/select-target.vue';
|
|
|
+
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ modelValue: {
|
|
|
+ type: Boolean,
|
|
|
+ required: true,
|
|
|
+ },
|
|
|
+ checkTarget: {
|
|
|
+ type: Object,
|
|
|
+ required: true,
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+const emits = defineEmits(['update:modelValue']);
|
|
|
+
|
|
|
+const loading = ref(false);
|
|
|
+const xGridOne = ref(null);
|
|
|
+const xGridTwo = ref(null);
|
|
|
+let selectedAds = ref([]);
|
|
|
+
|
|
|
+const dialogVisible = ref(false);
|
|
|
+const SelectTargetVisible = ref(false);
|
|
|
+
|
|
|
+const selectedTargetedRow = ref(null);
|
|
|
+
|
|
|
+const selectedColumns = [
|
|
|
+ {
|
|
|
+ field: 'campaignName',
|
|
|
+ title: '广告活动',
|
|
|
+ slots: { default: 'campaignName_default' },
|
|
|
+ treeNode: true
|
|
|
+ },
|
|
|
+ { title: '操作', width: 65, align: 'center', slots: { header: 'header_operation', default: 'default_operation' } }
|
|
|
+];
|
|
|
+
|
|
|
+const treeProps = computed(() => {
|
|
|
+ return {
|
|
|
+ rowField: 'campaignId',
|
|
|
+ childrenField: 'adGroupInfo', // 子节点字段
|
|
|
+ expandAll: true,
|
|
|
+ };
|
|
|
+});
|
|
|
+
|
|
|
+const gridOptions = reactive({
|
|
|
+ border: 'inner',
|
|
|
+ height: 500,
|
|
|
+ loading: false,
|
|
|
+ rowConfig: {
|
|
|
+ isHover: true,
|
|
|
+ keyField: 'campaignId',
|
|
|
+ },
|
|
|
+ treeConfig: treeProps,
|
|
|
+ checkboxConfig: {
|
|
|
+ labelField: 'name',
|
|
|
+ reserve: true,
|
|
|
+ checkStrictly: false,
|
|
|
+ checkMethod: ({ row }) => {
|
|
|
+ // 只允许取消选中
|
|
|
+ return row.isSelected;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ columns: [
|
|
|
+ {
|
|
|
+ field: 'campaignName',
|
|
|
+ title: '广告活动',
|
|
|
+ slots: { default: 'campaignName_default' },
|
|
|
+ treeNode: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'checkbox',
|
|
|
+ width: 55,
|
|
|
+ fixed: 'right',
|
|
|
+ slots: { header: 'checkbox_header', checkbox: 'checkbox_cell' }
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ data: []
|
|
|
+});
|
|
|
+
|
|
|
+function handleGridChange({ records, row, checked }) {
|
|
|
+ console.log(12321312312);
|
|
|
+ if (row) {
|
|
|
+ if (!checked) {
|
|
|
+ row.isSelected = false;
|
|
|
+ updateSelectedAds();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 全选/取消全选
|
|
|
+ records.forEach(record => {
|
|
|
+ if (record.isSelected) {
|
|
|
+ record.isSelected = checked;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ updateSelectedAds();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function toggleCheckboxEvent(row) {
|
|
|
+
|
|
|
+ if (row.isSelected) {
|
|
|
+ // 只有已选择的行可以被取消选中
|
|
|
+ xGridOne.value.setCheckboxRow(row, false);
|
|
|
+ handleGridChange({ records: [row], row, checked: false });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+async function fetchAdCampaign() {
|
|
|
+ try {
|
|
|
+ const resp = await getCampaignRuleList({
|
|
|
+ profileId: props.checkTarget.profileId,
|
|
|
+ campaignId: props.checkTarget.campaignId
|
|
|
+ });
|
|
|
+ gridOptions.data = [resp.data];
|
|
|
+
|
|
|
+ // // 默认勾选有 selectTargetId 的数据
|
|
|
+ // const adGroupsToCheck = resp.data.adGroupInfo.filter(group =>
|
|
|
+ // group.selectTargetId && group.selectTargetId.length > 0
|
|
|
+ // );
|
|
|
+ //
|
|
|
+ // // 更新选中的广告
|
|
|
+ // selectedAds.value = [{
|
|
|
+ // campaignId: resp.data.campaignId,
|
|
|
+ // campaignType: resp.data.campaignType,
|
|
|
+ // campaignName: resp.data.campaignName,
|
|
|
+ // adGroupInfo: adGroupsToCheck
|
|
|
+ // }];
|
|
|
+ //
|
|
|
+ // // 在 nextTick 中设置选中状态,确保表格已经渲染
|
|
|
+ // nextTick(() => {
|
|
|
+ // if (xGridOne.value) {
|
|
|
+ // adGroupsToCheck.forEach(group => {
|
|
|
+ // group.isSelected = true;
|
|
|
+ // xGridOne.value.setCheckboxRow(group, true);
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('请求广告活动数据失败');
|
|
|
+ } finally {
|
|
|
+ // gridOptions.loading = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function handleSelectTarget(row) {
|
|
|
+ // 获取父节点数据
|
|
|
+ const parent = gridOptions.data.find(campaign =>
|
|
|
+ campaign.adGroupInfo.some(group => group.adGroupId === row.adGroupId)
|
|
|
+ );
|
|
|
+ selectedTargetedRow.value = {
|
|
|
+ campaignType: parent.campaignType,
|
|
|
+ campaignId: parent.campaignId,
|
|
|
+ adGroupId: row.adGroupId,
|
|
|
+ isSelected: row.isSelected || false,
|
|
|
+ keywordInfo: row.keywordInfo || [],
|
|
|
+ campaignTargetInfo: row.campaignTargetInfo || [],
|
|
|
+ };
|
|
|
+ SelectTargetVisible.value = true;
|
|
|
+ console.log('SelectTargetVisible', SelectTargetVisible.value);
|
|
|
+}
|
|
|
+
|
|
|
+function updateSelectedAds() {
|
|
|
+ selectedAds.value = gridOptions.data
|
|
|
+ .filter(ad => ad.adGroupInfo && ad.adGroupInfo.some(group => group.isSelected))
|
|
|
+ .map(ad => ({
|
|
|
+ ...ad,
|
|
|
+ adGroupInfo: ad.adGroupInfo.filter(group => group.isSelected),
|
|
|
+ }));
|
|
|
+ console.log('selectedAds.value', selectedAds.value);
|
|
|
+}
|
|
|
+
|
|
|
+// 选择定向弹窗确认按钮
|
|
|
+function handleConfirm({ campaignInfo, targetType }) {
|
|
|
+ if (!selectedTargetedRow.value) return;
|
|
|
+
|
|
|
+ // 找到父级广告活动
|
|
|
+ const parentCampaign = gridOptions.data.find(campaign =>
|
|
|
+ campaign.adGroupInfo.some(group => group.adGroupId === selectedTargetedRow.value.adGroupId)
|
|
|
+ );
|
|
|
+
|
|
|
+ if (parentCampaign) {
|
|
|
+ // 更新子节点(广告组)的信息
|
|
|
+ const group = parentCampaign.adGroupInfo.find(group => group.adGroupId === selectedTargetedRow.value.adGroupId);
|
|
|
+ if (group) {
|
|
|
+ if (targetType === 'keyword') {
|
|
|
+ group.keywordInfo = campaignInfo;
|
|
|
+ } else if (targetType === 'target') {
|
|
|
+ group.campaignTargetInfo = campaignInfo;
|
|
|
+ }
|
|
|
+ group.isSelected = true; // 更新子节点的选择状态
|
|
|
+ group.targetLength = (group.keywordInfo?.length || 0) + (group.campaignTargetInfo?.length || 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 勾选表格1中的对应行,只有在定向大于0时进行勾选
|
|
|
+ if (group && group.targetLength > 0) {
|
|
|
+ if (xGridOne.value) {
|
|
|
+ xGridOne.value.toggleCheckboxRow(group, true); // 手动勾选复选框
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 更新选中的广告
|
|
|
+ updateSelectedAds();
|
|
|
+}
|
|
|
+
|
|
|
+// 删除选中的广告
|
|
|
+const removeSelectedAd = async (row) => {
|
|
|
+ const $grid = xGridTwo.value;
|
|
|
+ if ($grid) {
|
|
|
+ if (row.adGroupId) {
|
|
|
+ // 删除子节点(广告组)
|
|
|
+ selectedAds.value = selectedAds.value.map(ad => {
|
|
|
+ if (ad.adGroupInfo) {
|
|
|
+ return {
|
|
|
+ ...ad,
|
|
|
+ adGroupInfo: ad.adGroupInfo.filter(group => group.adGroupId !== row.adGroupId)
|
|
|
+ };
|
|
|
+ }
|
|
|
+ return ad;
|
|
|
+ }).filter(ad => ad.adGroupInfo && ad.adGroupInfo.length > 0);
|
|
|
+ } else {
|
|
|
+ // 删除父节点(广告活动)
|
|
|
+ selectedAds.value = selectedAds.value.filter(ad => ad.campaignId !== row.campaignId);
|
|
|
+ }
|
|
|
+
|
|
|
+ await $grid.remove(row);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (xGridOne.value) {
|
|
|
+ await xGridOne.value.toggleCheckboxRow(row);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+function removeAllSelectedAds() {
|
|
|
+ selectedAds.value = [];
|
|
|
+ const $grid = xGridOne.value;
|
|
|
+ if ($grid) {
|
|
|
+ $grid.clearCheckboxRow();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+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(() => props.modelValue, (newValue) => {
|
|
|
+ dialogVisible.value = newValue;
|
|
|
+});
|
|
|
+
|
|
|
+watch(dialogVisible, (newValue) => {
|
|
|
+ emits('update:modelValue', newValue);
|
|
|
+ fetchAdCampaign();
|
|
|
+});
|
|
|
+
|
|
|
+watch(props.checkTarget, () => {
|
|
|
+ fetchAdCampaign();
|
|
|
+});
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ // fetchAdCampaign();
|
|
|
+});
|
|
|
+
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <el-dialog
|
|
|
+ v-model="dialogVisible"
|
|
|
+ style="border-radius: 10px;"
|
|
|
+ title="关联广告活动"
|
|
|
+ width="1158px"
|
|
|
+ >
|
|
|
+ <div class="container">
|
|
|
+ <div class="container-left">
|
|
|
+ <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 && row.selectTargetId.length!==0"
|
|
|
+ class="btn-link"
|
|
|
+ link
|
|
|
+ @click="handleSelectTarget(row)">
|
|
|
+ 选择定向
|
|
|
+ </el-button>
|
|
|
+ <span v-else-if="row.adGroupName">已选择定向</span>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ <template #checkbox_header="{ checked, indeterminate }">
|
|
|
+ <span class="custom-checkbox" @click.stop="toggleAllCheckboxEvent">
|
|
|
+ <i v-if="indeterminate" class="vxe-icon-square-minus-fill" style="color: #0d84ff"></i>
|
|
|
+ <i v-else-if="checked" class="vxe-icon-square-checked-fill" style="color: #0d84ff"></i>
|
|
|
+ <i v-else class="vxe-icon-checkbox-unchecked" style="color: #0d84ff"></i>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ <template #checkbox_cell="{ row, checked, indeterminate }">
|
|
|
+ <span class="custom-checkbox" @click.stop="toggleCheckboxEvent(row)">
|
|
|
+ <i v-if="indeterminate" class="vxe-icon-square-minus-fill" style="color: #0d84ff"></i>
|
|
|
+ <i v-else-if="checked" class="vxe-icon-square-checked-fill" style="color: #0d84ff"></i>
|
|
|
+ <el-tooltip v-else
|
|
|
+ class="box-item"
|
|
|
+ content="请选择定向"
|
|
|
+ effect="dark"
|
|
|
+ placement="top"
|
|
|
+ >
|
|
|
+ <i class="vxe-icon-checkbox-unchecked" style="color: #0d84ff"></i>
|
|
|
+ </el-tooltip>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </vxe-grid>
|
|
|
+ </div>
|
|
|
+ <div class="container-right">
|
|
|
+ <h3>已选择({{ selectedAds.length }})</h3>
|
|
|
+ <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="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>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <!-- 子节点(广告组) -->
|
|
|
+ <span class="flex-container">
|
|
|
+ {{ row.adGroupName }}
|
|
|
+ <el-button
|
|
|
+ v-if="row.isSelected"
|
|
|
+ :icon="DocumentAdd"
|
|
|
+ class="btn-link"
|
|
|
+ link
|
|
|
+ @click="handleSelectTarget(row)">
|
|
|
+ 共{{ row.targetLength }}个定向规则
|
|
|
+ </el-button>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ <template #header_operation>
|
|
|
+ <el-button link size="default" style="color: #2077d7;font-size: 13px" @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>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button @click="cancel">取消</el-button>
|
|
|
+ <el-button type="primary" @click="confirm">确定</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ <SelectTarget v-model="SelectTargetVisible"
|
|
|
+ :selectedTargetedRow="selectedTargetedRow"
|
|
|
+ @confirm:selectTarget="handleConfirm"
|
|
|
+ ></SelectTarget>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.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
|
|
|
+}
|
|
|
+
|
|
|
+.campaign-type {
|
|
|
+ color: #fff;
|
|
|
+ border-color: #fff;
|
|
|
+ border-radius: 12px;
|
|
|
+ margin-right: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.btn-link {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #0085ff;
|
|
|
+}
|
|
|
+
|
|
|
+.flex-container {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+</style>
|