ソースを参照

1. 广告推送相关

ith5 6 ヶ月 前
コミット
790dbc1cae

+ 2 - 2
src/components/sa-table/defaultOptions.js

@@ -10,7 +10,7 @@ export default {
   // 设置选择列
   rowSelection: undefined,
   // 是否显示边框
-  bordered: { wrapper: true, cell: false },
+  bordered: { wrapper: true, cell: true },
   // 每页记录数
   pageSize: 10,
   // 默认展开所有行
@@ -20,7 +20,7 @@ export default {
   // 斑马线
   stripe: true,
   // 表格大小
-  size: "large",
+  size: "small",
   // 是否显示展开/折叠按钮
   isExpand: false,
   // 是否显示工具栏

+ 1 - 1
src/components/sa-table/index.vue

@@ -230,7 +230,7 @@
               :pagination="false"
               :columns="columns"
               :loading="loading"
-              :size="options.size || 'mini'"
+              :size="options.size"
               :stripe="options.stripe"
               :data="tableData.data"
               :scroll="{ x: '100%', y: '100%' }"

+ 19 - 4
src/views/v1/advert/agentSite/edit.vue

@@ -19,18 +19,32 @@
       <a-form-item label="媒体ID" field="media_id">
         <a-select
           v-model="formData.media_id"
-          :options="mediaOptions"
           placeholder="请选择媒体ID"
           allow-clear
-        />
+          :disabled="mode === 'edit'"
+        >
+          <a-option
+            v-for="item in mediaOptions"
+            :key="item.id"
+            :value="item.id"
+            :label="`${item.id}:${item.name}`"
+          />
+        </a-select>
       </a-form-item>
       <a-form-item label="渠道ID" field="agent_id">
         <a-select
           v-model="formData.agent_id"
-          :options="agentOptions"
           placeholder="请选择渠道ID"
           allow-clear
-        />
+          :disabled="mode === 'edit'"
+        >
+          <a-option
+            v-for="item in agentOptions"
+            :key="item.id"
+            :value="item.id"
+            :label="`${item.id}:${item.name}`"
+          />
+        </a-select>
       </a-form-item>
       <a-form-item label="负责人ID" field="auth_id">
         <a-select
@@ -38,6 +52,7 @@
           :options="authOptions"
           placeholder="请选择负责人ID"
           allow-clear
+          :disabled="mode === 'edit'"
         />
       </a-form-item>
       <a-form-item label="广告位名称" field="name">

+ 206 - 0
src/views/v1/advert/agentSite/gdt_pac.vue

@@ -0,0 +1,206 @@
+<template>
+  <component
+    is="a-modal"
+    v-model:visible="visible"
+    :width="tool.getDevice() === 'mobile' ? '100%' : '600px'"
+    :title="title"
+    :mask-closable="false"
+    :ok-loading="loading"
+    @cancel="close"
+    @before-ok="submit"
+    :footer="false"
+  >
+    <!-- 表单信息 start -->
+    <a-form
+      ref="formRef"
+      :model="formData"
+      :rules="rules"
+      :auto-label-width="true"
+    >
+      <a-form-item label="推送游戏" field="gamePackageId">
+        <a-select v-model="formData.gamePackageId" placeholder="请选择推送游戏">
+          <a-option
+            v-for="item in gamePackageOptions"
+            :key="item.id"
+            :value="item.id"
+            :label="item.name"
+          />
+        </a-select>
+      </a-form-item>
+
+      <a-form-item label="分包标识" field="remark">
+        <a-textarea v-model="formData.remark" placeholder="请输入分包标识" />
+      </a-form-item>
+      <a-form-item>
+        <a-space>
+          <a-button type="primary" @click="addGamePackage"
+            >生成分包标识</a-button
+          >
+          <a-button type="primary" @click="downloadExcel">下载excel</a-button>
+        </a-space>
+      </a-form-item>
+    </a-form>
+    <!-- 表单信息 end -->
+  </component>
+</template>
+
+<script setup>
+import { ref, reactive, computed } from "vue";
+import { Message, Modal } from "@arco-design/web-vue";
+import tool from "@/utils/tool";
+import api from "@/api/system/post";
+import { request } from "@/utils/request";
+import commonApi from "../../api/common";
+
+const emit = defineEmits(["success"]);
+
+// 引用定义
+const formRef = ref();
+const mode = ref("");
+const visible = ref(false);
+const loading = ref(false);
+const batchData = ref([]);
+const gamePackageOptions = ref([]);
+const isExport = ref(false);
+
+let title = computed(() => {
+  return "广点通分包";
+});
+
+// 表单初始值
+const initialFormData = {
+  id: "",
+  gamePackageId: "",
+  remark: "",
+};
+
+// 表单信息
+const formData = reactive({ ...initialFormData });
+
+// 设置批量数据
+const setBatchData = async (data) => {
+  batchData.value = data;
+};
+
+// 验证规则
+const rules = {
+  game_id: [{ required: true, message: "推送游戏不能为空" }],
+};
+
+// 打开弹框
+const open = async (type = "ks") => {
+  mode.value = type;
+  // 重置表单数据
+  Object.assign(formData, initialFormData);
+  formRef.value.clearValidate();
+  formRef.value.resetFields();
+
+  visible.value = true;
+  await initPage();
+};
+
+// 初始化页面数据
+const initPage = async () => {
+  await getGamePackageOptions();
+};
+
+// 获取母包列表
+const getGamePackageOptions = async () => {
+  const res = await commonApi.getPackageOptionsApi({ media_id: 2 });
+  if (res.code === 200) {
+    gamePackageOptions.value = res.data;
+  }
+};
+
+// 生成分包标识
+const addGamePackage = async () => {
+  let data = [];
+  let gamePackage = gamePackageOptions.value.find(
+    (item) => item.id === formData.gamePackageId
+  );
+  for (let i = 0; i < batchData.value.length; i++) {
+    let row = batchData.value[i];
+    data.push(
+      // 母包名称-广告位ID,游戏ID_渠道ID_广告位ID
+      `${gamePackage.name}-${row.site_id},${gamePackage.game_id}_${row.agent_id}_${row.site_id}`
+    );
+  }
+  formData.remark = data.join("\n");
+  console.log("生成分包标识", data);
+};
+
+// 下载excel
+const downloadExcel = async () => {
+  if (!formData.remark) {
+    Modal.error({
+      title: "提示",
+      content: "请先生成分包标识",
+    });
+    return;
+  }
+  console.log("下载excel");
+  // 导出
+  Message.info("请求服务器下载文件中...");
+  const data = formData.remark.split("\n");
+  const download = () =>
+    request({
+      url: "/v1/advert/AgentSite/exportGamePackageKs",
+      data: { title: title.value, data },
+      method: "post",
+      timeout: 60 * 1000,
+      responseType: "blob",
+    });
+  isExport.value = true;
+  download()
+    .then((res) => {
+      if (res && res.status == 200) {
+        tool.download(res);
+        Message.success("请求成功,文件开始下载");
+      } else {
+        Message.error("请前往服务端安装Excel导出库");
+      }
+    })
+    .catch(() => {
+      Message.error("请求服务器错误,下载失败");
+    })
+    .finally(() => {
+      isExport.value = false;
+    });
+};
+
+// 设置数据
+const setFormData = async (data) => {
+  for (const key in formData) {
+    if (data[key] != null && data[key] != undefined) {
+      formData[key] = data[key];
+    }
+  }
+};
+
+// 数据保存
+const submit = async (done) => {
+  const validate = await formRef.value?.validate();
+  if (!validate) {
+    loading.value = true;
+    let data = { ...formData };
+    let result = {};
+    // 生成标识
+
+    if (result.code === 200) {
+      Message.success("操作成功");
+      emit("success");
+      done(true);
+    }
+    // 防止连续点击提交
+    setTimeout(() => {
+      loading.value = false;
+    }, 500);
+  }
+  done(false);
+};
+
+// 关闭弹窗
+const close = () => (visible.value = false);
+
+defineExpose({ open, setFormData, setBatchData });
+</script>

+ 130 - 13
src/views/v1/advert/agentSite/index.vue

@@ -67,13 +67,34 @@
 
       <template #tableBeforeButtons>
         <a-button
-          size="mini"
           type="primary"
           @click="addApk"
-          :disabled="selecteds.length != 1"
+          :disabled="selecteds.length === 0"
         >
           APK打包
         </a-button>
+        <a-button
+          type="primary"
+          status="warning"
+          @click="addGdt"
+          :disabled="selecteds.length === 0"
+          >广点通分包</a-button
+        >
+
+        <a-button
+          type="primary"
+          status="success"
+          @click="addKs"
+          :disabled="selecteds.length === 0"
+          >快手分包</a-button
+        >
+        <a-button
+          type="primary"
+          status="danger"
+          @click="addTt"
+          :disabled="selecteds.length === 0"
+          >头条推送</a-button
+        >
       </template>
 
       <!-- Table 自定义渲染 -->
@@ -83,17 +104,28 @@
 
     <!-- 打包新增 -->
     <add-apk-form ref="addApkRef" @success="refresh" />
+
+    <!-- 快手分包 -->
+    <ks-pac-form ref="ksPacRef" @success="refresh" />
+
+    <!-- 广点通分包 -->
+    <gdt-pac-form ref="gdtPacRef" @success="refresh" />
+
+    <!-- 头条推送(新) -->
+    <tt-pac-form ref="ttPacRef" @success="refresh" />
   </div>
 </template>
 
 <script setup>
 import { onMounted, ref, reactive } from "vue";
-import { Message } from "@arco-design/web-vue";
+import { Message, Modal } from "@arco-design/web-vue";
 import advertCommonApi from "../../api/advert/common";
 import editForm from "./edit.vue";
 import addApkForm from "../../gameLog/gamePackageLog/edit.vue";
 import api from "../../api/advert/agentSite";
-
+import ksPacForm from "./ks_pac.vue";
+import gdtPacForm from "./gdt_pac.vue";
+import ttPacForm from "./tt_pac.vue";
 // 引用定义
 const crudRef = ref();
 const viewRef = ref();
@@ -102,6 +134,9 @@ const mediaOptions = ref([]);
 const agentOptions = ref([]);
 const authOptions = ref([]);
 const editRef = ref();
+const ksPacRef = ref();
+const gdtPacRef = ref();
+const ttPacRef = ref();
 const selecteds = ref([]);
 
 // 搜索表单
@@ -146,9 +181,9 @@ const options = reactive({
 
 // SaTable 列配置
 const columns = reactive([
+  { title: "广告位ID", dataIndex: "id", width: 120 },
   { title: "广告位名称", dataIndex: "name", width: 180 },
-  { title: "媒体ID", dataIndex: "media_id", width: 180 },
-  { title: "媒体名", dataIndex: "media_name", width: 180 },
+  { title: "媒体类型", dataIndex: "media_name", width: 180 },
   { title: "渠道ID", dataIndex: "agent_id", width: 180 },
   { title: "渠道名", dataIndex: "agent_name", width: 180 },
   { title: "负责人", dataIndex: "auth_name", width: 180 },
@@ -193,14 +228,96 @@ const getAdvertSiteDetail = async () => {
 
 // 打包新增
 const addApk = async () => {
-  let id = selecteds.value[0];
-  const siteDetail = await getAdvertSiteDetail(id);
-  let data = {
-    site_id: siteDetail.id, // 广告位
-    agent_id: siteDetail.agent_id, // 渠道
-  };
+  let data = [];
+  let tableData = crudRef.value?.getTableData();
+  for (let i = 0; i < selecteds.value.length; i++) {
+    let id = selecteds.value[i];
+    let row = tableData.find((item) => item.id == id);
+    data.push({
+      site_id: row.id, // 广告位
+      agent_id: row.agent_id, // 渠道
+    });
+  }
+
   addApkRef.value?.open();
-  addApkRef.value?.setFormData(data);
+  addApkRef.value?.setBatchData(data);
+};
+
+// 广点通分包
+const addGdt = async () => {
+  let tableData = crudRef.value?.getTableData();
+  for (let i = 0; i < selecteds.value.length; i++) {
+    // media_id 必须都是1, 否则不给打包
+    let row = tableData.find((item) => item.id == selecteds.value[i]);
+    if (row.media_id != 2) {
+      Modal.error({
+        title: "提示",
+        content: `广告位ID:${row.id},媒体类型不是广点通,不能分包!`,
+      });
+
+      return;
+    }
+  }
+  let data = [];
+  for (let i = 0; i < selecteds.value.length; i++) {
+    let row = tableData.find((item) => item.id == selecteds.value[i]);
+    data.push({
+      site_id: row.id, // 广告位
+      agent_id: row.agent_id, // 渠道
+    });
+  }
+
+  gdtPacRef.value?.open();
+  gdtPacRef.value?.setBatchData(data);
+};
+
+// 快手分包
+const addKs = async () => {
+  let tableData = crudRef.value?.getTableData();
+  for (let i = 0; i < selecteds.value.length; i++) {
+    let row = tableData.find((item) => item.id == selecteds.value[i]);
+    if (row.media_id != 3) {
+      Modal.error({
+        title: "提示",
+        content: `广告位ID:${row.id},媒体类型不是快手,不能分包!`,
+      });
+      return false;
+    }
+  }
+  let data = [];
+  for (let i = 0; i < selecteds.value.length; i++) {
+    let row = tableData.find((item) => item.id == selecteds.value[i]);
+    data.push({
+      site_id: row.id, // 广告位
+      agent_id: row.agent_id, // 渠道
+    });
+  }
+
+  ksPacRef.value?.open();
+  ksPacRef.value?.setBatchData(data);
+};
+
+// 头条推送(新)
+const addTt = async () => {
+  let tableData = crudRef.value?.getTableData();
+  for (let i = 0; i < selecteds.value.length; i++) {
+    let row = tableData.find((item) => item.id == selecteds.value[i]);
+    if (row.media_id != 1) {
+      Modal.error({
+        title: "提示",
+        content: `广告位ID:${row.id},媒体类型不是头条,不能推送!`,
+      });
+      return false;
+    }
+  }
+  let siteIds = [];
+  for (let i = 0; i < selecteds.value.length; i++) {
+    let row = tableData.find((item) => item.id == selecteds.value[i]);
+    siteIds.push(row.id);
+  }
+
+  ttPacRef.value?.open();
+  ttPacRef.value?.setSiteIds(siteIds.join(","));
 };
 
 // 页面数据初始化

+ 205 - 0
src/views/v1/advert/agentSite/ks_pac.vue

@@ -0,0 +1,205 @@
+<template>
+  <component
+    is="a-modal"
+    v-model:visible="visible"
+    :width="tool.getDevice() === 'mobile' ? '100%' : '600px'"
+    :title="title"
+    :mask-closable="false"
+    :ok-loading="loading"
+    @cancel="close"
+    @before-ok="submit"
+    :footer="false"
+  >
+    <!-- 表单信息 start -->
+    <a-form
+      ref="formRef"
+      :model="formData"
+      :rules="rules"
+      :auto-label-width="true"
+    >
+      <a-form-item label="推送游戏" field="gamePackageId">
+        <a-select v-model="formData.gamePackageId" placeholder="请选择推送游戏">
+          <a-option
+            v-for="item in gamePackageOptions"
+            :key="item.id"
+            :value="item.id"
+            :label="item.name"
+          />
+        </a-select>
+      </a-form-item>
+
+      <a-form-item label="分包标识" field="remark">
+        <a-textarea v-model="formData.remark" placeholder="请输入分包标识" />
+      </a-form-item>
+      <a-form-item>
+        <a-space>
+          <a-button type="primary" @click="addGamePackage"
+            >生成分包标识</a-button
+          >
+          <a-button type="primary" @click="downloadExcel">下载excel</a-button>
+        </a-space>
+      </a-form-item>
+    </a-form>
+    <!-- 表单信息 end -->
+  </component>
+</template>
+
+<script setup>
+import { ref, reactive, computed } from "vue";
+import { Message, Modal } from "@arco-design/web-vue";
+import tool from "@/utils/tool";
+import api from "@/api/system/post";
+import { request } from "@/utils/request";
+import commonApi from "../../api/common";
+
+const emit = defineEmits(["success"]);
+
+// 引用定义
+const formRef = ref();
+const mode = ref("");
+const visible = ref(false);
+const loading = ref(false);
+const batchData = ref([]);
+const gamePackageOptions = ref([]);
+const isExport = ref(false);
+
+let title = computed(() => {
+  return "快手分包";
+});
+
+// 表单初始值
+const initialFormData = {
+  id: "",
+  gamePackageId: "",
+  remark: "",
+};
+
+// 表单信息
+const formData = reactive({ ...initialFormData });
+
+// 设置批量数据
+const setBatchData = async (data) => {
+  batchData.value = data;
+};
+
+// 验证规则
+const rules = {
+  game_id: [{ required: true, message: "推送游戏不能为空" }],
+};
+
+// 打开弹框
+const open = async (type = "ks") => {
+  mode.value = type;
+  // 重置表单数据
+  Object.assign(formData, initialFormData);
+  formRef.value.clearValidate();
+  formRef.value.resetFields();
+
+  visible.value = true;
+  await initPage();
+};
+
+// 初始化页面数据
+const initPage = async () => {
+  await getGamePackageOptions();
+};
+
+// 获取母包列表
+const getGamePackageOptions = async () => {
+  const res = await commonApi.getPackageOptionsApi({ media_id: 3 });
+  if (res.code === 200) {
+    gamePackageOptions.value = res.data;
+  }
+};
+
+// 生成分包标识
+const addGamePackage = async () => {
+  let data = [];
+  let gamePackage = gamePackageOptions.value.find(
+    (item) => item.id === formData.gamePackageId
+  );
+  for (let i = 0; i < batchData.value.length; i++) {
+    let row = batchData.value[i];
+    data.push(
+      `${gamePackage.game_id}_${row.agent_id}_${row.site_id},${gamePackage.name}-${row.site_id}`
+    );
+  }
+  formData.remark = data.join("\n");
+  console.log("生成分包标识", data);
+};
+
+// 下载excel
+const downloadExcel = async () => {
+  if (!formData.remark) {
+    Modal.error({
+      title: "提示",
+      content: "请先生成分包标识",
+    });
+    return;
+  }
+  console.log("下载excel");
+  // 导出
+  Message.info("请求服务器下载文件中...");
+  const data = formData.remark.split("\n");
+  const download = () =>
+    request({
+      url: "/v1/gameLog/AgentSite/exportGamePackageKs",
+      data: { title: title.value, data },
+      method: "post",
+      timeout: 60 * 1000,
+      responseType: "blob",
+    });
+  isExport.value = true;
+  download()
+    .then((res) => {
+      if (res && res.status == 200) {
+        tool.download(res);
+        Message.success("请求成功,文件开始下载");
+      } else {
+        Message.error("请前往服务端安装Excel导出库");
+      }
+    })
+    .catch(() => {
+      Message.error("请求服务器错误,下载失败");
+    })
+    .finally(() => {
+      isExport.value = false;
+    });
+};
+
+// 设置数据
+const setFormData = async (data) => {
+  for (const key in formData) {
+    if (data[key] != null && data[key] != undefined) {
+      formData[key] = data[key];
+    }
+  }
+};
+
+// 数据保存
+const submit = async (done) => {
+  const validate = await formRef.value?.validate();
+  if (!validate) {
+    loading.value = true;
+    let data = { ...formData };
+    let result = {};
+    // 生成标识
+
+    if (result.code === 200) {
+      Message.success("操作成功");
+      emit("success");
+      done(true);
+    }
+    // 防止连续点击提交
+    setTimeout(() => {
+      loading.value = false;
+    }, 500);
+  }
+  done(false);
+};
+
+// 关闭弹窗
+const close = () => (visible.value = false);
+
+defineExpose({ open, setFormData, setBatchData });
+</script>

+ 181 - 0
src/views/v1/advert/agentSite/tt_pac.vue

@@ -0,0 +1,181 @@
+<template>
+  <component
+    is="a-modal"
+    v-model:visible="visible"
+    :width="tool.getDevice() === 'mobile' ? '100%' : '600px'"
+    :title="title"
+    :mask-closable="false"
+    :ok-loading="loading"
+    @cancel="close"
+    @before-ok="submit"
+  >
+    <!-- 表单信息 start -->
+    <a-form
+      ref="formRef"
+      :model="formData"
+      :rules="rules"
+      :auto-label-width="true"
+    >
+      <a-form-item label="推送游戏" field="game_id">
+        <a-select v-model="formData.game_id" placeholder="请选择推送游戏">
+          <a-option
+            v-for="item in gamePackageOptions"
+            :key="item.game_id"
+            :value="item.game_id"
+            :label="item.name"
+          />
+        </a-select>
+      </a-form-item>
+
+      <a-form-item label="推送头条分包" field="fb">
+        <a-switch v-model="formData.fb" />
+      </a-form-item>
+
+      <a-form-item label="推送转化跟踪" field="zh">
+        <a-switch v-model="formData.zh" />
+      </a-form-item>
+
+      <a-form-item label="头条账号" field="advertiser_id">
+        <a-select v-model="formData.advertiser_id" placeholder="请选择头条账号">
+          <a-option
+            v-for="item in ttAccountOptions"
+            :key="item.advertiser_id"
+            :value="item.advertiser_id"
+            :label="item.advertiser_name"
+          />
+        </a-select>
+      </a-form-item>
+    </a-form>
+    <!-- 表单信息 end -->
+  </component>
+</template>
+
+<script setup>
+import { ref, reactive, computed } from "vue";
+import { Message, Modal } from "@arco-design/web-vue";
+import tool from "@/utils/tool";
+import api from "@/api/system/post";
+import { request } from "@/utils/request";
+import commonApi from "../../api/common";
+import agentSiteApi from "../../api/advert/agentSite";
+
+const emit = defineEmits(["success"]);
+
+// 引用定义
+const formRef = ref();
+const mode = ref("");
+const visible = ref(false);
+const loading = ref(false);
+const siteIds = ref();
+const ttAccountOptions = ref([]);
+const gamePackageOptions = ref([]);
+
+let title = computed(() => {
+  return "推送头条分包和转化";
+});
+
+// 表单初始值
+const initialFormData = {
+  id: "",
+  game_id: "",
+  fb: true,
+  zh: true,
+  remark: "",
+};
+
+// 表单信息
+const formData = reactive({ ...initialFormData });
+
+// 设置批量数据
+const setSiteIds = async (value) => {
+  siteIds.value = value;
+};
+
+// 验证规则
+const rules = {
+  game_id: [{ required: true, message: "推送游戏不能为空" }],
+  advertiser_id: [{ required: true, message: "头条账号不能为空" }],
+};
+
+// 打开弹框
+const open = async (type = "ks") => {
+  mode.value = type;
+  // 重置表单数据
+  Object.assign(formData, initialFormData);
+  formRef.value.clearValidate();
+  formRef.value.resetFields();
+
+  visible.value = true;
+  await initPage();
+};
+
+// 初始化页面数据
+const initPage = async () => {
+  await getGamePackageOptions();
+  await getTtAccountOptions();
+};
+
+// 获取母包列表
+const getGamePackageOptions = async () => {
+  const res = await commonApi.getPackageOptionsApi({ media_id: 1 });
+  if (res.code === 200) {
+    gamePackageOptions.value = res.data;
+  }
+};
+
+// 获取头条账号Options
+const getTtAccountOptions = async () => {
+  const res = await agentSiteApi.getTtAccountOptionsApi();
+  if (res.code === 200) {
+    ttAccountOptions.value = res.data;
+  }
+};
+
+// 设置数据
+const setFormData = async (data) => {
+  for (const key in formData) {
+    if (data[key] != null && data[key] != undefined) {
+      formData[key] = data[key];
+    }
+  }
+};
+
+// 数据保存
+const submit = async (done) => {
+  const validate = await formRef.value?.validate();
+  if (!validate) {
+    loading.value = true;
+    let data = { ...formData };
+    let result = {};
+
+    // 推送
+    result = await agentSiteApi.ttPushNewEventApi({
+      site_ids: siteIds.value,
+      game_id: formData.game_id,
+      fb: formData.fb,
+      zh: formData.zh,
+      advertiser_id: formData.advertiser_id,
+    });
+
+    if (result.code === 200) {
+      // Message.success("操作成功");
+      Modal.info({
+        title: "推送结果",
+        content: result.data.message,
+      });
+      emit("success");
+      done(true);
+    }
+    // 防止连续点击提交
+    setTimeout(() => {
+      loading.value = false;
+    }, 500);
+  }
+  done(false);
+};
+
+// 关闭弹窗
+const close = () => (visible.value = false);
+
+defineExpose({ open, setFormData, setSiteIds });
+</script>

+ 21 - 23
src/views/v1/api/advert/agenList.js

@@ -1,20 +1,19 @@
-import { request } from '@/utils/request.js'
+import { request } from "@/utils/request.js";
 
 /**
  * 渠道管理 API接口
  */
 export default {
-
   /**
    * 数据列表
    * @returns
    */
   getPageList(params = {}) {
     return request({
-      url: '/v1/advert/AgentList/index',
-      method: 'get',
-      params
-    })
+      url: "/v1/advert/AgentList/index",
+      method: "get",
+      params,
+    });
   },
 
   /**
@@ -23,10 +22,10 @@ export default {
    */
   save(params = {}) {
     return request({
-      url: '/v1/advert/AgentList/save',
-      method: 'post',
-      data: params
-    })
+      url: "/v1/advert/AgentList/save",
+      method: "post",
+      data: params,
+    });
   },
 
   /**
@@ -35,10 +34,10 @@ export default {
    */
   update(id, data = {}) {
     return request({
-      url: '/v1/advert/AgentList/update?id=' + id,
-      method: 'put',
-      data
-    })
+      url: "/v1/advert/AgentList/update?id=" + id,
+      method: "put",
+      data,
+    });
   },
 
   /**
@@ -47,9 +46,9 @@ export default {
    */
   read(id) {
     return request({
-      url: '/v1/advert/AgentList/read?id=' + id,
-      method: 'get'
-    })
+      url: "/v1/advert/AgentList/read?id=" + id,
+      method: "get",
+    });
   },
 
   /**
@@ -58,10 +57,9 @@ export default {
    */
   destroy(data) {
     return request({
-      url: '/v1/advert/AgentList/destroy',
-      method: 'delete',
-      data
-    })
+      url: "/v1/advert/AgentList/destroy",
+      method: "delete",
+      data,
+    });
   },
