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

feat:文件直接上传组织ID下

pudongliang 4 месяцев назад
Родитель
Сommit
604eecf934
36 измененных файлов с 554 добавлено и 15 удалено
  1. 1 1
      portal/dist/assets/accountGroup-CC1adQS4.js
  2. 1 1
      portal/dist/assets/adAutoConf-DC1ZhFrQ.js
  3. 1 1
      portal/dist/assets/adPlanConf-B_Atl4vP.js
  4. 1 1
      portal/dist/assets/auth-CK4bunUz.js
  5. 1 1
      portal/dist/assets/conversion-BS06mk4P.js
  6. 0 0
      portal/dist/assets/detail-BRpIie4g.js
  7. 1 1
      portal/dist/assets/drama-dSaPpJa-.js
  8. 0 0
      portal/dist/assets/edit-DbY5Xn7q.js
  9. 0 0
      portal/dist/assets/index-B7ISxA3m.js
  10. 0 0
      portal/dist/assets/index-BDxme8A7.js
  11. 0 0
      portal/dist/assets/index-BGlJGEwd.js
  12. 1 0
      portal/dist/assets/index-BLUPLBBv.css
  13. 0 0
      portal/dist/assets/index-BQkzI7wM.js
  14. 1 1
      portal/dist/assets/index-BSUhTPha.js
  15. 0 0
      portal/dist/assets/index-Bg9gqZHF.js
  16. 0 0
      portal/dist/assets/index-Bjpg4YBS.js
  17. 0 0
      portal/dist/assets/index-C9XkxV8b.js
  18. 0 0
      portal/dist/assets/index-Cpb6-tRE.js
  19. 0 0
      portal/dist/assets/index-CuF4mDo1.js
  20. 0 0
      portal/dist/assets/index-D6h_CFAs.js
  21. 0 0
      portal/dist/assets/index-D7pIv_YJ.js
  22. 0 0
      portal/dist/assets/index-DA446b_J.js
  23. 0 0
      portal/dist/assets/index-DokRAm_d.js
  24. 0 0
      portal/dist/assets/index-fa8YdELH.js
  25. 0 1
      portal/dist/assets/index-vV63W3OI.css
  26. 1 1
      portal/dist/assets/loadPageConf-DkMgu9F5.js
  27. 1 1
      portal/dist/assets/ossFile-aTlflaDN.js
  28. 0 0
      portal/dist/assets/request-2CyynisS.js
  29. 1 1
      portal/dist/assets/user-zDESo9RD.js
  30. 1 1
      portal/dist/index.html
  31. 5 0
      portal/src/views/ad-plan-conf/index.vue
  32. 1 1
      portal/src/views/oss-file/index.vue
  33. 6 2
      src/main/java/com/moka/gdtauto/controller/AdPlanConfController.java
  34. 41 0
      src/main/java/com/moka/gdtauto/entity/OssFile.java
  35. 225 0
      src/main/java/com/moka/gdtauto/service/impl/OssFileServiceImpl.java
  36. 264 0
      src/test/java/com/moka/gdtauto/service/OssFileTencentUploadTest.java

+ 1 - 1
portal/dist/assets/accountGroup-8uZ-21zh.js → portal/dist/assets/accountGroup-CC1adQS4.js

@@ -1 +1 @@
-import{r as u}from"./request-DQh-iLk2.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-2CyynisS.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 - 1
portal/dist/assets/adAutoConf-o4VcXTr6.js → portal/dist/assets/adAutoConf-DC1ZhFrQ.js

@@ -1 +1 @@
-import{r as e}from"./request-DQh-iLk2.js";function u(t){return e({url:"/api/ad-auto-conf/list",method:"get",params:t})}function n(t){return e({url:`/api/ad-auto-conf/${t}`,method:"get"})}function a(t){return e({url:"/api/ad-auto-conf",method:"post",data:t})}function r(t){return e({url:"/api/ad-auto-conf/update",method:"post",data:t})}function i(t){return e({url:`/api/ad-auto-conf/execute?id=${t}`,method:"post"})}function d(t){return e({url:"/api/execute-log/list",method:"get",params:t})}function c(t){return e({url:"/api/execute-log/getChildLog",method:"get",params:t})}export{c as a,d as b,n as c,i as e,u as g,a as s,r as u};
+import{r as e}from"./request-2CyynisS.js";function u(t){return e({url:"/api/ad-auto-conf/list",method:"get",params:t})}function n(t){return e({url:`/api/ad-auto-conf/${t}`,method:"get"})}function a(t){return e({url:"/api/ad-auto-conf",method:"post",data:t})}function r(t){return e({url:"/api/ad-auto-conf/update",method:"post",data:t})}function i(t){return e({url:`/api/ad-auto-conf/execute?id=${t}`,method:"post"})}function d(t){return e({url:"/api/execute-log/list",method:"get",params:t})}function c(t){return e({url:"/api/execute-log/getChildLog",method:"get",params:t})}export{c as a,d as b,n as c,i as e,u as g,a as s,r as u};

