pudongliang 4 месяцев назад
Родитель
Сommit
a759ba3ff7
33 измененных файлов с 580 добавлено и 147 удалено
  1. 1 1
      portal/dist/assets/accountGroup-D5BVVYC-.js
  2. 1 0
      portal/dist/assets/adPlanConf-B2AMh7LC.js
  3. 0 1
      portal/dist/assets/adPlanConf-CI3n-C42.js
  4. 1 1
      portal/dist/assets/auth-BG9T5TeO.js
  5. 1 1
      portal/dist/assets/conversion-I_E-Xf3z.js
  6. 0 0
      portal/dist/assets/detail-CBxFMQ1J.js
  7. 0 0
      portal/dist/assets/detail-CSztW6DS.js
  8. 1 1
      portal/dist/assets/drama-ip2vqI6Z.js
  9. 0 0
      portal/dist/assets/index-BKez29zS.js
  10. 0 0
      portal/dist/assets/index-BUV6YVYL.js
  11. 0 0
      portal/dist/assets/index-Bp2sCRIy.js
  12. 0 0
      portal/dist/assets/index-C7lrjIzZ.js
  13. 0 0
      portal/dist/assets/index-CF5CVDrR.js
  14. 0 0
      portal/dist/assets/index-CPOKnn_X.js
  15. 0 0
      portal/dist/assets/index-D8STC3Us.js
  16. 0 0
      portal/dist/assets/index-DC0wtMgG.js
  17. 0 0
      portal/dist/assets/index-DDhUBKxm.js
  18. 1 1
      portal/dist/assets/index-DuzzreWw.js
  19. 0 0
      portal/dist/assets/index-S53wAHkf.js
  20. 0 0
      portal/dist/assets/index-mLIJT9s3.js
  21. 1 1
      portal/dist/assets/ossFile-BmNYIa3l.js
  22. 0 0
      portal/dist/assets/request-DLbisFwp.js
  23. 1 1
      portal/dist/assets/user-CSEJNVe3.js
  24. 1 1
      portal/dist/index.html
  25. 19 3
      portal/src/api/adPlanConf.js
  26. 133 4
      portal/src/views/ad-plan-conf/detail.vue
  27. 2 2
      portal/vite.config.js
  28. 54 7
      src/main/java/com/moka/gdtauto/controller/AdPlanConfController.java
  29. 6 0
      src/main/java/com/moka/gdtauto/entity/AdPlan.java
  30. 5 0
      src/main/java/com/moka/gdtauto/entity/AdPlanConf.java
  31. 5 0
      src/main/java/com/moka/gdtauto/entity/AdPlanCreative.java
  32. 4 3
      src/main/java/com/moka/gdtauto/service/AdPlanConfService.java
  33. 343 119
      src/main/java/com/moka/gdtauto/service/impl/AdPlanConfServiceImpl.java

+ 1 - 1
portal/dist/assets/accountGroup-D7rbsEFD.js → portal/dist/assets/accountGroup-D5BVVYC-.js

@@ -1 +1 @@
-import{r as u}from"./request-CXIq51ov.js";function c(t){return u({url:"/api/account-group/create",method:"post",data:t})}function e(t){return u({url:"/api/account-group/update",method:"post",data:t})}function n(t){return u({url:`/api/account-group/${t}`,method:"delete"})}function a(t=1,o=10){return u({url:"/api/account-group/list",method:"get",params:{pageNum:t,pageSize:o}})}function p(){return u({url:"/api/account-group/all",method:"get"})}function i(t){return u({url:`/api/account-group/${t}/accounts`,method:"get"})}export{i as a,p as b,c,n as d,a as g,e as u};
+import{r as u}from"./request-DLbisFwp.js";function c(t){return u({url:"/api/account-group/create",method:"post",data:t})}function e(t){return u({url:"/api/account-group/update",method:"post",data:t})}function n(t){return u({url:`/api/account-group/${t}`,method:"delete"})}function a(t=1,o=10){return u({url:"/api/account-group/list",method:"get",params:{pageNum:t,pageSize:o}})}function p(){return u({url:"/api/account-group/all",method:"get"})}function i(t){return u({url:`/api/account-group/${t}/accounts`,method:"get"})}export{i as a,p as b,c,n as d,a as g,e as u};

+ 1 - 0
portal/dist/assets/adPlanConf-B2AMh7LC.js

@@ -0,0 +1 @@
+import{r as a}from"./request-DLbisFwp.js";function r(n){return a({url:"/api/ad-plan-conf/reCreate",method:"post",data:n})}function d(n){return a({url:"/api/ad-plan-conf/generate-plan",method:"post",data:n})}function o(n){return a({url:`/api/ad-plan-conf/reGeneratePlan/${n}`,method:"get"})}function l(n){return a({url:`/api/ad-plan-conf/syncSystemStatus/${n}`,method:"get"})}function u(n){return a({url:"/api/ad-plan-conf/create",method:"post",data:n})}function p(n){return a({url:"/api/ad-plan-conf/update",method:"post",data:n})}function s(n=1,t=10){return a({url:"/api/ad-plan-conf/list",method:"get",params:{pageNum:n,pageSize:t}})}function f(n){return a({url:`/api/ad-plan-conf/${n}`,method:"get"})}function i(n){return a({url:"/api/ad-plan/list",method:"get",params:n})}function c(n){return a({url:`/api/ad-plan-creative/plan/${n}`,method:"get"})}function m(n){return a({url:"/api/ad-plan-conf/gdtSuspendByConfId",params:{confId:n},method:"get"})}function g(n){return a({url:"/api/ad-plan-conf/gdtDeleteByConfId",params:{confId:n},method:"get"})}function h(n,t){return a({url:`/api/ad-plan-conf/gdtSuspendByPlanIds/${n}`,method:"post",data:t})}function P(n,t){return a({url:`/api/ad-plan-conf/gdtDeleteByPlanIds/${n}`,method:"post",data:t})}export{d as a,f as b,u as c,i as d,g as e,h as f,s as g,P as h,l as i,o as j,c as k,r,m as s,p as u};

+ 0 - 1
portal/dist/assets/adPlanConf-CI3n-C42.js

@@ -1 +0,0 @@
-import{r as a}from"./request-CXIq51ov.js";function r(n){return a({url:"/api/ad-plan-conf/reCreate",method:"post",data:n})}function o(n){return a({url:"/api/ad-plan-conf/generate-plan",method:"post",data:n})}function u(n){return a({url:`/api/ad-plan-conf/reGeneratePlan/${n}`,method:"get"})}function d(n){return a({url:`/api/ad-plan-conf/syncSystemStatus/${n}`,method:"get"})}function s(n){return a({url:"/api/ad-plan-conf/create",method:"post",data:n})}function l(n){return a({url:"/api/ad-plan-conf/update",method:"post",data:n})}function p(n=1,t=10){return a({url:"/api/ad-plan-conf/list",method:"get",params:{pageNum:n,pageSize:t}})}function i(n){return a({url:`/api/ad-plan-conf/${n}`,method:"get"})}function f(n){return a({url:"/api/ad-plan/list",method:"get",params:n})}function c(n){return a({url:`/api/ad-plan-creative/plan/${n}`,method:"get"})}function m(n){return a({url:"/api/ad-plan-conf/suspendByConfId",params:{confId:n},method:"get"})}function g(n,t){return a({url:`/api/ad-plan-conf/suspendByPlanIds/${n}`,method:"post",data:t})}export{o as a,i as b,s as c,f as d,g as e,d as f,p as g,u as h,c as i,r,m as s,l as u};