-
-}
+};

+ 53 - 22
src/views/v1/api/advert/agentSite.js

@@ -1,20 +1,19 @@
-import { request } from '@/utils/request.js'
+import { request } from "@/utils/request.js";
 
 /**
  * 广告位列表 API接口
  */
 export default {
-
   /**
    * 数据列表
    * @returns
    */
   getPageList(params = {}) {
     return request({
-      url: '/v1/advert/AgentSite/index',
-      method: 'get',
-      params
-    })
+      url: "/v1/advert/AgentSite/index",
+      method: "get",
+      params,
+    });
   },
 
   /**
@@ -23,10 +22,10 @@ export default {
    */
   save(params = {}) {
     return request({
-      url: '/v1/advert/AgentSite/save',
-      method: 'post',
-      data: params
-    })
+      url: "/v1/advert/AgentSite/save",
+      method: "post",
+      data: params,
+    });
   },
 
   /**
@@ -35,10 +34,10 @@ export default {
    */
   update(id, data = {}) {
     return request({
-      url: '/v1/advert/AgentSite/update?id=' + id,
-      method: 'put',
-      data
-    })
+      url: "/v1/advert/AgentSite/update?id=" + id,
+      method: "put",
+      data,
+    });
   },
 
   /**
@@ -47,9 +46,9 @@ export default {
    */
   read(id) {
     return request({
-      url: '/v1/advert/AgentSite/read?id=' + id,
-      method: 'get'
-    })
+      url: "/v1/advert/AgentSite/read?id=" + id,
+      method: "get",
+    });
   },
 
   /**
@@ -58,10 +57,42 @@ export default {
    */
   destroy(data) {
     return request({
-      url: '/v1/advert/AgentSite/destroy',
-      method: 'delete',
-      data
-    })
+      url: "/v1/advert/AgentSite/destroy",
+      method: "delete",
+      data,
+    });
+  },
+
+  /**
+   * 获取头条账号Options列表
+   * @returns
+   */
+  getTtAccountOptionsApi() {
+    return request({
+      url: "/v1/advert/AgentSite/getTtAccountOptions",
+      method: "get",
+    });
+  },
+
+  /**
+   * 导出分包标识数据
+   */
+  exportGamePackageKsApi(data = {}) {
+    return request({
+      url: "/v1/advert/AgentSite/exportGamePackageKs",
+      method: "post",
+      data,
+    });
   },
 