+ 1 - 1
portal/dist/assets/adPlanConf-DREVW8zw.js → portal/dist/assets/adPlanConf-B_Atl4vP.js

@@ -1 +1 @@
-import{r as a}from"./request-DQh-iLk2.js";function d(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 l(n){return a({url:`/api/ad-plan-conf/syncSystemStatus/${n}`,method:"get"})}function p(n){return a({url:"/api/ad-plan-conf/create",method:"post",data:n})}function s(n){return a({url:"/api/ad-plan-conf/update",method:"post",data:n})}function i(n=1,e=10,t={}){return a({url:"/api/ad-plan-conf/list",method:"get",params:{pageNum:n,pageSize:e,...t}})}function f(n){return a({url:`/api/ad-plan-conf/${n}`,method:"get"})}function c(n){return a({url:"/api/ad-plan/list",method:"get",params:n})}function g(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 h(n){return a({url:"/api/ad-plan-conf/gdtDeleteByConfId",params:{confId:n},method:"get"})}function C(n,e){return a({url:`/api/ad-plan-conf/gdtSuspendByPlanIds/${n}`,method:"post",data:e})}function P(n,e){return a({url:`/api/ad-plan-conf/gdtDeleteByPlanIds/${n}`,method:"post",data:e})}function y(n=[]){return a({url:"/api/ad-plan-conf/getOneCreativeImage",method:"post",data:n})}function I(){return a({url:"/api/ad-plan-conf/getOneBrandImage",method:"get"})}function B(n=[]){return a({url:"/api/ad-plan-conf/getOneCreativeVideo",method:"post",data:n})}export{y as a,I as b,B as c,o as d,p as e,f,i as g,c as h,h as i,C as j,P as k,l,u as m,g as n,d as r,m as s,s as u};
+import{r as a}from"./request-2CyynisS.js";function d(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 l(n){return a({url:`/api/ad-plan-conf/syncSystemStatus/${n}`,method:"get"})}function p(n){return a({url:"/api/ad-plan-conf/create",method:"post",data:n})}function s(n){return a({url:"/api/ad-plan-conf/update",method:"post",data:n})}function i(n=1,e=10,t={}){return a({url:"/api/ad-plan-conf/list",method:"get",params:{pageNum:n,pageSize:e,...t}})}function f(n){return a({url:`/api/ad-plan-conf/${n}`,method:"get"})}function c(n){return a({url:"/api/ad-plan/list",method:"get",params:n})}function g(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 h(n){return a({url:"/api/ad-plan-conf/gdtDeleteByConfId",params:{confId:n},method:"get"})}function C(n,e){return a({url:`/api/ad-plan-conf/gdtSuspendByPlanIds/${n}`,method:"post",data:e})}function P(n,e){return a({url:`/api/ad-plan-conf/gdtDeleteByPlanIds/${n}`,method:"post",data:e})}function y(n=[]){return a({url:"/api/ad-plan-conf/getOneCreativeImage",method:"post",data:n})}function I(){return a({url:"/api/ad-plan-conf/getOneBrandImage",method:"get"})}function B(n=[]){return a({url:"/api/ad-plan-conf/getOneCreativeVideo",method:"post",data:n})}export{y as a,I as b,B as c,o as d,p as e,f,i as g,c as h,h as i,C as j,P as k,l,u as m,g as n,d as r,m as s,s as u};

+ 1 - 1
portal/dist/assets/auth-DpDW-wbY.js → portal/dist/assets/auth-CK4bunUz.js

@@ -1 +1 @@
-import{r as t}from"./request-DQh-iLk2.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-2CyynisS.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-D9jEO0bx.js → portal/dist/assets/conversion-BS06mk4P.js

@@ -1 +1 @@
-import{r as t}from"./request-DQh-iLk2.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-2CyynisS.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-BRpIie4g.js


+ 1 - 1
portal/dist/assets/drama-BzmyP39D.js → portal/dist/assets/drama-dSaPpJa-.js

@@ -1 +1 @@
-import{r as t}from"./request-DQh-iLk2.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-2CyynisS.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/edit-DbY5Xn7q.js


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


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


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


+ 1 - 0
portal/dist/assets/index-BLUPLBBv.css

@@ -0,0 +1 @@
+.btn-primary[data-v-7d553ac2]{background:linear-gradient(135deg,#667eea,#764ba2);border:none;color:#fff}.btn-primary[data-v-7d553ac2]:hover{background:linear-gradient(135deg,#764ba2,#667eea)}.btn-secondary[data-v-7d553ac2]{border-color:#e5e7eb;color:#6b7280}.btn-secondary[data-v-7d553ac2]:hover{background-color:#f9fafb}[data-v-7d553ac2] .el-upload-dragger{border:2px dashed #d1d5db;border-radius:8px;background-color:#f9fafb;transition:all .3s}[data-v-7d553ac2] .el-upload-dragger:hover{border-color:#667eea;background-color:#f3f4f6}

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


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


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


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


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


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


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


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


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


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


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


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


+ 0 - 1
portal/dist/assets/index-vV63W3OI.css

@@ -1 +0,0 @@
-.btn-primary[data-v-f01c5d8c]{background:linear-gradient(135deg,#667eea,#764ba2);border:none;color:#fff}.btn-primary[data-v-f01c5d8c]:hover{background:linear-gradient(135deg,#764ba2,#667eea)}.btn-secondary[data-v-f01c5d8c]{border-color:#e5e7eb;color:#6b7280}.btn-secondary[data-v-f01c5d8c]:hover{background-color:#f9fafb}[data-v-f01c5d8c] .el-upload-dragger{border:2px dashed #d1d5db;border-radius:8px;background-color:#f9fafb;transition:all .3s}[data-v-f01c5d8c] .el-upload-dragger:hover{border-color:#667eea;background-color:#f3f4f6}

+ 1 - 1
portal/dist/assets/loadPageConf-Csy6zpsA.js → portal/dist/assets/loadPageConf-DkMgu9F5.js

@@ -1 +1 @@
-import{r as o}from"./request-DQh-iLk2.js";function t(a){return o({url:"/api/load-page-conf/list",method:"get",params:a})}function n(a){return o({url:`/api/load-page-conf/${a}`,method:"get"})}function r(a){return o({url:"/api/load-page-conf",method:"post",data:a})}function u(a){return o({url:"/api/load-page-conf",method:"put",data:a})}function d(){return o({url:"/api/load-page-conf/all",method:"get"})}export{t as a,n as b,r as c,d as g,u};
+import{r as o}from"./request-2CyynisS.js";function t(a){return o({url:"/api/load-page-conf/list",method:"get",params:a})}function n(a){return o({url:`/api/load-page-conf/${a}`,method:"get"})}function r(a){return o({url:"/api/load-page-conf",method:"post",data:a})}function u(a){return o({url:"/api/load-page-conf",method:"put",data:a})}function d(){return o({url:"/api/load-page-conf/all",method:"get"})}export{t as a,n as b,r as c,d as g,u};

+ 1 - 1
portal/dist/assets/ossFile-BwPbz9Kl.js → portal/dist/assets/ossFile-aTlflaDN.js

@@ -1 +1 @@
-import{r as t}from"./request-DQh-iLk2.js";function i(e){return t({timeout:12e5,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-2CyynisS.js";function i(e){return t({timeout:12e5,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-2CyynisS.js


+ 1 - 1
portal/dist/assets/user-D8E2_djv.js → portal/dist/assets/user-zDESo9RD.js

@@ -1 +1 @@
-import{r as e}from"./request-DQh-iLk2.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-2CyynisS.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-CfVVmcBm.js"></script>
+    <script type="module" crossorigin src="/assets/index-BSUhTPha.js"></script>
     <link rel="stylesheet" crossorigin href="/assets/index-DLIfzCMM.css">
   </head>
   <body>

+ 5 - 0
portal/src/views/ad-plan-conf/index.vue

@@ -535,6 +535,11 @@
                     <span v-else>-</span>
                   </template>
                 </el-table-column>
+                <el-table-column prop="imageId" label="资产ID" width="130">
+                  <template #default="{ row }">
+                    {{ row.imageId  || row.videoId}}
+                  </template>
+                  </el-table-column>
                 <el-table-column prop="creativeName" label="创意名称" min-width="100" show-overflow-tooltip />
                 <el-table-column prop="creativeText" label="创意文案" min-width="100" show-overflow-tooltip />
                 <el-table-column prop="brandName" label="品牌名称" width="120" />

+ 1 - 1
portal/src/views/oss-file/index.vue

@@ -129,7 +129,7 @@
         <el-table-column type="selection" width="55"></el-table-column>
         
         <el-table-column prop="id" label="ID" width="80"></el-table-column>
-        
+        <el-table-column prop="assetId" label="资产ID" width="120"></el-table-column>
         <el-table-column prop="businessType" label="业务分类" width="120">
           <template #default="{ row }">
             <el-tag :type="row.businessType === 1 ? 'primary' : 'success'" size="small">

+ 6 - 2
src/main/java/com/moka/gdtauto/controller/AdPlanConfController.java

@@ -330,14 +330,18 @@ public class AdPlanConfController {
                                 String creativeName = accountGroupName.trim() + "-" + dateTime + "-" + j + "-"
                                         + fileName;
                                 AdPlanCreative adPlanCreative = new AdPlanCreative();
+                                
                                 adPlanCreative.setCreativeFileUrl(creativeUrl);
                                 adPlanCreative.setCreativeFileMd5(creativeFile.getFileMd5());
                                 adPlanCreative.setCreativeFileType(creativeFile.getFileType());
                                 adPlanCreative.setCreativeId(0L);
                                 adPlanCreative.setCreativeName(creativeName);
                                 adPlanCreative.setCreativeText(request.getCreativeText());
-                                adPlanCreative.setImageId(0L);
-                                adPlanCreative.setVideoId(0L);
+                                if (creativeFile.getFileType().equals("image")) {
+                                    adPlanCreative.setImageId(Long.valueOf(creativeFile.getAssetId()));
+                                } else if (creativeFile.getFileType().equals("video")) {
+                                    adPlanCreative.setVideoId(Long.valueOf(creativeFile.getAssetId()));
+                                }
                                 adPlanCreative.setBrandImageId(0L);
                                 adPlanCreative.setBrandName(request.getBrandName());
                                 adPlanCreative.setBrandImageUrl(request.getBrandImageFile().getFileUrl());

+ 41 - 0
src/main/java/com/moka/gdtauto/entity/OssFile.java

@@ -71,6 +71,47 @@ public class OssFile {
     private String fileExtension;
 
     /**
+     * 图片ID
+     */
+    private String assetId;
+    /**
+     * 图片宽度
+     */
+    private Long width;
+    /**
+     * 图片高度
+     */
+    private Long height;
+    /**
+     * 图片大小
+     */
+    private Long imageFileSize;
+    /**
+     * 图片类型
+     */
+    private String imageType;
+    /**
+     * 图片签名
+     */
+    private String imageSignature;
+    /**
+     * 外部图片ID
+     */
+    private String outerImageId;
+    /**
+     * 预览地址
+     */
+    private String previewUrl;
+    /**
+     * 图片描述
+     */
+    private String description;
+    /**
+     * 封面图ID
+     */
+    private Long coverImageId;
+
+    /**
      * 创建人ID
      */
     private Long createdBy;

+ 225 - 0
src/main/java/com/moka/gdtauto/service/impl/OssFileServiceImpl.java

@@ -4,11 +4,17 @@ import com.aliyun.oss.common.utils.BinaryUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.moka.gdtauto.client.TencentAdsApiClientFactory;
+import com.moka.gdtauto.common.Constant;
+import com.moka.gdtauto.controller.OssFileController;
 import com.moka.gdtauto.entity.OssFile;
 import com.moka.gdtauto.mapper.OssFileMapper;
 import com.moka.gdtauto.service.OssFileService;
 import com.moka.gdtauto.util.OssUtil;
 import com.moka.gdtauto.util.TencentFileMd5Util;
+import com.tencent.ads.model.v3.ImagesAddResponseData;
+import com.tencent.ads.model.v3.VideosAddResponseData;
+import com.tencent.ads.v3.TencentAds;
 
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -16,7 +22,14 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
 import java.time.LocalDateTime;
+import java.util.Base64;
 
 /**
  * OSS文件Service实现类
@@ -30,6 +43,7 @@ import java.time.LocalDateTime;
 public class OssFileServiceImpl extends ServiceImpl<OssFileMapper, OssFile> implements OssFileService {
 
     private final OssUtil ossUtil;
+    private TencentAdsApiClientFactory clientFactory;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -71,6 +85,9 @@ public class OssFileServiceImpl extends ServiceImpl<OssFileMapper, OssFile> impl
             ossFile.setUpdatedTime(LocalDateTime.now());
             
             save(ossFile);
+            if (businessType == 1) {
+                uploadFileToTencent(ossFile);   
+            }
             
             log.info("文件上传成功,ID: {}, URL: {}", ossFile.getId(), fileUrl);
             return ossFile;
@@ -80,6 +97,214 @@ public class OssFileServiceImpl extends ServiceImpl<OssFileMapper, OssFile> impl
         }
     }
 
+    private void uploadFileToTencent(OssFile ossFile) throws Exception {
+        log.info("开始上传文件到腾讯广告,ID: {}", ossFile.getId());
+        TencentAds tencentAds = clientFactory.getTencentAds("", Constant.MAIN_ORG_ACCOUNT_ID);
+        String fileUrl = ossFile.getFileUrl();
+            String fileMd5 = ossFile.getFileMd5();
+            //image/video
+            String fileType = ossFile.getFileType();
+            if (fileType.equals("image")) {
+                try  {
+                    byte[] fileBytes = downloadFileToBytes(fileUrl);
+                    uploadImageFromBytes(tencentAds, fileBytes, fileMd5, fileType, ossFile);
+                } catch (Exception e) {
+                    log.error("上传文件失败,URL: {}", fileUrl, e);
+                }
+            } else if(fileType.equals("video")) {
+                try  {
+                    uploadVideoFromUrl(tencentAds, Constant.MAIN_ORG_ACCOUNT_ID, fileUrl, fileMd5, fileType, ossFile);
+                } catch (Exception e) {
+                    log.error("上传文件失败,URL: {}", fileUrl, e);
+                }
+            }
+    }
+
+    private Long uploadImageFromBytes(TencentAds tencentAds, byte[] imageBytes, String fileMd5, String description, OssFile ossFile)
+            throws Exception {
+        String base64Image = Base64.getEncoder().encodeToString(imageBytes);
+
+        ImagesAddResponseData response = tencentAds.images()
+                .imagesAdd(
+                        "UPLOAD_TYPE_BYTES",
+                        fileMd5,
+                        null,
+                        Constant.MAIN_ORG_ACCOUNT_ID,
+                        null,
+                        base64Image,
+                        null,
+                        description,
+                        null,
+                        null,
+                        null
+                );
+
+        if (response == null || response.getImageId() == null) {
+            throw new Exception("图片上传返回结果为空");
+        }
+
+        log.info("图片上传成功,imageId: {}, 宽度: {}px, 高度: {}px",
+                response.getImageId(), response.getImageWidth(), response.getImageHeight());
+        ossFile.setAssetId(response.getImageId());
+        ossFile.setWidth(response.getImageWidth());
+        ossFile.setHeight(response.getImageHeight());
+        ossFile.setImageFileSize(response.getImageFileSize());
+        ossFile.setImageType(response.getImageType().getValue());
+        ossFile.setImageSignature(response.getImageSignature());
+        ossFile.setOuterImageId(response.getOuterImageId());
+        ossFile.setPreviewUrl(response.getPreviewUrl());
+        ossFile.setDescription(response.getDescription());
+        return Long.parseLong(response.getImageId());
+    }
+
+    private record VideoUploadResult(Long videoId, Long coverImageId) {}
+
+
+    private VideoUploadResult uploadVideoFromUrl(TencentAds tencentAds, Long accountId, String videoUrl, String fileMd5, String description, OssFile ossFile)
+            throws Exception {
+        File tempFile = null;
+        try {
+            // 1. 从URL下载视频到临时文件
+            tempFile = downloadFileFromUrl(videoUrl);
+
+            // 2. 检查文件大小(最大100MB)
+            long fileSizeInMB = tempFile.length() / (1024 * 1024);
+            if (fileSizeInMB > 100) {
+                throw new Exception("视频文件过大: " + fileSizeInMB + "MB,超过 100MB 限制");
+            }
+
+            // 3. 计算视频MD5签名
+            String signature = fileMd5;
+            log.info("视频MD5签名: {}, 文件大小: {}MB", signature, fileSizeInMB);
+
+            // 4. 调用腾讯广告API上传视频
+            VideosAddResponseData response = tencentAds.videos()
+                    .videosAdd(
+                            tempFile,           // videoFile
+                            signature,          // signature
+                            null,          // accountId
+                            Constant.MAIN_ORG_ACCOUNT_ID,               // organizationId
+                            description,        // description
+                            null                // adcreativeTemplateId
+                    );
+
+            if (response == null || response.getVideoId() == null) {
+                throw new Exception("视频上传返回结果为空");
+            }
+
+            log.info("视频上传成功,videoId: {}, 封面图片ID: {}",
+                    response.getVideoId(), response.getCoverImageId());
+            ossFile.setAssetId(String.valueOf(response.getVideoId()));
+            ossFile.setCoverImageId(response.getCoverImageId());
+            return new VideoUploadResult(response.getVideoId(), response.getCoverImageId());
+        } finally {
+            // 5. 删除临时文件
+            if (tempFile != null && tempFile.exists()) {
+                tempFile.delete();
+            }
+        }
+    }
+
+    private File downloadFileFromUrl(String fileUrl) throws Exception {
+        HttpURLConnection connection = null;
+        InputStream inputStream = null;
+        FileOutputStream outputStream = null;
+
+        try {
+            // 创建临时文件
+            String suffix = getFileSuffix(fileUrl);
+            File tempFile = File.createTempFile("gdt_upload_", suffix);
+
+            // 打开HTTP连接
+            URL url = new URL(fileUrl);
+            connection = (HttpURLConnection) url.openConnection();
+            connection.setConnectTimeout(10000);
+            connection.setReadTimeout(30000);
+            connection.setRequestMethod("GET");
+            connection.connect();
+
+            int responseCode = connection.getResponseCode();
+            if (responseCode != HttpURLConnection.HTTP_OK) {
+                throw new Exception("下载文件失败,HTTP状态码: " + responseCode);
+            }
+
+            // 读取文件内容
+            inputStream = connection.getInputStream();
+            outputStream = new FileOutputStream(tempFile);
+
+            byte[] buffer = new byte[8192];
+            int bytesRead;
+            while ((bytesRead = inputStream.read(buffer)) != -1) {
+                outputStream.write(buffer, 0, bytesRead);
+            }
+
+            log.info("文件下载成功,URL: {}, 大小: {} bytes", fileUrl, tempFile.length());
+            return tempFile;
+
+        } finally {
+            if (outputStream != null) {
+                try {
+                    outputStream.close();
+                } catch (Exception e) {
+                }
+            }
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (Exception e) {
+                }
+            }
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+    }
+
+    private String getFileSuffix(String fileUrl) {
+        int lastDotIndex = fileUrl.lastIndexOf('.');
+        int lastSlashIndex = fileUrl.lastIndexOf('/');
+
+        if (lastDotIndex > lastSlashIndex && lastDotIndex < fileUrl.length() - 1) {
+            return fileUrl.substring(lastDotIndex);
+        }
+
+        return ".mp4"; // 默认后缀
+    }
+
+    private byte[] downloadFileToBytes(String fileUrl) throws Exception {
+        HttpURLConnection connection = null;
+        InputStream inputStream = null;
+        try {
+            URL url = new URL(fileUrl);
+            connection = (HttpURLConnection) url.openConnection();
+            connection.setConnectTimeout(10000);
+            connection.setReadTimeout(30000);
+            connection.setRequestMethod("GET");
+            connection.connect();
+
+            int responseCode = connection.getResponseCode();
+            if (responseCode != HttpURLConnection.HTTP_OK) {
+                throw new Exception("下载文件失败,HTTP状态码: " + responseCode);
+            }
+
+            inputStream = connection.getInputStream();
+            byte[] fileBytes = inputStream.readAllBytes();
+            log.info("文件下载成功,URL: {}, 大小: {} bytes", fileUrl, fileBytes.length);
+            return fileBytes;
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    log.warn("关闭输入流失败", e);
+                }
+            }
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public boolean deleteFile(Long fileId) {

+ 264 - 0
src/test/java/com/moka/gdtauto/service/OssFileTencentUploadTest.java

@@ -0,0 +1,264 @@
+package com.moka.gdtauto.service;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Base64;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import lombok.extern.slf4j.Slf4j;
+
+import com.moka.gdtauto.GdtAutoApplication;
+import com.moka.gdtauto.client.TencentAdsApiClientFactory;
+import com.moka.gdtauto.entity.OssFile;
+import com.tencent.ads.model.v3.BrandAddResponseData;
+import com.tencent.ads.model.v3.ImagesAddResponseData;
+import com.tencent.ads.model.v3.VideosAddResponseData;
+import com.tencent.ads.v3.TencentAds;
+
+/**
+ * mvn test -Dtest=OssFileTencentUploadTest#testUploadFile -Dspring.profiles.active=test
+ */
+@SpringBootTest(classes = GdtAutoApplication.class)
+@ActiveProfiles("test")
+@Slf4j
+public class OssFileTencentUploadTest {
+
+    @Autowired
+    private OssFileService ossFileService;
+    @Autowired
+    private TencentAdsApiClientFactory clientFactory;
+
+    private static final Long ORG_ACCOUNT_ID = 44035150L;
+    private static final String TEST_JOB_NUMBER = "12458";
+
+    @Test
+    public void testUploadFile() throws Exception {
+        List<OssFile> ossFileList = ossFileService.lambdaQuery()
+        .eq(OssFile::getBusinessType, 1)
+        .list();
+        TencentAds tencentAds = clientFactory.getTencentAds(TEST_JOB_NUMBER, ORG_ACCOUNT_ID);
+            tencentAds.setDebug(true);
+            ossFileList.forEach(ossFile -> {
+            String fileUrl = ossFile.getFileUrl();;
+            String fileMd5 = ossFile.getFileMd5();
+            //1:创意 2:品牌形象
+            Integer businessType = ossFile.getBusinessType();
+            //image/video
+            String fileType = ossFile.getFileType();
+
+            if (fileType.equals("image")) {
+                try  {
+                    byte[] fileBytes = downloadFileToBytes(fileUrl);
+                    uploadImageFromBytes(tencentAds, ORG_ACCOUNT_ID, fileBytes, fileMd5, fileType, ossFile);
+                } catch (Exception e) {
+                    log.error("上传文件失败,URL: {}", fileUrl, e);
+                }
+            } else if(fileType.equals("video")) {
+                try  {
+                    uploadVideoFromUrl(tencentAds, ORG_ACCOUNT_ID, fileUrl, fileMd5, fileType, ossFile);
+                } catch (Exception e) {
+                    log.error("上传文件失败,URL: {}", fileUrl, e);
+                }
+            }
+        });
+        ossFileService.updateBatchById(ossFileList);
+    }
+
+    private byte[] downloadFileToBytes(String fileUrl) throws Exception {
+        HttpURLConnection connection = null;
+        InputStream inputStream = null;
+        try {
+            URL url = new URL(fileUrl);
+            connection = (HttpURLConnection) url.openConnection();
+            connection.setConnectTimeout(10000);
+            connection.setReadTimeout(30000);
+            connection.setRequestMethod("GET");
+            connection.connect();
+
+            int responseCode = connection.getResponseCode();
+            if (responseCode != HttpURLConnection.HTTP_OK) {
+                throw new Exception("下载文件失败,HTTP状态码: " + responseCode);
+            }
+
+            inputStream = connection.getInputStream();
+            byte[] fileBytes = inputStream.readAllBytes();
+            log.info("文件下载成功,URL: {}, 大小: {} bytes", fileUrl, fileBytes.length);
+            return fileBytes;
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    log.warn("关闭输入流失败", e);
+                }
+            }
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+    }
+
+    /**
+     * 使用字节数组上传图片到腾讯广告
+     */
+    private Long uploadImageFromBytes(TencentAds tencentAds, Long accountId, byte[] imageBytes, String fileMd5, String description, OssFile ossFile)
+            throws Exception {
+        String base64Image = Base64.getEncoder().encodeToString(imageBytes);
+
+        ImagesAddResponseData response = tencentAds.images()
+                .imagesAdd(
+                        "UPLOAD_TYPE_BYTES",
+                        fileMd5,
+                        null,
+                        ORG_ACCOUNT_ID,
+                        null,
+                        base64Image,
+                        null,
+                        description,
+                        null,
+                        null,
+                        null
+                );
+
+        if (response == null || response.getImageId() == null) {
+            throw new Exception("图片上传返回结果为空");
+        }
+
+        log.info("图片上传成功,imageId: {}, 宽度: {}px, 高度: {}px",
+                response.getImageId(), response.getImageWidth(), response.getImageHeight());
+        ossFile.setAssetId(response.getImageId());
+        ossFile.setWidth(response.getImageWidth());
+        ossFile.setHeight(response.getImageHeight());
+        ossFile.setImageFileSize(response.getImageFileSize());
+        ossFile.setImageType(response.getImageType().getValue());
+        ossFile.setImageSignature(response.getImageSignature());
+        ossFile.setOuterImageId(response.getOuterImageId());
+        ossFile.setPreviewUrl(response.getPreviewUrl());
+        ossFile.setDescription(response.getDescription());
+        return Long.parseLong(response.getImageId());
+    }
+
+      private record VideoUploadResult(Long videoId, Long coverImageId) {}
+
+
+    private VideoUploadResult uploadVideoFromUrl(TencentAds tencentAds, Long accountId, String videoUrl, String fileMd5, String description, OssFile ossFile)
+            throws Exception {
+        File tempFile = null;
+        try {
+            // 1. 从URL下载视频到临时文件
+            tempFile = downloadFileFromUrl(videoUrl);
+
+            // 2. 检查文件大小(最大100MB)
+            long fileSizeInMB = tempFile.length() / (1024 * 1024);
+            if (fileSizeInMB > 100) {
+                throw new Exception("视频文件过大: " + fileSizeInMB + "MB,超过 100MB 限制");
+            }
+
+            // 3. 计算视频MD5签名
+            String signature = fileMd5;
+            log.info("视频MD5签名: {}, 文件大小: {}MB", signature, fileSizeInMB);
+
+            // 4. 调用腾讯广告API上传视频
+            VideosAddResponseData response = tencentAds.videos()
+                    .videosAdd(
+                            tempFile,           // videoFile
+                            signature,          // signature
+                            null,          // accountId
+                            ORG_ACCOUNT_ID,               // organizationId
+                            description,        // description
+                            null                // adcreativeTemplateId
+                    );
+
+            if (response == null || response.getVideoId() == null) {
+                throw new Exception("视频上传返回结果为空");
+            }
+
+            log.info("视频上传成功,videoId: {}, 封面图片ID: {}",
+                    response.getVideoId(), response.getCoverImageId());
+            ossFile.setAssetId(String.valueOf(response.getVideoId()));
+            ossFile.setCoverImageId(response.getCoverImageId());
+            return new VideoUploadResult(response.getVideoId(), response.getCoverImageId());
+        } finally {
+            // 5. 删除临时文件
+            if (tempFile != null && tempFile.exists()) {
+                tempFile.delete();
+            }
+        }
+    }
+
+    private File downloadFileFromUrl(String fileUrl) throws Exception {
+        HttpURLConnection connection = null;
+        InputStream inputStream = null;
+        FileOutputStream outputStream = null;
+
+        try {
+            // 创建临时文件
+            String suffix = getFileSuffix(fileUrl);
+            File tempFile = File.createTempFile("gdt_upload_", suffix);
+
+            // 打开HTTP连接
+            URL url = new URL(fileUrl);
+            connection = (HttpURLConnection) url.openConnection();
+            connection.setConnectTimeout(10000);
+            connection.setReadTimeout(30000);
+            connection.setRequestMethod("GET");
+            connection.connect();
+
+            int responseCode = connection.getResponseCode();
+            if (responseCode != HttpURLConnection.HTTP_OK) {
+                throw new Exception("下载文件失败,HTTP状态码: " + responseCode);
+            }
+
+            // 读取文件内容
+            inputStream = connection.getInputStream();
+            outputStream = new FileOutputStream(tempFile);
+
+            byte[] buffer = new byte[8192];
+            int bytesRead;
+            while ((bytesRead = inputStream.read(buffer)) != -1) {
+                outputStream.write(buffer, 0, bytesRead);
+            }
+
+            log.info("文件下载成功,URL: {}, 大小: {} bytes", fileUrl, tempFile.length());
+            return tempFile;
+
+        } finally {
+            if (outputStream != null) {
+                try {
+                    outputStream.close();
+                } catch (Exception e) {
+                }
+            }
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (Exception e) {
+                }
+            }
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+    }
+
+    private String getFileSuffix(String fileUrl) {
+        int lastDotIndex = fileUrl.lastIndexOf('.');
+        int lastSlashIndex = fileUrl.lastIndexOf('/');
+
+        if (lastDotIndex > lastSlashIndex && lastDotIndex < fileUrl.length() - 1) {
+            return fileUrl.substring(lastDotIndex);
+        }
+
+        return ".mp4"; // 默认后缀
+    }
+
+    
+}

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