+ 1 - 1
portal/dist/assets/auth-BZSOUw1f.js → portal/dist/assets/auth-BG9T5TeO.js

@@ -1 +1 @@
-import{r as t}from"./request-CXIq51ov.js";function i(){return t({url:"/api/gdt/auth/authorize-url",method:"get"})}function n(r){return t({url:"/api/gdt/auth/refresh",method:"post",params:r})}function u(){return t({url:"/api/gdt/auth/list",method:"get"})}function a(){return u()}function o(){return t({url:"/api/gdt/auth/expiring",method:"get"})}export{o as a,a as b,i as g,u as l,n as r};
+import{r as t}from"./request-DLbisFwp.js";function i(){return t({url:"/api/gdt/auth/authorize-url",method:"get"})}function n(r){return t({url:"/api/gdt/auth/refresh",method:"post",params:r})}function u(){return t({url:"/api/gdt/auth/list",method:"get"})}function a(){return u()}function o(){return t({url:"/api/gdt/auth/expiring",method:"get"})}export{o as a,a as b,i as g,u as l,n as r};

+ 1 - 1
portal/dist/assets/conversion-BUAwWA1R.js → portal/dist/assets/conversion-I_E-Xf3z.js

@@ -1 +1 @@
-import{r as t}from"./request-CXIq51ov.js";function e(n,o){return t({url:"/api/gdt/conversion/sync",method:"post",params:{orgAccountId:n,accountId:o}})}function s(n=1,o=20){return t({url:"/api/gdt/conversion/list",method:"get",params:{page:n,pageSize:o}})}function i(n){return t({url:"/api/gdt/conversion/detail",method:"get",params:{conversionId:n}})}function a(){return t({url:"/api/gdt/conversion/all",method:"get"})}export{s as a,i as b,a as g,e as s};
+import{r as t}from"./request-DLbisFwp.js";function e(n,o){return t({url:"/api/gdt/conversion/sync",method:"post",params:{orgAccountId:n,accountId:o}})}function s(n=1,o=20){return t({url:"/api/gdt/conversion/list",method:"get",params:{page:n,pageSize:o}})}function i(n){return t({url:"/api/gdt/conversion/detail",method:"get",params:{conversionId:n}})}function a(){return t({url:"/api/gdt/conversion/all",method:"get"})}export{s as a,i as b,a as g,e as s};

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/detail-CBxFMQ1J.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/detail-CSztW6DS.js


+ 1 - 1
portal/dist/assets/drama-DbDVW1CF.js → portal/dist/assets/drama-ip2vqI6Z.js

@@ -1 +1 @@
-import{r as t}from"./request-CXIq51ov.js";function n(a){return t({url:"/api/gdt/asset/drama/sync",method:"post",params:{accountId:a}})}function m(a=1,s=20,r=""){return t({url:"/api/gdt/asset/drama/list",method:"get",params:{dramaName:r,page:a,pageSize:s}})}function d(a){return t({url:"/api/gdt/asset/drama/myDramaAssets",method:"get",params:{dramaName:a}})}function o(){return t({url:"/api/gdt/asset/drama/sync/conf/myConf",method:"get"})}function u(a){return t({url:"/api/gdt/asset/drama/sync/conf/add",method:"post",data:a})}function i(a){return t({url:"/api/gdt/asset/drama/sync/conf/delete",method:"post",params:{id:a}})}export{o as a,u as b,i as d,m as g,d as m,n as s};
+import{r as t}from"./request-DLbisFwp.js";function n(a){return t({url:"/api/gdt/asset/drama/sync",method:"post",params:{accountId:a}})}function m(a=1,s=20,r=""){return t({url:"/api/gdt/asset/drama/list",method:"get",params:{dramaName:r,page:a,pageSize:s}})}function d(a){return t({url:"/api/gdt/asset/drama/myDramaAssets",method:"get",params:{dramaName:a}})}function o(){return t({url:"/api/gdt/asset/drama/sync/conf/myConf",method:"get"})}function u(a){return t({url:"/api/gdt/asset/drama/sync/conf/add",method:"post",data:a})}function i(a){return t({url:"/api/gdt/asset/drama/sync/conf/delete",method:"post",params:{id:a}})}export{o as a,u as b,i as d,m as g,d as m,n as s};

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/index-BKez29zS.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/index-BUV6YVYL.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/index-Bp2sCRIy.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/index-C7lrjIzZ.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/index-CF5CVDrR.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/index-CPOKnn_X.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/index-D8STC3Us.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/index-DC0wtMgG.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/index-DDhUBKxm.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
portal/dist/assets/index-DuzzreWw.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/index-S53wAHkf.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/index-mLIJT9s3.js


+ 1 - 1
portal/dist/assets/ossFile-Bf1xorcM.js → portal/dist/assets/ossFile-BmNYIa3l.js

@@ -1 +1 @@
-import{r as t}from"./request-CXIq51ov.js";function i(e){return t({timeout:3e5,url:"/api/oss-file/upload",method:"post",data:e,headers:{"Content-Type":"multipart/form-data"}})}function o(e){return t({url:"/api/oss-file/list",method:"get",params:e})}function r(e){return t({url:`/api/oss-file/${e}`,method:"delete"})}function l(e){return t({url:"/api/oss-file/batch",method:"delete",params:{fileIds:e}})}export{l as b,r as d,o as g,i as u};
+import{r as t}from"./request-DLbisFwp.js";function i(e){return t({timeout:3e5,url:"/api/oss-file/upload",method:"post",data:e,headers:{"Content-Type":"multipart/form-data"}})}function o(e){return t({url:"/api/oss-file/list",method:"get",params:e})}function r(e){return t({url:`/api/oss-file/${e}`,method:"delete"})}function l(e){return t({url:"/api/oss-file/batch",method:"delete",params:{fileIds:e}})}export{l as b,r as d,o as g,i as u};

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
portal/dist/assets/request-DLbisFwp.js


+ 1 - 1
portal/dist/assets/user-xPLDcMxJ.js → portal/dist/assets/user-CSEJNVe3.js

@@ -1 +1 @@
-import{r as e}from"./request-CXIq51ov.js";function s(){return e({url:"/api/user/list",method:"get"})}function u(r){return e({url:"/api/user/info",method:"get",params:r})}function n(r){return e({url:"/api/user/user-token-url",method:"get",params:r})}function o(r){return e({url:"/api/user/login",method:"post",params:r})}function a(r){return e({url:"/api/user/change-password",method:"post",params:r})}export{u as a,s as b,a as c,n as g,o as l};
+import{r as e}from"./request-DLbisFwp.js";function s(){return e({url:"/api/user/list",method:"get"})}function u(r){return e({url:"/api/user/info",method:"get",params:r})}function n(r){return e({url:"/api/user/user-token-url",method:"get",params:r})}function o(r){return e({url:"/api/user/login",method:"post",params:r})}function a(r){return e({url:"/api/user/change-password",method:"post",params:r})}export{u as a,s as b,a as c,n as g,o as l};

+ 1 - 1
portal/dist/index.html

@@ -5,7 +5,7 @@
     <link rel="icon" type="image/svg+xml" href="/vite.svg" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>腾讯广告自动化管理后台</title>