-}
+  /**
+   * 头条推送新事件
+   */
+  ttPushNewEventApi(data = {}) {
+    return request({
+      url: "/v1/advert/AgentSite/ttPushNewEvent",
+      method: "post",
+      data,
+    });
+  },
+};

+ 33 - 23
src/views/v1/api/gameLog/gamePackageLog.js

@@ -1,20 +1,19 @@
-import { request } from '@/utils/request.js'
+import { request } from "@/utils/request.js";
 
 /**
  * 打包记录 API接口
  */
 export default {
-
   /**
    * 数据列表
    * @returns
    */
   getPageList(params = {}) {
     return request({
-      url: '/v1/gameLog/GamePackLog/index',
-      method: 'get',
-      params
-    })
+      url: "/v1/gameLog/GamePackLog/index",
+      method: "get",
+      params,
+    });
   },
 
   /**
@@ -23,10 +22,22 @@ export default {
    */
   save(params = {}) {
     return request({
-      url: '/v1/gameLog/GamePackLog/save',
-      method: 'post',
-      data: params
-    })
+      url: "/v1/gameLog/GamePackLog/save",
+      method: "post",
+      data: params,
+    });
+  },
+
+  /**
+   * 批量打包
+   * @returns
+   */
+  batchSave(params = {}) {
+    return request({
+      url: "/v1/gameLog/GamePackLog/batchSave",
+      method: "post",
+      data: params,
+    });
   },
 
   /**
@@ -35,10 +46,10 @@ export default {
    */
   update(id, data = {}) {
     return request({
-      url: '/v1/gameLog/GamePackLog/update?id=' + id,
-      method: 'put',
-      data
-    })
+      url: "/v1/gameLog/GamePackLog/update?id=" + id,
+      method: "put",
+      data,
+    });
   },
 
   /**
@@ -47,9 +58,9 @@ export default {
    */
   read(id) {
     return request({
-      url: '/v1/gameLog/GamePackLog/read?id=' + id,
-      method: 'get'
-    })
+      url: "/v1/gameLog/GamePackLog/read?id=" + id,
+      method: "get",
+    });
   },
 
   /**
@@ -58,10 +69,9 @@ export default {
    */
   destroy(data) {
     return request({
-      url: '/v1/gameLog/GamePackLog/destroy',
-      method: 'delete',
-      data
-    })
+      url: "/v1/gameLog/GamePackLog/destroy",
+      method: "delete",
+      data,
+    });
   },