-    <script type="module" crossorigin src="/assets/index-_BAzpnfB.js"></script>
+    <script type="module" crossorigin src="/assets/index-DuzzreWw.js"></script>
     <link rel="stylesheet" crossorigin href="/assets/index-CdDwsIxv.css">
   </head>
   <body>

+ 19 - 3
portal/src/api/adPlanConf.js

@@ -119,7 +119,15 @@ export function getAdPlanCreativesByPlanId(planId) {
 
 export function suspendByConfId(confId) {
   return request({
-    url: `/api/ad-plan-conf/suspendByConfId`,
+    url: `/api/ad-plan-conf/gdtSuspendByConfId`,
+    params: { confId },
+    method: 'get'
+  })
+}
+
+export function deleteByConfId(confId) {
+  return request({
+    url: `/api/ad-plan-conf/gdtDeleteByConfId`,
     params: { confId },
     method: 'get'
   })
@@ -127,8 +135,16 @@ export function suspendByConfId(confId) {
 
 export function suspendByPlanIds(confId, ids) {
   return request({
-    url: `/api/ad-plan-conf/suspendByPlanIds/${confId}`,
+    url: `/api/ad-plan-conf/gdtSuspendByPlanIds/${confId}`,
     method: 'post',
     data: ids
   })
-}
+}
+
+export function deleteByPlanIds(confId, ids) {
+  return request({
+    url: `/api/ad-plan-conf/gdtDeleteByPlanIds/${confId}`,
+    method: 'post',
+    data: ids
+  })
+}

+ 133 - 4
portal/src/views/ad-plan-conf/detail.vue

@@ -19,6 +19,9 @@
           <el-button type="danger" @click="handleSuspendAll(confDetail.id)">
             <el-icon><SwitchButton /></el-icon>
             全部暂停</el-button>
+            <el-button type="danger" @click="handleDeleteAll(confDetail.id)">
+            <el-icon><DeleteFilled /></el-icon>
+            全部删除</el-button>
           <el-button type="primary" @click="handleRefresh(confDetail.id)">
             <el-icon><Refresh /></el-icon>
             刷新状态</el-button>
@@ -34,9 +37,15 @@
           </div>
           <div>
             <div class="text-sm text-gray-500 mb-1">状态</div>
-            <el-tag :type="getPlanStatusColor(confDetail.status)" size="large">
+            <el-tag :type="getPlanStatusColor(confDetail.status)" size="large" style="margin-right: 8px;">
               {{ getPlanStatusText(confDetail.status) }}
             </el-tag>
+            <el-tag v-if="confDetail.systemSuspendProcessStatus > 0" :type="getSuspendStatusColor(confDetail.systemSuspendProcessStatus)" size="large" style="margin-right: 8px;">
+              {{ getSuspendStatusText(confDetail.systemSuspendProcessStatus) }}
+            </el-tag>
+            <el-tag v-if="confDetail.systemDeleteProcessStatus > 0" :type="getSuspendStatusColor(confDetail.systemDeleteProcessStatus)" size="large">
+              {{ getDeleteStatusText(confDetail.systemDeleteProcessStatus) }}
+            </el-tag>
           </div>
         </div>
 
@@ -167,6 +176,9 @@
           <el-button type="warning" @click="handleSuspendPlans(confDetail.id)">
             <el-icon><SwitchButton /></el-icon>
             暂停选中计划</el-button>
+            <el-button type="warning" @click="handleDeletePlans(confDetail.id)">
+            <el-icon><DeleteFilled /></el-icon>
+            删除选中计划</el-button>
            <el-button type="primary" @click="handleSystemRefresh(confDetail.id)">
             <el-icon><Refresh /></el-icon>
             同步平台状态</el-button>
@@ -275,6 +287,11 @@
                   </template>
                 </el-table-column>
                 <el-table-column prop="buttonText" label="按钮文案" width="120" />
+                <el-table-column label="设置状态" prop="configuredStatus" width="100" >
+                  <template #default="{ row }">
+                    {{ getConfiguredStatusText(row.configuredStatus) }}
+                  </template>
+                </el-table-column>
                 <el-table-column prop="approvalStatus" label="审核状态" width="120" show-overflow-tooltip />
                 <el-table-column label="系统删除" prop="systemDelete" width="85" >
                   <template #default="{ row }">
@@ -332,6 +349,11 @@
             </el-tag>
           </template>
         </el-table-column>
+        <el-table-column label="设置状态" prop="configuredStatus" width="100" >
+          <template #default="{ row }">
+            {{ getConfiguredStatusText(row.configuredStatus) }}
+          </template>
+        </el-table-column>
         <el-table-column label="失败原因" min-width="200" show-overflow-tooltip>
           <template #default="{ row }">
             <span class="text-red-500">{{ row.failReason || '-' }}</span>
@@ -370,7 +392,7 @@
 <script setup>
 import { ref, onMounted, computed } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
-import { ElMessage } from 'element-plus'
+import { ElMessage, ElMessageBox } from 'element-plus'
 import { 
   getAdPlanConfDetail, 
   getAdPlanList, 
@@ -378,6 +400,8 @@ import {
   getAdPlanCreativesByPlanId,
   syncSystemStatus,
     suspendByConfId,
+    deleteByConfId,
+    deleteByPlanIds,
   suspendByPlanIds
 } from '@/api/adPlanConf'
 
@@ -558,6 +582,44 @@ const getPlanStatusColor = (status) => {
   return map[status] || ''
 }
 
+//0 未暂停 1 暂停中 2 暂停完毕 3 暂停失败 
+const getSuspendStatusColor = (status) => {
+  const map = {
+    1: 'warning',
+    2: 'success',
+    3: 'danger',
+  }
+  return map[status] || ''
+}
+
+const getSuspendStatusText = (status) => {
+  const map = {
+    1: '暂停中',
+    2: '暂停完毕',
+    3: '暂停失败'
+  }
+  return map[status] || '未知'
+}
+
+const getDeleteStatusText = (status) => {
+  const map = {
+    1: '删除中',
+    2: '删除成功',
+    3: '删除失败'
+  }
+  return map[status] || '未知'
+}
+
+//AD_STATUS_NORMAL 有效
+// AD_STATUS_SUSPEND 暂停
+const getConfiguredStatusText = (status) => {
+  const map = {
+    1: '有效',
+    2: '暂停'
+  }
+  return map[status] || '未知'
+}
+
 // 格式化日期
 const formatDate = (dateStr) => {
   if (!dateStr) return '-'
@@ -580,11 +642,20 @@ const handleRefresh = async () => {
 
 const handleSuspendAll = async (confId) => {
   try {
+    await ElMessageBox.confirm(
+      `确定要暂停配置"${confDetail.value.name}"吗?`,
+      '提示',
+      {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }
+    )
     const res = await suspendByConfId(confId)
     if (res.success) {
       handleRefresh()
     } else {
-      ElMessage.error(res.msg || '全部暂停失败')
+      ElMessage.error(res.msg || '暂停中。。。')
     }
   } catch (error) {
     console.error('全部暂停失败:', error)
@@ -592,8 +663,40 @@ const handleSuspendAll = async (confId) => {
   }
 }
 
+const handleDeleteAll = async (confId) => {
+  try {
+    await ElMessageBox.confirm(
+      `确定要删除配置"${confDetail.value.name}"吗?`,
+      '提示',
+      {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }
+    )
+    const res = await deleteByConfId(confId)
+    if (res.success) {
+      handleRefresh()
+    } else {
+      ElMessage.error(res.msg || '删除中。。。')
+    }
+  } catch (error) {
+    console.error('全部删除失败:', error)
+    ElMessage.error('全部删除失败')
+  }
+}
+
 const handleSuspendPlans = async (confId) => {
   try {
+    await ElMessageBox.confirm(
+      `确定要暂停配置"${confDetail.value.name}"吗?`,
+      '提示',
+      {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }
+    )
     if (selectedRows.value.length < 1) {
       return
     }
@@ -601,7 +704,7 @@ const handleSuspendPlans = async (confId) => {
     if (res.success) {
       handleRefresh()
     } else {
-      ElMessage.error(res.msg || '暂停失败')
+      ElMessage.error(res.msg || '暂停中。。。')
     }
   } catch (error) {
     console.error('暂停失败:', error)
@@ -609,6 +712,32 @@ const handleSuspendPlans = async (confId) => {
   }
 }
 
+const handleDeletePlans = async (confId) => {
+  try {
+    await ElMessageBox.confirm(
+      `确定要删除配置"${confDetail.value.name}"吗?`,
+      '提示',
+      {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }
+    )
+    if (selectedRows.value.length < 1) {
+      return
+    }
+    const res = await deleteByPlanIds(confId, selectedRows.value.map(r => r.id))
+    if (res.success) {
+      handleRefresh()
+    } else {
+      ElMessage.error(res.msg || '删除中。。。')
+    }
+  } catch (error) {
+    console.error('删除失败:', error)
+    ElMessage.error('删除失败')
+  }
+}
+
 const handleSystemRefresh = async (confId) => {
   try {
     const res = await syncSystemStatus(confId)

+ 2 - 2
portal/vite.config.js

@@ -14,8 +14,8 @@ export default defineConfig({
     port: 5173,
     proxy: {
       '/api': {
-        //target: 'http://localhost:8080',
-        target: 'https://ad-auto.mokamrp.com/api',
+        target: 'http://localhost:8080',
+        //target: 'https://ad-auto.mokamrp.com/api',
         changeOrigin: true,
         rewrite: (path) => path.replace(/^\/api/, '')
       }

+ 54 - 7
src/main/java/com/moka/gdtauto/controller/AdPlanConfController.java

@@ -62,18 +62,65 @@ public class AdPlanConfController {
     private final TencentAssetDramaMapper tencentAssetDramaMapper;
 
 
-    @GetMapping("/suspendByConfId")
-    public Result<Void> suspendByConfId(@NotNull Long confId) {
-        adPlanConfService.suspendByConfId(confId);
-        return Result.success("全部暂停成功");
+    @GetMapping("/gdtSuspendByConfId")
+    public Result<Void> gdtSuspendByConfId(@NotNull Long confId) {
+        AdPlanConf adPlanConf = adPlanConfService.getById(confId);
+        if (adPlanConf == null) {
+            return Result.fail("广告计划配置不存在");
+        }
+        adPlanConfService.gdtSuspendByConf(adPlanConf);
+        adPlanConfService.lambdaUpdate()
+        .eq(AdPlanConf::getId, confId)
+        .eq(AdPlanConf::getSystemSuspendProcessStatus, 1)
+        .update();
+        return Result.success("暂停执行中");
+    }
+
+    @PostMapping("/gdtSuspendByPlanIds/{confId}")
+    public Result<Void> gdtSuspendByPlanIds (@PathVariable Long confId, @RequestBody Long planIds){
+        if (planIds == null) {
+            return  Result.success("请选择要暂停广告");
+        }
+        AdPlanConf adPlanConf = adPlanConfService.getById(confId);
+        if (adPlanConf == null) {
+            return Result.fail("广告计划配置不存在");
+        }
+        adPlanConfService.gdtSuspendByPlanIds(adPlanConf, planIds);
+        adPlanConfService.lambdaUpdate()
+        .eq(AdPlanConf::getId, confId)
+        .eq(AdPlanConf::getSystemSuspendProcessStatus, 1)
+        .update();
+        return Result.success();
+    }
+
+    @GetMapping("/gdtDeleteByConfId")
+    public Result<Void> gdtDeleteByConfId(@NotNull Long confId) {
+        AdPlanConf adPlanConf = adPlanConfService.getById(confId);
+        if (adPlanConf == null) {
+            return Result.fail("广告计划配置不存在");
+        }
+        adPlanConfService.gdtDeleteByConf(adPlanConf);
+        adPlanConfService.lambdaUpdate()
+        .eq(AdPlanConf::getId, confId)
+        .eq(AdPlanConf::getSystemSuspendProcessStatus, 1)
+        .update();
+        return Result.success("暂停执行中");
     }
 
-    @PostMapping("/suspendByPlanIds/{confId}")
-    public Result<Void> suspendByPlanIds (@PathVariable Long confId, @RequestBody Long planIds){
+    @PostMapping("/gdtDeleteByPlanIds/{confId}")
+    public Result<Void> gdtDeleteByPlanIds (@PathVariable Long confId, @RequestBody Long planIds){
         if (planIds == null) {
             return  Result.success("请选择要暂停广告");
         }
-        adPlanConfService.suspendByPlanIds(confId, planIds);
+        AdPlanConf adPlanConf = adPlanConfService.getById(confId);
+        if (adPlanConf == null) {
+            return Result.fail("广告计划配置不存在");
+        }
+        adPlanConfService.gdtDeleteByPlanIds(adPlanConf, planIds);
+        adPlanConfService.lambdaUpdate()
+        .eq(AdPlanConf::getId, confId)
+        .eq(AdPlanConf::getSystemSuspendProcessStatus, 1)
+        .update();
         return Result.success();
     }
 

+ 6 - 0
src/main/java/com/moka/gdtauto/entity/AdPlan.java

@@ -96,7 +96,13 @@ public class AdPlan {
      */
     private Integer status;
 
+    
+    /**
+     * 客户设置的状态
+     */
+    private String configuredStatus;
     private String systemStatus;
+    // 是否已删除,true:是,false:否
     private String systemDelete;
 
     /**

+ 5 - 0
src/main/java/com/moka/gdtauto/entity/AdPlanConf.java

@@ -119,6 +119,11 @@ public class AdPlanConf {
     private String failReason;
     private LocalDateTime successTime;
 
+    //0 未删除 1 删除中 2 删除完毕 3 删除失败
+    private Integer systemDeleteProcessStatus;
+    //0 未暂停 1 暂停中 2 暂停完毕 3 暂停失败 
+    private Integer systemSuspendProcessStatus;
+
     /**
      * 用户ID
      */

+ 5 - 0
src/main/java/com/moka/gdtauto/entity/AdPlanCreative.java

@@ -70,6 +70,11 @@ public class AdPlanCreative {
      * 计划状态:1-待执行,2-执行中,3-失败,4-已结束
      */
     private Integer status;
+
+    /**
+     * 客户设置的状态
+     */
+    private String configuredStatus;
     /**
      * 审批状态
      */

+ 4 - 3
src/main/java/com/moka/gdtauto/service/AdPlanConfService.java

@@ -66,7 +66,8 @@ public interface AdPlanConfService extends IService<AdPlanConf> {
 
     void asyncReGeneratePlan(Long id);
 
-    void suspendByConfId(@NotNull Long confId);
-
-    void suspendByPlanIds(Long confId, Long planIds);
+    void gdtDeleteByConf(AdPlanConf conf);
+    void gdtSuspendByConf(AdPlanConf conf);
+    void gdtDeleteByPlanIds(AdPlanConf conf, Long planIds);
+    void gdtSuspendByPlanIds(AdPlanConf conf, Long planIds);
 }

+ 343 - 119
src/main/java/com/moka/gdtauto/service/impl/AdPlanConfServiceImpl.java

@@ -21,6 +21,7 @@ import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import java.util.ArrayList;
 import com.moka.gdtauto.entity.AdPlan;
@@ -47,7 +48,6 @@ import java.security.MessageDigest;
 import java.util.Base64;
 import com.moka.gdtauto.common.Constant;
 
-
 /**
  * 广告计划配置服务实现类
  *
@@ -69,66 +69,284 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
     @Autowired
     private TencentAccountService tencentAccountService;
 
+    @Async
     @Override
-    public void suspendByConfId(Long confId) {
-        AdPlanConf conf = this.getById(confId);
-        String jobNumber = conf.getJobNumber();
-        List<AdPlan> plans = adPlanService.lambdaQuery()
-                .eq(AdPlan::getAdPlanConfId, confId)
-                .gt(AdPlan::getAdgroupId, 0)
-                .orderByAsc(AdPlan::getId).list();
+    public void gdtDeleteByConf(AdPlanConf conf) {
         try {
-            TencentAds tencentAds = clientFactory.getTencentAds(jobNumber, Constant.MAIN_ORG_ACCOUNT_ID);
-            for (AdPlan plan : plans) {
-                try {
-                    AdgroupsUpdateRequest req = new AdgroupsUpdateRequest();
-                    req.setAccountId(plan.getAccountId());
-                    req.setAdgroupId(plan.getAdgroupId());
-                    req.setConfiguredStatus(ConfiguredStatus.SUSPEND);
-                    tencentAds.adgroups().adgroupsUpdate(req);
-                    plan.setSystemStatus("ADGROUP_STATUS_SUSPEND");
-                } catch (Exception e) {
-                    plan.setFailReason(truncateError(e.getMessage()));
-                }
-                adPlanService.lambdaUpdate().eq(AdPlan::getId,plan.getId())
-                        .set(AdPlan::getSystemStatus, plan.getSystemStatus())
-                        .set(AdPlan::getFailReason, plan.getFailReason())
-                        .update();
+            doDeletePlanAll(conf);
+            doDeleteCreativeAll(conf);
+            this.lambdaUpdate()
+                .eq(AdPlanConf::getId, conf.getId())
+                .set(AdPlanConf::getSystemDeleteProcessStatus, 2)
+                .update();
+        } catch (Exception e) {
+            log.error("gdtDeleteByConf error", e);
+            this.lambdaUpdate()
+                .eq(AdPlanConf::getId, conf.getId())
+                .set(AdPlanConf::getSystemDeleteProcessStatus, 3)
+                .set(AdPlanConf::getFailReason, truncateError(e.getMessage())).update();
+        }
+    }
+
+    private void doDeletePlanAll(AdPlanConf conf) throws Exception {
+        log.info("doDeletePlanAll {}", conf.getId());
+        TencentAds tencentAds = clientFactory.getTencentAds(conf.getJobNumber(), Constant.MAIN_ORG_ACCOUNT_ID);
+        int pageSize = 100;
+        int pageNum = 1;
+        while (true) {
+            LambdaQueryWrapper<AdPlan> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(AdPlan::getAdPlanConfId, conf.getId())
+                    .gt(AdPlan::getAdgroupId, 0)
+                    .orderByAsc(AdPlan::getId);
+            Page<AdPlan> page = adPlanService.page(new Page<>(pageNum, pageSize), queryWrapper);
+            List<AdPlan> plans = page.getRecords();
+            if (plans.isEmpty()) {
+                break;
+            }
+            doDeletePlans(tencentAds, plans);
+            if (!page.hasNext()) {
+                break;
+            }
+            pageNum++;
+            TimeUnit.SECONDS.sleep(1);
+        }
+    }
+
+    private void doDeletePlans(TencentAds tencentAds, List<AdPlan> plans) throws Exception {
+        for (AdPlan plan : plans) {
+            try {
+                AdgroupsDeleteRequest req = new AdgroupsDeleteRequest();
+                req.setAccountId(plan.getAccountId());
+                req.setAdgroupId(plan.getAdgroupId());
+                tencentAds.adgroups().adgroupsDelete(req);
+            } catch (Exception e) {
+                plan.setFailReason(truncateError(e.getMessage()));
+            }
+            adPlanService.lambdaUpdate()
+                    .eq(AdPlan::getId, plan.getId())
+                    .set(AdPlan::getSystemDelete, "true")
+                    .set(AdPlan::getFailReason, plan.getFailReason())
+                    .update();
+        }
+    }
+    private void doDeleteCreativeAll(AdPlanConf conf) throws Exception {
+        log.info("doDeleteCreativeAll {}", conf.getId());
+        TencentAds tencentAds = clientFactory.getTencentAds(conf.getJobNumber(), Constant.MAIN_ORG_ACCOUNT_ID);
+        int pageSize = 100;
+        int pageNum = 1;
+        while (true) {
+            LambdaQueryWrapper<AdPlanCreative> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(AdPlanCreative::getAdPlanConfId, conf.getId())
+                    .gt(AdPlanCreative::getAdgroupId, 0)
+                    .gt(AdPlanCreative::getCreativeId, 0)
+                    .orderByAsc(AdPlanCreative::getId);
+            Page<AdPlanCreative> page = adPlanCreativeService.page(new Page<>(pageNum, pageSize), queryWrapper);
+            List<AdPlanCreative> creatives = page.getRecords();
+            if (creatives.isEmpty()) {
+                break;
+            }
+            doDeleteCreative(tencentAds, creatives);
+            if (!page.hasNext()) {
+                break;
             }
+            pageNum++;
+            TimeUnit.SECONDS.sleep(1);
+        }
+    }
+
+    private void doDeleteCreative(TencentAds tencentAds, List<AdPlanCreative> creatives) throws Exception {
+        for (AdPlanCreative creative : creatives) {
+            try {
+                DynamicCreativesDeleteRequest req = new DynamicCreativesDeleteRequest();
+                req.setAccountId(creative.getAccountId());
+                req.setDynamicCreativeId(creative.getCreativeId());
+                tencentAds.dynamicCreatives().dynamicCreativesDelete(req);
+            } catch (Exception e) {
+                creative.setFailReason(truncateError(e.getMessage()));
+            }
+            adPlanCreativeService.lambdaUpdate()
+                    .eq(AdPlanCreative::getId, creative.getId())
+                    .set(AdPlanCreative::getSystemDelete, "true")
+                    .set(AdPlanCreative::getFailReason, creative.getFailReason())
+                    .update();
+        }
+    }
+
+    @Async
+    @Override
+    public void gdtDeleteByPlanIds(AdPlanConf conf, Long planIds) {
+        log.info("gdtDeleteByPlanIds {}", conf.getId());
+        try {
+            TencentAds tencentAds = clientFactory.getTencentAds(conf.getJobNumber(), Constant.MAIN_ORG_ACCOUNT_ID);
+            List<AdPlan> plans = adPlanService.lambdaQuery()
+                    .eq(AdPlan::getAdPlanConfId, conf.getId())
+                    .in(AdPlan::getId, planIds)
+                    .gt(AdPlan::getAdgroupId, 0)
+                    .orderByAsc(AdPlan::getId).list();
+            doDeletePlans(tencentAds, plans);
+
+            List<Long> adPlanIds = plans.stream().map(AdPlan::getId).collect(Collectors.toList());
+            List<AdPlanCreative> creatives = adPlanCreativeService.lambdaQuery()
+                                .in(AdPlanCreative::getAdPlanId, adPlanIds)
+                                .gt(AdPlanCreative::getAdgroupId, 0)
+                                .gt(AdPlanCreative::getCreativeId, 0)
+                                .orderByAsc(AdPlanCreative::getId)
+                                .list();
+            doDeleteCreative(tencentAds, creatives);
+
+            this.lambdaUpdate()
+                .eq(AdPlanConf::getId, conf.getId())
+                .set(AdPlanConf::getSystemDeleteProcessStatus, 2)
+                .update();
         } catch (Exception e) {
-            throw new RuntimeException(e);
+            log.error("gdtDeleteByPlanIds error", e);
+            this.lambdaUpdate()
+                .eq(AdPlanConf::getId, conf.getId())
+                .eq(AdPlanConf::getSystemDeleteProcessStatus, 3)
+                .set(AdPlanConf::getFailReason, truncateError(e.getMessage())).update();
         }
     }
 
+    @Async
     @Override
-    public void suspendByPlanIds(Long confId, Long planIds) {
-        AdPlanConf conf = this.getById(confId);
-        String jobNumber = conf.getJobNumber();
-        List<AdPlan> plans = adPlanService.lambdaQuery()
-                .eq(AdPlan::getAdPlanConfId, confId)
-                .in(AdPlan::getId, planIds)
-                .gt(AdPlan::getAdgroupId, 0)
-                .orderByAsc(AdPlan::getId).list();
+    public void gdtSuspendByConf(AdPlanConf conf) {
         try {
-            TencentAds tencentAds = clientFactory.getTencentAds(jobNumber, Constant.MAIN_ORG_ACCOUNT_ID);
-            for (AdPlan plan : plans) {
-                try {
-                    AdgroupsUpdateRequest req = new AdgroupsUpdateRequest();
-                    req.setAccountId(plan.getAccountId());
-                    req.setAdgroupId(plan.getAdgroupId());
-                    req.setConfiguredStatus(ConfiguredStatus.SUSPEND);
-                    tencentAds.adgroups().adgroupsUpdate(req);
-                    plan.setSystemStatus("ADGROUP_STATUS_SUSPEND");
-                } catch (Exception e) {
-                    plan.setFailReason(truncateError(e.getMessage()));
-                }
-                adPlanService.lambdaUpdate().eq(AdPlan::getId,plan.getId())
-                        .set(AdPlan::getSystemStatus, plan.getSystemStatus())
-                        .set(AdPlan::getFailReason, plan.getFailReason())
-                        .update();
+            doSuspendPlanAll(conf);
+            doSuspendCreativeAll(conf);
+            this.lambdaUpdate()
+                .eq(AdPlanConf::getId, conf.getId())
+                .set(AdPlanConf::getSystemSuspendProcessStatus, 2)
+                .update();
+        } catch (Exception e) {
+            log.error("gdtSuspendByConf error", e);
+            this.lambdaUpdate()
+                .eq(AdPlanConf::getId, conf.getId())
+                .set(AdPlanConf::getSystemSuspendProcessStatus, 3)
+                .set(AdPlanConf::getFailReason, truncateError(e.getMessage())).update();
+        }
+    }
+
+    private void doSuspendPlanAll(AdPlanConf conf) throws Exception {
+        log.info("doSuspendPlanAll {}", conf.getId());
+        TencentAds tencentAds = clientFactory.getTencentAds(conf.getJobNumber(), Constant.MAIN_ORG_ACCOUNT_ID);
+        int pageSize = 100;
+        int pageNum = 1;
+        while (true) {
+            LambdaQueryWrapper<AdPlan> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(AdPlan::getAdPlanConfId, conf.getId())
+                    .gt(AdPlan::getAdgroupId, 0)
+                    .orderByAsc(AdPlan::getId);
+            Page<AdPlan> page = adPlanService.page(new Page<>(pageNum, pageSize), queryWrapper);
+            List<AdPlan> plans = page.getRecords();
+            if (plans.isEmpty()) {
+                break;
+            }
+            doSuspendPlans(tencentAds, plans);
+            if (!page.hasNext()) {
+                break;
+            }
+            pageNum++;
+            TimeUnit.SECONDS.sleep(1);
+        }
+    }
+
+    private void doSuspendPlans(TencentAds tencentAds, List<AdPlan> plans) throws Exception {
+        for (AdPlan plan : plans) {
+            try {
+                AdgroupsUpdateRequest req = new AdgroupsUpdateRequest();
+                req.setAccountId(plan.getAccountId());
+                req.setAdgroupId(plan.getAdgroupId());
+                req.setConfiguredStatus(ConfiguredStatus.SUSPEND);
+                tencentAds.adgroups().adgroupsUpdate(req);
+                plan.setConfiguredStatus(ConfiguredStatus.SUSPEND.getValue());
+            } catch (Exception e) {
+                plan.setFailReason(truncateError(e.getMessage()));
+            }
+            adPlanService.lambdaUpdate()
+                    .eq(AdPlan::getId, plan.getId())
+                    .set(AdPlan::getConfiguredStatus, plan.getSystemStatus())
+                    .set(AdPlan::getFailReason, plan.getFailReason())
+                    .update();
+        }
+    }
+
+    private void doSuspendCreativeAll(AdPlanConf conf) throws Exception {
+        log.info("doSuspendCreativeAll {}", conf.getId());
+        TencentAds tencentAds = clientFactory.getTencentAds(conf.getJobNumber(), Constant.MAIN_ORG_ACCOUNT_ID);
+        int pageSize = 100;
+        int pageNum = 1;
+        while (true) {
+            LambdaQueryWrapper<AdPlanCreative> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(AdPlanCreative::getAdPlanConfId, conf.getId())
+                    .gt(AdPlanCreative::getAdgroupId, 0)
+                    .gt(AdPlanCreative::getCreativeId, 0)
+                    .orderByAsc(AdPlanCreative::getId);
+            Page<AdPlanCreative> page = adPlanCreativeService.page(new Page<>(pageNum, pageSize), queryWrapper);
+            List<AdPlanCreative> creatives = page.getRecords();
+            if (creatives.isEmpty()) {
+                break;
+            }
+            doSuspendCreative(tencentAds, creatives);
+            if (!page.hasNext()) {
+                break;
+            }
+            pageNum++;
+            TimeUnit.SECONDS.sleep(1);
+        }
+
+    }
+
+    private void doSuspendCreative(TencentAds tencentAds, List<AdPlanCreative> creatives)
+            throws Exception {
+        for (AdPlanCreative creative : creatives) {
+            try {
+                DynamicCreativesUpdateRequest req = new DynamicCreativesUpdateRequest();
+                req.setAccountId(creative.getAccountId());
+                req.setDynamicCreativeId(creative.getCreativeId());
+                req.setConfiguredStatus(ConfiguredStatus.SUSPEND);
+                tencentAds.dynamicCreatives().dynamicCreativesUpdate(req);
+                creative.setConfiguredStatus(ConfiguredStatus.SUSPEND.getValue());
+            } catch (Exception e) {
+                creative.setFailReason(truncateError(e.getMessage()));
             }
+            adPlanCreativeService.lambdaUpdate()
+                    .eq(AdPlanCreative::getId, creative.getId())
+                    .set(AdPlanCreative::getConfiguredStatus, creative.getConfiguredStatus())
+                    .set(AdPlanCreative::getFailReason, creative.getFailReason())
+                    .update();
+        }
+    }
+
+    @Async
+    @Override
+    public void gdtSuspendByPlanIds(AdPlanConf conf, Long planIds) {
+        try {
+            TencentAds tencentAds = clientFactory.getTencentAds(conf.getJobNumber(), Constant.MAIN_ORG_ACCOUNT_ID);
+            List<AdPlan> plans = adPlanService.lambdaQuery()
+                    .eq(AdPlan::getAdPlanConfId, conf.getId())
+                    .in(AdPlan::getId, planIds)
+                    .gt(AdPlan::getAdgroupId, 0)
+                    .orderByAsc(AdPlan::getId).list();
+            doSuspendPlans(tencentAds, plans);
+
+            List<Long> adPlanIds = plans.stream().map(AdPlan::getId).collect(Collectors.toList());
+            List<AdPlanCreative> creatives = adPlanCreativeService.lambdaQuery()
+                                .in(AdPlanCreative::getAdPlanId, adPlanIds)
+                                .gt(AdPlanCreative::getAdgroupId, 0)
+                                .gt(AdPlanCreative::getCreativeId, 0)
+                                .orderByAsc(AdPlanCreative::getId)
+                                .list();
+            doSuspendCreative(tencentAds, creatives);
+            this.lambdaUpdate()
+                .eq(AdPlanConf::getId, conf.getId())
+                .set(AdPlanConf::getSystemSuspendProcessStatus, 2)
+                .update();
         } catch (Exception e) {
-            throw new RuntimeException(e);
+            log.error("gdtSuspendByPlanIds error", e);
+            this.lambdaUpdate()
+                .eq(AdPlanConf::getId, conf.getId())
+                .set(AdPlanConf::getSystemSuspendProcessStatus, 3)
+                .set(AdPlanConf::getFailReason, truncateError(e.getMessage())).update();
         }
     }
 
@@ -240,8 +458,9 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
             creative.setCreativeText(conf.getCreativeText());
             creative.setButtonText(conf.getButtonText());
         });
-        //group by planId
-        Map<Long, List<AdPlanCreative>> creativeMap = creatives.stream().collect(Collectors.groupingBy(AdPlanCreative::getAdPlanId));
+        // group by planId
+        Map<Long, List<AdPlanCreative>> creativeMap = creatives.stream()
+                .collect(Collectors.groupingBy(AdPlanCreative::getAdPlanId));
         for (AdPlan plan : plans) {
             plan.setAdCreatives(creativeMap.getOrDefault(plan.getId(), new ArrayList<AdPlanCreative>()));
         }
@@ -274,7 +493,7 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
                 log.info("开始处理广告计划,planId={}, adgroupName={}", plan.getId(), plan.getAdgroupName());
 
                 if (plan.getAdgroupId() > 0 || plan.getStatus() == AdPlanStatus.SUCCESS) {
-                     // 创建动态创意
+                    // 创建动态创意
                     createDynamicCreatives(plan, jobNumber, Constant.MAIN_ORG_ACCOUNT_ID);
                     plan.setFailReason("");
                     plan.setStatus(AdPlanStatus.SUCCESS);
@@ -283,7 +502,6 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
                     continue;
                 }
 
-
                 // 更新状态为执行中
                 plan.setStatus(AdPlanStatus.IN_PROGRESS);
                 adPlanService.updateById(plan);
@@ -292,16 +510,16 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
                 AdgroupsAddRequest request = buildAdgroupRequest(plan);
                 log.info("请求参数: {}", JSON.toJSON(request));
                 // 创建广告组
-                log.info("调用腾讯API创建广告组,accountId={}, orgAccountId={}", plan.getAccountId(), Constant.MAIN_ORG_ACCOUNT_ID);
+                log.info("调用腾讯API创建广告组,accountId={}, orgAccountId={}", plan.getAccountId(),
+                        Constant.MAIN_ORG_ACCOUNT_ID);
                 AdgroupsAddResponseData response = tencentAdsAdgroupService.createAdgroup(
-                    jobNumber, Constant.MAIN_ORG_ACCOUNT_ID, request
-                );
+                        jobNumber, Constant.MAIN_ORG_ACCOUNT_ID, request);
 
                 // 更新 adgroupId
                 plan.setAdgroupId(response.getAdgroupId());
                 log.info("广告组创建成功,adgroupId={}", response.getAdgroupId());
 
-                 // 更新状态为成功
+                // 更新状态为成功
                 plan.setStatus(AdPlanStatus.SUCCESS);
                 plan.setFailReason("");
                 plan.setSuccessTime(LocalDateTime.now());
@@ -316,7 +534,8 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
 
             } catch (TencentAdsResponseException e) {
                 // 记录失败
-                log.error("创建广告失败, planId={} code={} message={} messageCn={}", plan.getId(), e.getCode(), e.getMessage(), e.getMessageCn());
+                log.error("创建广告失败, planId={} code={} message={} messageCn={}", plan.getId(), e.getCode(),
+                        e.getMessage(), e.getMessageCn());
                 plan.setStatus(AdPlanStatus.FAILED);
                 plan.setFailReason(truncateError(e.getMessageCn()));
                 adPlanService.updateById(plan);
@@ -341,30 +560,28 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
         if (plan.getAdType() == 1) {
             // 企微广告
             return AdgroupsAddReqPool.getAdgroupsAddRequest(
-                plan.getAccountId(),
-                plan.getAdgroupName(),
-                plan.getWxCorpid(),
-                calculateBeginDate(),
-                "",
-                parseTargetConfId(plan.getTarget()),
-                parseSiteConfId(plan.getSite()),
-                plan.getBidAmount(),
-                plan.getConversionId()
-            );
+                    plan.getAccountId(),
+                    plan.getAdgroupName(),
+                    plan.getWxCorpid(),
+                    calculateBeginDate(),
+                    "",
+                    parseTargetConfId(plan.getTarget()),
+                    parseSiteConfId(plan.getSite()),
+                    plan.getBidAmount(),
+                    plan.getConversionId());
         } else {
             // ROI广告
             return AdgroupsAddReqPool.getROIAdgroupsAddRequest(
-                plan.getAccountId(),
-                plan.getAdgroupName(),
-                plan.getDramaId(),
-                calculateBeginDate(),
-                "",
-                parseTargetConfId(plan.getTarget()),
-                parseSiteConfId(plan.getSite()),
-                plan.getBidAmount(),
-                plan.getConversionId(),
-                plan.getDeepConversionWorthRate()
-            );
+                    plan.getAccountId(),
+                    plan.getAdgroupName(),
+                    plan.getDramaId(),
+                    calculateBeginDate(),
+                    "",
+                    parseTargetConfId(plan.getTarget()),
+                    parseSiteConfId(plan.getSite()),
+                    plan.getBidAmount(),
+                    plan.getConversionId(),
+                    plan.getDeepConversionWorthRate());
         }
     }
 
@@ -372,7 +589,7 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
      * 创建动态创意
      */
     private void createDynamicCreatives(AdPlan plan, String jobNumber, Long orgAccountId)
-        throws TencentAdsResponseException, Exception {
+            throws TencentAdsResponseException, Exception {
 
         TencentAds tencentAds = clientFactory.getTencentAds(jobNumber, orgAccountId);
 
@@ -394,7 +611,8 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
                     if (creativeFileUrl != null && !creativeFileUrl.isEmpty()) {
                         try {
                             log.info("开始上传创意图片,URL: {}", creativeFileUrl);
-                            Long imageId = uploadImageFromUrl(tencentAds, plan.getAccountId(), creativeFileUrl, "创意图片-" + creative.getCreativeName());
+                            Long imageId = uploadImageFromUrl(tencentAds, plan.getAccountId(), creativeFileUrl,
+                                    "创意图片-" + creative.getCreativeName());
                             creative.setImageId(imageId);
                             adPlanCreativeService.updateById(creative);
                             log.info("创意图片上传成功,imageId: {}", imageId);
@@ -410,10 +628,11 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
                     String brandImageUrl = creative.getBrandImageUrl();
                     String brandName = creative.getBrandName();
                     if (brandImageUrl != null && !brandImageUrl.isEmpty()
-                        && brandName != null && !brandName.isEmpty()) {
+                            && brandName != null && !brandName.isEmpty()) {
                         try {
                             log.info("开始上传品牌形象,URL: {}, 品牌名称: {}", brandImageUrl, brandName);
-                            Long brandImageId = uploadBrandFromUrl(tencentAds, plan.getAccountId(), brandImageUrl, brandName);
+                            Long brandImageId = uploadBrandFromUrl(tencentAds, plan.getAccountId(), brandImageUrl,
+                                    brandName);
                             creative.setBrandImageId(brandImageId);
                             adPlanCreativeService.updateById(creative);
                             log.info("品牌形象上传成功,brandImageId: {}", brandImageId);
@@ -424,13 +643,11 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
                     }
                 }
 
-
                 // 构建动态创意请求
                 DynamicCreativesAddRequest request = buildDynamicCreativeRequest(plan, creative);
 
                 // 调用API创建
-                DynamicCreativesAddResponseData response =
-                    tencentAds.dynamicCreatives().dynamicCreativesAdd(request);
+                DynamicCreativesAddResponseData response = tencentAds.dynamicCreatives().dynamicCreativesAdd(request);
 
                 // 更新创意ID和状态
                 creative.setCreativeId(response.getDynamicCreativeId());
@@ -627,7 +844,7 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
 
         this.updateById(conf);
         log.info("更新广告计划配置状态,confId={}, status={}, 成功:{}, 失败:{}",
-            confId, conf.getStatus(), successCount, failCount);
+                confId, conf.getStatus(), successCount, failCount);
     }
 
     /**
@@ -647,7 +864,6 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
         return LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
     }
 
-
     /**
      * 解析定向配置ID
      */
@@ -681,14 +897,15 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
     /**
      * 从URL下载图片并上传到腾讯广告
      *
-     * @param tencentAds 腾讯广告SDK实例
-     * @param accountId 账户ID
-     * @param imageUrl 图片URL
+     * @param tencentAds  腾讯广告SDK实例
+     * @param accountId   账户ID
+     * @param imageUrl    图片URL
      * @param description 图片描述
      * @return 图片ID
      * @throws Exception 上传失败
      */
-    private Long uploadImageFromUrl(TencentAds tencentAds, Long accountId, String imageUrl, String description) throws Exception {
+    private Long uploadImageFromUrl(TencentAds tencentAds, Long accountId, String imageUrl, String description)
+            throws Exception {
         File tempFile = null;
         try {
             // 1. 从URL下载图片到临时文件
@@ -703,26 +920,26 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
 
             // 4. 调用腾讯广告API上传图片
             ImagesAddResponseData response = tencentAds.images()
-                .imagesAdd(
-                    "UPLOAD_TYPE_BYTES",  // uploadType
-                    signature,             // signature
-                    accountId,             // accountId
-                    null,                  // organizationId
-                    null,                  // file
-                    base64Image,           // bytes
-                    null,                  // imageUsage
-                    description,           // description
-                    null,                  // resizeWidth
-                    null,                  // resizeHeight
-                    null                   // resizeFileSize
-                );
+                    .imagesAdd(
+                            "UPLOAD_TYPE_BYTES", // uploadType
+                            signature, // signature
+                            accountId, // accountId
+                            null, // organizationId
+                            null, // file
+                            base64Image, // bytes
+                            null, // imageUsage
+                            description, // description
+                            null, // resizeWidth
+                            null, // resizeHeight
+                            null // resizeFileSize
+                    );
 
             if (response == null || response.getImageId() == null) {
                 throw new Exception("图片上传返回结果为空");
             }
 
             log.info("图片上传成功,imageId: {}, 宽度: {}px, 高度: {}px",
-                response.getImageId(), response.getImageWidth(), response.getImageHeight());
+                    response.getImageId(), response.getImageWidth(), response.getImageHeight());
 
             return Long.parseLong(response.getImageId());
 
@@ -737,14 +954,15 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
     /**
      * 从URL下载品牌形象并上传到腾讯广告
      *
-     * @param tencentAds 腾讯广告SDK实例
-     * @param accountId 账户ID
+     * @param tencentAds    腾讯广告SDK实例
+     * @param accountId     账户ID
      * @param brandImageUrl 品牌形象图片URL
-     * @param brandName 品牌名称
+     * @param brandName     品牌名称
      * @return 品牌图片ID
      * @throws Exception 上传失败
      */
-    private Long uploadBrandFromUrl(TencentAds tencentAds, Long accountId, String brandImageUrl, String brandName) throws Exception {
+    private Long uploadBrandFromUrl(TencentAds tencentAds, Long accountId, String brandImageUrl, String brandName)
+            throws Exception {
         File tempFile = null;
         try {
             // 1. 从URL下载图片到临时文件
@@ -752,18 +970,18 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
 
             // 2. 调用腾讯广告API创建品牌形象
             BrandAddResponseData response = tencentAds.brand()
-                .brandAdd(
-                    accountId,      // accountId
-                    brandName,      // name
-                    tempFile        // brandImageFile
-                );
+                    .brandAdd(
+                            accountId, // accountId
+                            brandName, // name
+                            tempFile // brandImageFile
+                    );
 
             if (response == null || response.getImageId() == null) {
                 throw new Exception("品牌形象上传返回结果为空");
             }
 
             log.info("品牌形象上传成功,imageId: {}, 品牌名称: {}, 宽度: {}px, 高度: {}px",
-                response.getImageId(), response.getName(), response.getWidth(), response.getHeight());
+                    response.getImageId(), response.getName(), response.getWidth(), response.getHeight());
 
             return Long.parseLong(response.getImageId());
 
@@ -820,10 +1038,16 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
 
         } finally {
             if (outputStream != null) {
-                try { outputStream.close(); } catch (Exception e) { }
+                try {
+                    outputStream.close();
+                } catch (Exception e) {
+                }
             }
             if (inputStream != null) {
-                try { inputStream.close(); } catch (Exception e) { }
+                try {
+                    inputStream.close();
+                } catch (Exception e) {
+                }
             }
             if (connection != null) {
                 connection.disconnect();

Некоторые файлы не были показаны из-за большого количества измененных файлов