-
-}
+};

+ 5 - 2
src/views/v1/gameLog/gamePackage/index.vue

@@ -43,6 +43,9 @@
       </template>
 
       <!-- Table 自定义渲染 -->
+      <template #letter="{ record }">
+        {{ record.game_id }}_{{ record.letter }}
+      </template>
     </sa-table>
 
     <!-- 编辑表单 -->
@@ -109,8 +112,8 @@ const columns = reactive([
   { title: "母包名称", dataIndex: "name", width: 220 },
   { title: "打包目录", dataIndex: "letter", width: 120 },
   { title: "包名", dataIndex: "package_name", width: 180 },
-  { title: "媒体APPID", dataIndex: "appid", width: 180 },
-  { title: "账号ID", dataIndex: "advertiser_id", width: 180 },
+  { title: "APPID(头条)", dataIndex: "tt_appid", width: 180 },
+  { title: "账号ID(头条)", dataIndex: "tt_advertiser_id", width: 180 },
 ]);
 
 // 页面数据初始化

+ 23 - 18
src/views/v1/gameLog/gamePackageLog/edit.vue

@@ -94,17 +94,16 @@ let title = computed(() => {
 const initialFormData = {
   id: null,
   package_id: null,
-  game_id: null,
   letter: "",
-  agent_id: null,
-  site_id: null,
   icon: "",
-  status: null,
 };
 
 // 表单信息
 const formData = reactive({ ...initialFormData });
 
+// 批量打包数据
+const batchData = ref([]);
+
 // 验证规则
 const rules = {
   package_id: [{ required: true, message: "母包ID必需填写" }],
@@ -142,22 +141,17 @@ const getGameOptions = async () => {
   }
 };
 
-// 设置数据
-const setFormData = async (data) => {
-  for (const key in formData) {
-    if (data[key] != null && data[key] != undefined) {
-      formData[key] = data[key];
-    }
-  }
+// 设置批量打包数据
+const setBatchData = async (data) => {
+  batchData.value = data;
 };
 
 // 获取母包详情
 const getPackageDetail = async (id) => {
-  const resp = await gamePackageApi.read(id);
-  if (resp.code === 200) {
-    formData.letter = resp.data.letter;
-    formData.game_id = resp.data.game_id;
-  }
+  let row = packageOptions.value.find((item) => item.id == id);
+  formData.letter = row.letter;
+  formData.game_id = row.game_id;
+  formData.package_id = row.id;
 };
 
 // 数据保存
@@ -168,9 +162,20 @@ const submit = async (done) => {
     let data = { ...formData };
     let result = {};
     if (mode.value === "add") {
+      let postData = [];
       // 添加数据
       data.id = undefined;
-      result = await api.save(data);
+      // 批量打包
+      if (batchData.value.length > 0) {
+        for (let i = 0; i < batchData.value.length; i++) {
+          let item = batchData.value[i];
+          postData.push({
+            ...data,
+            ...item,
+          });
+        }
+        result = await api.batchSave(postData);
+      }
     } else {
       // 修改数据
       result = await api.update(data.id, data);
@@ -191,5 +196,5 @@ const submit = async (done) => {
 // 关闭弹窗
 const close = () => (visible.value = false);
 
-defineExpose({ open, setFormData });
+defineExpose({ open, setBatchData });
 </script>

+ 17 - 2
src/views/v1/gameLog/gamePackageLog/index.vue

@@ -19,6 +19,14 @@
         </a-col>
       </template>
 
+      <template #site_id="{ record }">
+        [{{ record.site_id }}] {{ record.site_name }}
+      </template>
+
+      <template #agent_id="{ record }">
+        [{{ record.agent_id }}] {{ record.agent_name }}
+      </template>
+
       <!-- Table 自定义渲染 -->
     </sa-table>
 
@@ -47,6 +55,7 @@ const searchForm = ref({
 const options = reactive({
   api: api.getPageList,
   rowSelection: { showCheckedAll: true },
+  operationColumn: false,
   add: {
     show: false,
     auth: ["/v1/gameLog/GamePackLog/save"],
@@ -78,11 +87,17 @@ const options = reactive({
 // SaTable 列配置
 const columns = reactive([
   { title: "广告位ID", dataIndex: "site_id", width: 120 },
-  { title: "渠道ID", dataIndex: "agent_id", width: 120, dict: "agent_list" },
+  { title: "渠道ID", dataIndex: "agent_id", width: 120 },
   { title: "母包名称", dataIndex: "package_name", width: 240 },
   { title: "目录", dataIndex: "letter", width: 180 },
   { title: "icon", dataIndex: "icon", type: "image", width: 120 },
-  { title: "状态", dataIndex: "status", width: 180, dict: "package_status" },
+  {
+    title: "状态",
+    dataIndex: "status",
+    type: "dict",
+    dict: "package_status",
+    width: 180,
+  },
   { title: "创建时间", dataIndex: "create_time", width: 180, type: "date" },
   { title: "更新时间", dataIndex: "update_time", width: 180, type: "date" },
 ]);