Explorar o código

feat:创意报表

pudongliang hai 4 meses
pai
achega
1d540f4f42
Modificáronse 65 ficheiros con 2439 adicións e 57 borrados
  1. 5 0
      .qoder/rules/always_on_rule.md
  2. 15 1
      pom.xml
  3. 1 1
      portal/dist/assets/accountGroup-Hz8DvqJ-.js
  4. 1 1
      portal/dist/assets/adPlanConf-DEahaXJn.js
  5. 1 1
      portal/dist/assets/auth-BjnVrv7v.js
  6. 1 1
      portal/dist/assets/conversion-CN1XBFwG.js
  7. 0 0
      portal/dist/assets/detail-CaknTo1e.js
  8. 0 0
      portal/dist/assets/index--MkpItGC.js
  9. 0 0
      portal/dist/assets/index-BFpRN2B4.js
  10. 0 1
      portal/dist/assets/index-BSHr2xvB.js
  11. 0 1
      portal/dist/assets/index-BkFEM_lT.css
  12. 0 0
      portal/dist/assets/index-CF76VUQw.js
  13. 0 0
      portal/dist/assets/index-CVim3yZa.js
  14. 0 1
      portal/dist/assets/index-CVqD3p3i.css
  15. 0 0
      portal/dist/assets/index-CadamGXn.js
  16. 0 0
      portal/dist/assets/index-CnHVwCE9.js
  17. 0 0
      portal/dist/assets/index-CvM19u79.js
  18. 1 0
      portal/dist/assets/index-CvzQKMxG.css
  19. 1 0
      portal/dist/assets/index-D2u6GVqk.css
  20. 0 0
      portal/dist/assets/index-D3XHZgVT.js
  21. 0 0
      portal/dist/assets/index-D9fmbPya.js
  22. 0 0
      portal/dist/assets/index-Dh7cGwUk.js
  23. 0 0
      portal/dist/assets/index-UWcrzzH4.js
  24. 0 0
      portal/dist/assets/index-tp-9sWmJ.js
  25. 1 1
      portal/dist/assets/ossFile-B7sSzdhg.js
  26. 0 0
      portal/dist/assets/request-BsgM0pQo.js
  27. 1 1
      portal/dist/assets/user-ZKuoi2ku.js
  28. 1 1
      portal/dist/index.html
  29. 3 3
      portal/jsconfig.json
  30. 37 0
      portal/src/api/dailyReport.js
  31. 6 0
      portal/src/router/index.js
  32. 4 4
      portal/src/views/conversion/index.vue
  33. 412 0
      portal/src/views/daily-report/index.vue
  34. 2 2
      portal/src/views/image/index.vue
  35. 1 1
      portal/src/views/oss-file/index.vue
  36. 0 1
      src/main/java/com/moka/gdtauto/client/TencentAdsApiClientFactory.java
  37. 81 0
      src/main/java/com/moka/gdtauto/controller/DailyReportController.java
  38. 0 2
      src/main/java/com/moka/gdtauto/controller/SysUserController.java
  39. 0 1
      src/main/java/com/moka/gdtauto/controller/TencentConversionController.java
  40. 2 4
      src/main/java/com/moka/gdtauto/entity/AdPlan.java
  41. 414 0
      src/main/java/com/moka/gdtauto/entity/BaseDailyCreativeReport.java
  42. 17 0
      src/main/java/com/moka/gdtauto/entity/RepDailyCreativeReport.java
  43. 17 0
      src/main/java/com/moka/gdtauto/entity/ReqDailyCreativeReport.java
  44. 24 0
      src/main/java/com/moka/gdtauto/mapper/RepDailyCreativeReportMapper.java
  45. 24 0
      src/main/java/com/moka/gdtauto/mapper/ReqDailyCreativeReportMapper.java
  46. 387 0
      src/main/java/com/moka/gdtauto/service/DailyReportService.java
  47. 0 2
      src/main/java/com/moka/gdtauto/service/TencentAdsAdgroupService.java
  48. 0 1
      src/main/java/com/moka/gdtauto/service/TencentAdsAuthService.java
  49. 0 2
      src/main/java/com/moka/gdtauto/service/TencentAssetDramaService.java
  50. 0 2
      src/main/java/com/moka/gdtauto/service/TencentConversionService.java
  51. 4 5
      src/main/java/com/moka/gdtauto/service/impl/AdPlanConfServiceImpl.java
  52. 0 2
      src/main/java/com/moka/gdtauto/service/impl/TencentConversionServiceImpl.java
  53. 0 2
      src/main/java/com/moka/gdtauto/service/impl/TencentImagesServiceImpl.java
  54. 0 2
      src/main/java/com/moka/gdtauto/service/impl/TencentVideoServiceImpl.java
  55. 100 0
      src/main/java/com/moka/gdtauto/task/DailyReportSyncTask.java
  56. 0 4
      src/main/java/com/moka/gdtauto/util/AdgroupsAddReqPool.java
  57. 0 1
      src/main/java/com/moka/gdtauto/util/VideoWatermarkUtil.java
  58. 201 0
      src/main/resources/mapper/RepDailyCreativeReportMapper.xml
  59. 201 0
      src/main/resources/mapper/ReqDailyCreativeReportMapper.xml
  60. 398 0
      src/main/resources/sql/create_daily_creative_report_tables.sql
  61. 0 1
      src/test/java/com/moka/gdtauto/integration/AdgroupsApiManualTest.java
  62. 73 0
      src/test/java/com/moka/gdtauto/service/DailyReportTest.java
  63. 0 2
      src/test/java/com/moka/gdtauto/service/TencentAssetDramaTest.java
  64. 1 0
      src/test/java/com/moka/gdtauto/util/VideoWatermarkSimpleTest.java
  65. 1 2
      src/test/java/com/moka/gdtauto/util/VideoWatermarkUtilTest.java

+ 5 - 0
.qoder/rules/always_on_rule.md

@@ -0,0 +1,5 @@
+---
+trigger: always_on
+---
+在进行前后端接口对接的时候使用 package com.moka.gdtauto.common.Result 进行相应;前端判定业务逻辑成功使用success字段
+前端界面风格参考 portal/src/conversion/index.vue

+ 15 - 1
pom.xml

@@ -8,7 +8,7 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>4.0.2</version>
+        <version>4.0.3</version>
     </parent>
 
     <groupId>com.moka</groupId>
@@ -245,6 +245,20 @@
                     </argLine>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <compilerArgs>
+                        <arg>-Xlint:all</arg>
+                        <arg>-Xlint:unchecked</arg>
+                        <arg>-Xlint:deprecation</arg>
+                    </compilerArgs>
+                    <showWarnings>true</showWarnings>
+                    <showDeprecation>true</showDeprecation>
+                </configuration>
+            </plugin>
+
         </plugins>
     </build>
 

+ 1 - 1
portal/dist/assets/accountGroup-ByV0FUyw.js → portal/dist/assets/accountGroup-Hz8DvqJ-.js

@@ -1 +1 @@
-import{r as u}from"./request-aterOvqm.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-BsgM0pQo.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/adPlanConf-DPKH1vgj.js → portal/dist/assets/adPlanConf-DEahaXJn.js

@@ -1 +1 @@
-import{r as a}from"./request-aterOvqm.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 l(n){return a({url:`/api/ad-plan-conf/reGeneratePlan/${n}`,method:"get"})}function d(n){return a({url:"/api/ad-plan-conf/create",method:"post",data:n})}function u(n){return a({url:"/api/ad-plan-conf/update",method:"post",data:n})}function p(n){return a({url:`/api/ad-plan-conf/${n}`,method:"delete"})}function i(n=1,e=10){return a({url:"/api/ad-plan-conf/list",method:"get",params:{pageNum:n,pageSize:e}})}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 s(n){return a({url:`/api/ad-plan-creative/plan/${n}`,method:"get"})}export{o as a,f as b,d as c,p as d,c as e,l as f,i as g,s as h,r,u};
+import{r as a}from"./request-BsgM0pQo.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 l(n){return a({url:`/api/ad-plan-conf/reGeneratePlan/${n}`,method:"get"})}function d(n){return a({url:"/api/ad-plan-conf/create",method:"post",data:n})}function u(n){return a({url:"/api/ad-plan-conf/update",method:"post",data:n})}function p(n){return a({url:`/api/ad-plan-conf/${n}`,method:"delete"})}function i(n=1,e=10){return a({url:"/api/ad-plan-conf/list",method:"get",params:{pageNum:n,pageSize:e}})}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 s(n){return a({url:`/api/ad-plan-creative/plan/${n}`,method:"get"})}export{o as a,f as b,d as c,p as d,c as e,l as f,i as g,s as h,r,u};

+ 1 - 1
portal/dist/assets/auth-C8u4LIGa.js → portal/dist/assets/auth-BjnVrv7v.js

@@ -1 +1 @@
-import{r as t}from"./request-aterOvqm.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-BsgM0pQo.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-BNy34mQQ.js → portal/dist/assets/conversion-CN1XBFwG.js

@@ -1 +1 @@
-import{r as t}from"./request-aterOvqm.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-BsgM0pQo.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};

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/detail-CaknTo1e.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/index--MkpItGC.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/index-BFpRN2B4.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 1
portal/dist/assets/index-BSHr2xvB.js


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

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

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/index-CF76VUQw.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/index-CVim3yZa.js


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

@@ -1 +0,0 @@
-.conversion-container[data-v-bd1a2db1]{padding:20px}.card-header[data-v-bd1a2db1]{display:flex;justify-content:space-between;align-items:center}.stats-row[data-v-bd1a2db1]{margin-bottom:20px}.pagination-container[data-v-bd1a2db1]{margin-top:20px;display:flex;justify-content:flex-end}[data-v-bd1a2db1] .el-statistic__head{font-size:14px;color:#909399}[data-v-bd1a2db1] .el-statistic__number{font-size:24px;font-weight:700;color:#303133}[data-v-bd1a2db1] .success .el-statistic__number{color:#67c23a}[data-v-bd1a2db1] .info .el-statistic__number{color:#409eff}[data-v-bd1a2db1] .warning .el-statistic__number{color:#e6a23c}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/index-CadamGXn.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/index-CnHVwCE9.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/index-CvM19u79.js


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

@@ -0,0 +1 @@
+.conversion-container[data-v-86e7044b]{padding:20px}.card-header[data-v-86e7044b]{display:flex;justify-content:space-between;align-items:center}.stats-row[data-v-86e7044b]{margin-bottom:20px}.pagination-container[data-v-86e7044b]{margin-top:20px;display:flex;justify-content:flex-end}[data-v-86e7044b] .el-statistic__head{font-size:14px;color:#909399}[data-v-86e7044b] .el-statistic__number{font-size:24px;font-weight:700;color:#303133}[data-v-86e7044b] .success .el-statistic__number{color:#67c23a}[data-v-86e7044b] .info .el-statistic__number{color:#409eff}[data-v-86e7044b] .warning .el-statistic__number{color:#e6a23c}

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

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

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/index-D3XHZgVT.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/index-D9fmbPya.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/index-Dh7cGwUk.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/index-UWcrzzH4.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/index-tp-9sWmJ.js


+ 1 - 1
portal/dist/assets/ossFile-DoOgwG8p.js → portal/dist/assets/ossFile-B7sSzdhg.js

@@ -1 +1 @@
-import{r as t}from"./request-aterOvqm.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-BsgM0pQo.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};

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
portal/dist/assets/request-BsgM0pQo.js


+ 1 - 1
portal/dist/assets/user-DIdDEfaX.js → portal/dist/assets/user-ZKuoi2ku.js

@@ -1 +1 @@
-import{r as e}from"./request-aterOvqm.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-BsgM0pQo.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-BTGVoQEn.js"></script>
+    <script type="module" crossorigin src="/assets/index-BSHr2xvB.js"></script>
     <link rel="stylesheet" crossorigin href="/assets/index-Cqptlhyz.css">
   </head>
   <body>

+ 3 - 3
portal/jsconfig.json

@@ -1,11 +1,11 @@
 {
   "compilerOptions": {
     "target": "ES6",
-    "module": "commonjs",
+    "module": "ESNext",  // 配合 bundler 使用
+    "moduleResolution": "bundler",  // 使用 bundler 模式
     "allowSyntheticDefaultImports": true,
-    "baseUrl": "./",
     "paths": {
-      "@/*": ["src/*"]
+      "@/*": ["./src/*"]  // 不再需要 baseUrl
     }
   },
   "exclude": ["node_modules", "dist"]

+ 37 - 0
portal/src/api/dailyReport.js

@@ -0,0 +1,37 @@
+import request from '@/utils/request'
+
+/**
+ * 手动同步指定账户日报表
+ * @param {Object} params
+ * @param {String} params.jobNumber     工号
+ * @param {Number} params.orgAccountId  组织账户ID
+ * @param {Number} params.accountId     广告账户ID
+ * @param {String} params.startDate     开始日期 yyyy-MM-dd
+ * @param {String} params.endDate       结束日期 yyyy-MM-dd
+ * @param {String} params.timeLine      时间口径 REQUEST_TIME / REPORTING_TIME
+ */
+export function syncDailyReport(params) {
+  return request({
+    url: '/api/gdt/daily-report/sync',
+    method: 'post',
+    params
+  })
+}
+
+/**
+ * 分页查询日报表
+ * @param {Object} params
+ * @param {String} params.timeLine      时间口径 REQUEST_TIME / REPORTING_TIME
+ * @param {Number} [params.accountId]   广告账户ID(可选)
+ * @param {String} [params.startDate]   开始日期 yyyy-MM-dd(可选)
+ * @param {String} [params.endDate]     结束日期 yyyy-MM-dd(可选)
+ * @param {Number} [params.page]        页码(默认1)
+ * @param {Number} [params.pageSize]    每页数量(默认20)
+ */
+export function getDailyReportList(params) {
+  return request({
+    url: '/api/gdt/daily-report/list',
+    method: 'get',
+    params
+  })
+}

+ 6 - 0
portal/src/router/index.js

@@ -68,6 +68,12 @@ const routes = [
         component: () => import('@/views/conversion/index.vue'),
         meta: { title: '转化归因管理', icon: 'DataAnalysis' }
       },
+      {
+        path: 'daily-report',
+        name: 'DailyReport',
+        component: () => import('@/views/daily-report/index.vue'),
+        meta: { title: '创意日报表', icon: 'TrendCharts' }
+      },
       // {
       //   path: 'adgroup',
       //   name: 'Adgroup',

+ 4 - 4
portal/src/views/conversion/index.vue

@@ -284,12 +284,12 @@ const handleSync = async () => {
 // 查看详情
 const handleViewDetail = async (row) => {
   try {
-    const response = await getConversionDetail(row.conversionId)
-    if (response.code === 0) {
-      currentConversion.value = response.data
+    const res = await getConversionDetail(row.conversionId)
+    if (res.success) {
+      currentConversion.value = res.data
       detailDialogVisible.value = true
     } else {
-      ElMessage.error(response.message || '查询详情失败')
+      ElMessage.error(res.message || '查询详情失败')
     }
   } catch (error) {
     console.error('查询详情失败:', error)

+ 412 - 0
portal/src/views/daily-report/index.vue

@@ -0,0 +1,412 @@
+<template>
+  <div class="space-y-6">
+    <div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
+
+      <!-- 标题栏 -->
+      <div class="border-b border-gray-200 pb-4 mb-6">
+        <div class="flex items-center justify-between flex-wrap gap-4">
+          <h2 class="text-xl font-semibold text-gray-800 flex items-center gap-2">
+            <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-blue-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
+              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
+            </svg>
+            动态创意日报表
+          </h2>
+          <!-- 手动同步区域 -->
+          <!-- <div class="flex items-center gap-2 flex-wrap">
+            <el-input
+              v-model="syncForm.accountId"
+              placeholder="广告账户ID"
+              clearable
+              style="width: 160px"
+            />
+            <el-date-picker
+              v-model="syncDateRange"
+              type="daterange"
+              range-separator="~"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
+              style="width: 240px"
+            />
+            <el-button
+              type="primary"
+              :loading="syncing"
+              :disabled="!syncForm.accountId"
+              @click="handleSync"
+            >
+              <el-icon><Refresh /></el-icon>
+              手动同步
+            </el-button>
+          </div> -->
+        </div>
+      </div>
+
+      <!-- 查询条件 -->
+      <div class="flex flex-wrap items-center gap-4 mb-6">
+        <!-- 时间口径 radio -->
+        <div class="flex items-center gap-2">
+          <span class="text-sm text-gray-600 font-medium">时间口径:</span>
+          <el-radio-group v-model="queryForm.timeLine" @change="handleTimeLineChange">
+            <el-radio-button value="REQUEST_TIME">请求时间</el-radio-button>
+            <el-radio-button value="REPORTING_TIME">上报时间</el-radio-button>
+          </el-radio-group>
+        </div>
+
+        <el-select
+          v-model="queryForm.groupId"
+          placeholder="账号组筛选"
+          clearable
+          filterable
+          style="width: 180px"
+          @change="handleSearch"
+        >
+          <el-option
+            v-for="g in groupOptions"
+            :key="g.id"
+            :label="g.groupName"
+            :value="g.id"
+          />
+        </el-select>
+
+        <el-input
+          v-model="queryForm.accountId"
+          placeholder="账户ID筛选"
+          clearable
+          style="width: 160px"
+          @clear="handleSearch"
+        />
+
+        <el-date-picker
+          v-model="queryDateRange"
+          type="daterange"
+          range-separator="~"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD"
+          style="width: 240px"
+          @change="handleSearch"
+        />
+
+        <el-button type="primary" @click="handleSearch">
+          <el-icon><Search /></el-icon>
+          查询
+        </el-button>
+        <el-button @click="handleReset">重置</el-button>
+      </div>
+
+      <!-- 数据统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
+        <div class="bg-gradient-to-br from-blue-50 to-blue-100 rounded-lg p-4 border border-blue-200">
+          <div class="flex items-center justify-between">
+            <div>
+              <p class="text-sm text-blue-600 mb-1">数据总条数</p>
+              <p class="text-2xl font-bold text-blue-700">{{ pagination.total }}</p>
+            </div>
+            <div class="p-3 bg-blue-200 rounded-lg">
+              <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
+                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h16M4 18h16" />
+              </svg>
+            </div>
+          </div>
+        </div>
+        <div class="bg-gradient-to-br from-green-50 to-green-100 rounded-lg p-4 border border-green-200">
+          <div class="flex items-center justify-between">
+            <div>
+              <p class="text-sm text-green-600 mb-1">当前口径</p>
+              <p class="text-lg font-bold text-green-700">{{ queryForm.timeLine === 'REQUEST_TIME' ? '请求时间' : '上报时间' }}</p>
+            </div>
+            <div class="p-3 bg-green-200 rounded-lg">
+              <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
+                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
+              </svg>
+            </div>
+          </div>
+        </div>
+        <div class="bg-gradient-to-br from-purple-50 to-purple-100 rounded-lg p-4 border border-purple-200">
+          <div class="flex items-center justify-between">
+            <div>
+              <p class="text-sm text-purple-600 mb-1">总页数</p>
+              <p class="text-2xl font-bold text-purple-700">{{ totalPages }}</p>
+            </div>
+            <div class="p-3 bg-purple-200 rounded-lg">
+              <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-purple-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
+                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
+              </svg>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 数据表格 -->
+      <el-table
+        :data="reportList"
+        v-loading="loading"
+        stripe
+        border
+        style="width: 100%"
+        max-height="600"
+      >
+        <!-- yyyy-MM-dd -->
+        <el-table-column prop="date" label="日期" width="110" fixed="left" >
+          <template #default="{ row }">{{ row.date.substring(0, 10) }}</template>
+        </el-table-column>
+        <el-table-column prop="accountId" label="账户ID" width="130" fixed="left" />
+        <el-table-column prop="dynamicCreativeId" label="动态创意ID" width="140" />
+        <el-table-column prop="cost" label="消耗(元)" width="110" align="right">
+          <template #default="{ row }">{{ formatNum(row.cost) }}</template>
+        </el-table-column>
+        <el-table-column prop="viewCount" label="曝光数" width="100" align="right">
+          <template #default="{ row }">{{ formatInt(row.viewCount) }}</template>
+        </el-table-column>
+        <el-table-column prop="validClickCount" label="有效点击" width="100" align="right">
+          <template #default="{ row }">{{ formatInt(row.validClickCount) }}</template>
+        </el-table-column>
+        <el-table-column prop="ctr" label="点击率" width="90" align="right">
+          <template #default="{ row }">{{ formatPct(row.ctr) }}</template>
+        </el-table-column>
+        <el-table-column prop="cpc" label="CPC" width="90" align="right">
+          <template #default="{ row }">{{ formatNum(row.cpc) }}</template>
+        </el-table-column>
+        <el-table-column prop="conversionsCount" label="转化数" width="90" align="right">
+          <template #default="{ row }">{{ formatInt(row.conversionsCount) }}</template>
+        </el-table-column>
+        <el-table-column prop="conversionsCost" label="转化成本" width="100" align="right">
+          <template #default="{ row }">{{ formatNum(row.conversionsCost) }}</template>
+        </el-table-column>
+        <el-table-column label="1日ROI" width="90" align="right">
+          <template #default="{ row }">{{ formatRoi(row.incomeRoi1) }}</template>
+        </el-table-column>
+        <el-table-column label="1日LTV" width="100" align="right">
+          <template #default="{ row }">{{ formatNum(row.incomeVal1) }}</template>
+        </el-table-column>
+        <el-table-column label="3日ROI" width="90" align="right">
+          <template #default="{ row }">{{ formatRoi(row.incomeRoi3) }}</template>
+        </el-table-column>
+        <el-table-column label="3日LTV" width="100" align="right">
+          <template #default="{ row }">{{ formatNum(row.incomeVal3) }}</template>
+        </el-table-column>
+        <el-table-column label="7日ROI" width="90" align="right">
+          <template #default="{ row }">{{ formatRoi(row.incomeRoi7) }}</template>
+        </el-table-column>
+        <el-table-column label="7日LTV" width="100" align="right">
+          <template #default="{ row }">{{ formatNum(row.incomeVal7) }}</template>
+        </el-table-column>
+        <el-table-column label="14日ROI" width="90" align="right">
+          <template #default="{ row }">{{ formatRoi(row.incomeRoi14) }}</template>
+        </el-table-column>
+        <el-table-column label="14日LTV" width="100" align="right">
+          <template #default="{ row }">{{ formatNum(row.incomeVal14) }}</template>
+        </el-table-column>
+        <el-table-column label="24h ROI" width="100" align="right">
+          <template #default="{ row }">{{ formatRoi(row.incomeRoi1_24h) }}</template>
+        </el-table-column>
+        <el-table-column label="24h LTV" width="100" align="right">
+          <template #default="{ row }">{{ formatNum(row.incomeVal24h) }}</template>
+        </el-table-column>
+        <el-table-column prop="videoOuterPlayCount" label="视频播放" width="100" align="right">
+          <template #default="{ row }">{{ formatInt(row.videoOuterPlayCount) }}</template>
+        </el-table-column>
+        <el-table-column prop="videoOuterPlay3sCount" label="3s播放" width="90" align="right">
+          <template #default="{ row }">{{ formatInt(row.videoOuterPlay3sCount) }}</template>
+        </el-table-column>
+      </el-table>
+
+      <!-- 分页 -->
+      <div class="mt-6 flex justify-end">
+        <el-pagination
+          v-model:current-page="pagination.page"
+          v-model:page-size="pagination.pageSize"
+          :page-sizes="[20, 50, 100, 200]"
+          :total="pagination.total"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, computed, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Refresh, Search } from '@element-plus/icons-vue'
+import { syncDailyReport, getDailyReportList } from '@/api/dailyReport'
+import { getAccountGroupListAll } from '@/api/accountGroup'
+
+// ─── 响应式状态 ───────────────────────────────────────────────────────────────
+const loading = ref(false)
+const syncing = ref(false)
+const reportList = ref([])
+const groupOptions = ref([])
+
+// 同步表单
+const syncForm = reactive({ accountId: '' })
+const syncDateRange = ref([])
+
+// 查询表单
+const queryForm = reactive({
+  timeLine: 'REQUEST_TIME',
+  accountId: '',
+  groupId: null,
+})
+const getDefaultDateRange = () => {
+  const end = new Date()
+  const start = new Date()
+  start.setDate(start.getDate() - 6)
+  const fmt = (d) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
+  return [fmt(start), fmt(end)]
+}
+const queryDateRange = ref(getDefaultDateRange())
+
+// 分页
+const pagination = reactive({ page: 1, pageSize: 20, total: 0 })
+
+// ─── 计算属性 ─────────────────────────────────────────────────────────────────
+const totalPages = computed(() => Math.ceil(pagination.total / pagination.pageSize) || 0)
+
+// ─── 格式化工具 ───────────────────────────────────────────────────────────────
+const formatNum = (v) => (v == null ? '-' : Number(v).toFixed(2))
+const formatInt = (v) => (v == null ? '-' : Number(v).toLocaleString())
+const formatPct = (v) => (v == null ? '-' : (Number(v) * 100).toFixed(2) + '%')
+const formatRoi = (v) => (v == null ? '-' : Number(v).toFixed(4))
+
+// ─── 加载数据 ─────────────────────────────────────────────────────────────────
+const loadList = async () => {
+  loading.value = true
+  try {
+    const params = {
+      timeLine: queryForm.timeLine,
+      page: pagination.page,
+      pageSize: pagination.pageSize,
+    }
+    if (queryForm.accountId) params.accountId = queryForm.accountId
+    if (queryForm.groupId) params.groupId = queryForm.groupId
+    if (queryDateRange.value && queryDateRange.value.length === 2) {
+      params.startDate = queryDateRange.value[0]
+      params.endDate = queryDateRange.value[1]
+    }
+    const res = await getDailyReportList(params)
+    if (res.success) {
+      reportList.value = res.data || []
+      pagination.total = res.total || 0
+    } else {
+      ElMessage.error(res.message || '查询失败')
+    }
+  } catch (err) {
+    console.error('查询日报表失败:', err)
+    ElMessage.error('查询失败')
+  } finally {
+    loading.value = false
+  }
+}
+
+// ─── 事件处理 ─────────────────────────────────────────────────────────────────
+const handleTimeLineChange = () => {
+  pagination.page = 1
+  loadList()
+}
+
+const handleSearch = () => {
+  pagination.page = 1
+  loadList()
+}
+
+const handleReset = () => {
+  queryForm.accountId = ''
+  queryForm.groupId = null
+  queryDateRange.value = getDefaultDateRange()
+  pagination.page = 1
+  loadList()
+}
+
+const handleSizeChange = (size) => {
+  pagination.pageSize = size
+  pagination.page = 1
+  loadList()
+}
+
+const handleCurrentChange = (page) => {
+  pagination.page = page
+  loadList()
+}
+
+const handleSync = async () => {
+  if (!syncForm.accountId) {
+    ElMessage.warning('请输入广告账户ID')
+    return
+  }
+
+  const startDate = syncDateRange.value?.[0] || getTodayStr()
+  const endDate = syncDateRange.value?.[1] || getTodayStr()
+
+  try {
+    await ElMessageBox.confirm(
+      `确定同步账户 ${syncForm.accountId} 的日报数据(${startDate} ~ ${endDate})?`,
+      '确认同步',
+      { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }
+    )
+    syncing.value = true
+    // 同步两个口径
+    const [r1, r2] = await Promise.all([
+      syncDailyReport({
+        jobNumber: '',       // 由后端路由到对应账户
+        orgAccountId: 0,
+        accountId: Number(syncForm.accountId),
+        startDate,
+        endDate,
+        timeLine: 'REQUEST_TIME',
+      }),
+      syncDailyReport({
+        jobNumber: '',
+        orgAccountId: 0,
+        accountId: Number(syncForm.accountId),
+        startDate,
+        endDate,
+        timeLine: 'REPORTING_TIME',
+      }),
+    ])
+    if (r1.success && r2.success) {
+      ElMessage.success(`同步完成:REQUEST_TIME ${r1.count ?? 0} 条,REPORTING_TIME ${r2.count ?? 0} 条`)
+      await loadList()
+    } else {
+      ElMessage.error((r1.message || r2.message) || '同步失败')
+    }
+  } catch (err) {
+    if (err !== 'cancel') {
+      console.error('同步日报表失败:', err)
+      ElMessage.error('同步失败')
+    }
+  } finally {
+    syncing.value = false
+  }
+}
+
+const getTodayStr = () => {
+  const d = new Date()
+  const y = d.getFullYear()
+  const m = String(d.getMonth() + 1).padStart(2, '0')
+  const day = String(d.getDate()).padStart(2, '0')
+  return `${y}-${m}-${day}`
+}
+
+// ─── 加载账号组 ───────────────────────────────────────────────────────────────
+const loadGroupOptions = async () => {
+  try {
+    const res = await getAccountGroupListAll()
+    if (res.success) {
+      groupOptions.value = res.data || []
+    }
+  } catch (err) {
+    console.error('加载账号组失败:', err)
+  }
+}
+
+// ─── 初始化 ───────────────────────────────────────────────────────────────────
+onMounted(() => {
+  loadGroupOptions()
+  loadList()
+})
+</script>

+ 2 - 2
portal/src/views/image/index.vue

@@ -346,7 +346,7 @@ const submitUpload = async () => {
     }
 
     const res = await uploadImage(formData)
-    if (res.code === 200) {
+    if (res.success) {
       ElMessage.success('图片上传成功')
       resetForm()
       loadImageList()
@@ -439,7 +439,7 @@ const handleDelete = async (row) => {
     })
 
     const res = await deleteImage(row.id)
-    if (res.code === 200) {
+    if (res.success) {
       ElMessage.success('删除成功')
       loadImageList()
     } else {

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

@@ -394,7 +394,7 @@ const handleBatchDelete = () => {
     try {
       const fileIds = selectedFiles.value.map(item => item.id)
       const res = await batchDeleteFiles(fileIds)
-      if (res.code === 200) {
+      if (res.success) {
         ElMessage.success('批量删除成功')
         loadFileList()
       } else {

+ 0 - 1
src/main/java/com/moka/gdtauto/client/TencentAdsApiClientFactory.java

@@ -1,6 +1,5 @@
 package com.moka.gdtauto.client;
 
-import com.moka.gdtauto.config.TencentAdsConfig;
 import com.moka.gdtauto.entity.SysUser;
 import com.moka.gdtauto.entity.TencentAdsAuth;
 import com.moka.gdtauto.service.SysUserService;

+ 81 - 0
src/main/java/com/moka/gdtauto/controller/DailyReportController.java

@@ -0,0 +1,81 @@
+package com.moka.gdtauto.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.moka.gdtauto.annotation.AuthUser;
+import com.moka.gdtauto.common.Result;
+import com.moka.gdtauto.entity.BaseDailyCreativeReport;
+import com.moka.gdtauto.entity.SysUser;
+import com.moka.gdtauto.service.DailyReportService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 动态创意日报表 Controller
+ *
+ * @author moka
+ * @since 2026-03-03
+ */
+@Tag(name = "动态创意日报表", description = "双口径(REQUEST_TIME/REPORTING_TIME)动态创意日报表查询与同步")
+@Slf4j
+@RestController
+@RequestMapping("/api/gdt/daily-report")
+@RequiredArgsConstructor
+public class DailyReportController {
+
+    private final DailyReportService dailyReportService;
+
+    /**
+     * 手动触发同步(指定账户、日期范围、时间口径)
+     */
+    @Operation(summary = "手动同步日报表", description = "指定账户和日期范围,将腾讯广告日报数据同步到本地数据库")
+    @PostMapping("/sync")
+    public Result<Void> sync(
+            @Parameter(description = "工号") @RequestParam String jobNumber,
+            @Parameter(description = "组织账户ID") @RequestParam Long orgAccountId,
+            @Parameter(description = "广告账户ID") @RequestParam Long accountId,
+            @Parameter(description = "账号组ID") @RequestParam(defaultValue = "0") Long groupId,
+            @Parameter(description = "账号组名称") @RequestParam(required = false) String groupName,
+            @Parameter(description = "开始日期 yyyy-MM-dd") @RequestParam String startDate,
+            @Parameter(description = "结束日期 yyyy-MM-dd") @RequestParam String endDate,
+            @Parameter(description = "时间口径 REQUEST_TIME / REPORTING_TIME")
+            @RequestParam(defaultValue = "REQUEST_TIME") String timeLine,
+            @AuthUser SysUser user) {
+        try {
+            int saved = dailyReportService.syncReport(jobNumber, orgAccountId, accountId,
+                    groupId, groupName, startDate, endDate, timeLine);
+            return Result.<Void>success("同步成功,共写入 " + saved + " 条数据").withCount(saved);
+        } catch (Exception e) {
+            log.error("日报表同步失败 accountId={} timeLine={}", accountId, timeLine, e);
+            return Result.fail("同步失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 分页查询日报表
+     */
+    @Operation(summary = "查询日报表列表", description = "分页查询指定口径的动态创意日报数据")
+    @GetMapping("/list")
+    public Result<?> list(
+            @Parameter(description = "时间口径 REQUEST_TIME / REPORTING_TIME")
+            @RequestParam(defaultValue = "REQUEST_TIME") String timeLine,
+            @Parameter(description = "账号组ID(可选)") @RequestParam(required = false) Long groupId,
+            @Parameter(description = "广告账户ID(可选)") @RequestParam(required = false) Long accountId,
+            @Parameter(description = "开始日期 yyyy-MM-dd(可选)") @RequestParam(required = false) String startDate,
+            @Parameter(description = "结束日期 yyyy-MM-dd(可选)") @RequestParam(required = false) String endDate,
+            @Parameter(description = "页码") @RequestParam(defaultValue = "1") long page,
+            @Parameter(description = "每页数量") @RequestParam(defaultValue = "20") long pageSize) {
+        try {
+            Page<? extends BaseDailyCreativeReport> result =
+                    dailyReportService.listReports(timeLine, groupId, accountId, startDate, endDate, page, pageSize);
+            return Result.success(result.getRecords(), "查询成功")
+                    .withPage(page, pageSize, result.getTotal());
+        } catch (Exception e) {
+            log.error("查询日报表失败 timeLine={} groupId={} accountId={}", timeLine, groupId, accountId, e);
+            return Result.fail("查询失败:" + e.getMessage());
+        }
+    }
+}

+ 0 - 2
src/main/java/com/moka/gdtauto/controller/SysUserController.java

@@ -6,7 +6,6 @@ import com.moka.gdtauto.common.Result;
 import com.moka.gdtauto.controller.vo.UserVo;
 import com.moka.gdtauto.entity.SysUser;
 import com.moka.gdtauto.service.SysUserService;
-import com.moka.gdtauto.service.TencentAdsAuthService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -32,7 +31,6 @@ import java.util.Map;
 public class SysUserController {
 
     private final SysUserService sysUserService;
-    private final TencentAdsAuthService authService;
 
     /**
      * 用户登录

+ 0 - 1
src/main/java/com/moka/gdtauto/controller/TencentConversionController.java

@@ -13,7 +13,6 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 
 import com.moka.gdtauto.annotation.AuthUser;
-import com.moka.gdtauto.entity.SysUser;
 
 import java.util.List;
 

+ 2 - 4
src/main/java/com/moka/gdtauto/entity/AdPlan.java

@@ -1,15 +1,13 @@
 package com.moka.gdtauto.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
-import com.baomidou.mybatisplus.annotation.TableField;
-import java.util.List;
-import com.moka.gdtauto.entity.AdPlanCreative;
-
 import java.time.LocalDateTime;
+import java.util.List;
 
 /**
  * 广告计划实体

+ 414 - 0
src/main/java/com/moka/gdtauto/entity/BaseDailyCreativeReport.java

@@ -0,0 +1,414 @@
+package com.moka.gdtauto.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 动态创意日报表 - 基类(供 req/rep 两张表共用)
+ *
+ * @author moka
+ * @since 2026-03-03
+ */
+@Data
+public abstract class BaseDailyCreativeReport {
+
+    /** 主键ID */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /** 广告主账号ID */
+    private Long accountId;
+
+    /** 账号组ID(来自 AccountGroup.id) */
+    private Long groupId;
+
+    /** 账号组名称 */
+    private String groupName;
+
+    /** 动态创意ID */
+    private Long dynamicCreativeId;
+
+    /** 日期 */
+    private LocalDate date;
+
+    // ── 基础曝光点击 ──────────────────────────────────────────────────────────
+    /** 曝光次数 */
+    private Long viewCount;
+    /** 曝光人数 */
+    private Long viewUserCount;
+    /** 人均曝光次数 */
+    private BigDecimal avgViewPerUser;
+    /** 点击次数 */
+    private Long validClickCount;
+    /** 点击人数 */
+    private Long clickUserCount;
+    /** 点击均价(分) */
+    private Long cpc;
+    /** 点击率 */
+    private BigDecimal ctr;
+    /** 可转化点击次数 */
+    private Long valuableClickCount;
+    /** 可转化点击成本(分) */
+    private Long valuableClickCost;
+    /** 可转化点击率 */
+    private BigDecimal valuableClickRate;
+
+    // ── 花费 ─────────────────────────────────────────────────────────────────
+    /** 花费(分) */
+    private Long cost;
+    /** 一键起量消耗(分) */
+    private Long acquisitionCost;
+    /** 千次展现均价(分) */
+    private Long thousandDisplayPrice;
+
+    // ── 转化 ─────────────────────────────────────────────────────────────────
+    /** 目标转化量 */
+    private Long conversionsCount;
+    /** 目标转化率 */
+    private BigDecimal conversionsRate;
+    /** 目标转化成本(分) */
+    private Long conversionsCost;
+    /** 深度目标转化量 */
+    private Long deepConversionsCount;
+    /** 深度目标转化率 */
+    private BigDecimal deepConversionsRate;
+    /** 深度转化成本(分) */
+    private Long deepConversionsCost;
+    /** 目标转化量(曝光归因) */
+    private Long conversionsByDisplayCount;
+    /** 目标转化率(曝光归因) */
+    private BigDecimal conversionsByDisplayRate;
+    /** 目标转化成本(曝光归因,分) */
+    private Long conversionsByDisplayCost;
+    /** 目标转化量(点击归因) */
+    private Long conversionsByClickCount;
+    /** 目标转化率(点击归因) */
+    private BigDecimal conversionsByClickRate;
+    /** 目标转化成本(点击归因,分) */
+    private Long conversionsByClickCost;
+    /** 目标转化量(在线预览) */
+    private Long previewConversionsCount;
+    /** 深度目标转化量(在线预览) */
+    private Long previewDeepConversionsCount;
+
+    // ── 视频播放 ──────────────────────────────────────────────────────────────
+    /** 视频有效播放次数 */
+    private Long videoOuterPlayCount;
+    /** 视频有效播放人数 */
+    private Long videoOuterPlayUserCount;
+    /** 人均播放次数 */
+    private BigDecimal avgUserPlayCount;
+    /** 平均有效播放时长(秒) */
+    private BigDecimal videoOuterPlayTimeCount;
+    /** 平均有效播放进度 */
+    private BigDecimal videoOuterPlayTimeAvgRate;
+    /** 有效播放率 */
+    private BigDecimal videoOuterPlayRate;
+    /** 有效播放成本(分) */
+    private Long videoOuterPlayCost;
+    /** 10%进度播放次数 */
+    private Long videoOuterPlay10Count;
+    /** 25%进度播放次数 */
+    private Long videoOuterPlay25Count;
+    /** 50%进度播放次数 */
+    private Long videoOuterPlay50Count;
+    /** 75%进度播放次数 */
+    private Long videoOuterPlay75Count;
+    /** 90%进度播放次数 */
+    private Long videoOuterPlay90Count;
+    /** 95%进度播放次数 */
+    private Long videoOuterPlay95Count;
+    /** 100%进度播放次数 */
+    private Long videoOuterPlay100Count;
+    /** 3s播放完成次数 */
+    private Long videoOuterPlay3sCount;
+    /** 3s播放完成率 */
+    private BigDecimal videoOuterPlay3sRate;
+    /** 5s播放完成次数 */
+    private Long videoOuterPlay5sCount;
+    /** 7s播放完成次数 */
+    private Long videoOuterPlay7sCount;
+
+    // ── 互动 ─────────────────────────────────────────────────────────────────
+    /** 阅读次数 */
+    private Long readCount;
+    /** 阅读成本(分) */
+    private Long readCost;
+    /** 评论次数 */
+    private Long commentCount;
+    /** 评论成本(分) */
+    private Long commentCost;
+    /** 点赞次数 */
+    private Long praiseCount;
+    /** 点赞成本(分) */
+    private Long praiseCost;
+    /** 分享次数 */
+    private Long forwardCount;
+    /** 分享成本(分) */
+    private Long forwardCost;
+    /** 不感兴趣点击次数 */
+    private Long noInterestCount;
+
+    // ── 素材点击 ──────────────────────────────────────────────────────────────
+    /** 素材点击次数 */
+    private Long liveStreamCrtClickCnt;
+    /** 外层图片点击次数 */
+    private Long clickImageCount;
+    /** 头像点击次数 */
+    private Long clickHeadCount;
+    /** 文字链点击次数 */
+    private Long clickDetailCount;
+    /** 本地门店点击次数 */
+    private Long clickPoiCount;
+    /** 顶部运营位点击次数 */
+    private Long zoneHeaderClickCount;
+    /** 官方信息区点击次数 */
+    private Long basicInfoClientCount;
+    /** 官方账号区点击次数 */
+    private Long accountInfoClickCount;
+    /** 官方账号区直播中头像点击次数 */
+    private Long clkAccountLivingStatusPv;
+    /** 官方账号区小程序组件点击次数 */
+    private Long clkAccountinfoWeappPv;
+    /** 官方账号区视频号组件点击次数 */
+    private Long clkAccountinfoFinderPv;
+    /** 官方账号区公众号组件点击次数 */
+    private Long clkAccountinfoBizPv;
+    /** 官方账号区系列tab总点击次数 */
+    private Long clkAccountInfoProducttabPv;
+    /** 官方账号区商品卡总点击次数 */
+    private Long clkAccountInfoProductdetailPv;
+    /** 热门活动区点击次数 */
+    private Long activityInfoClickCount;
+
+    // ── 线索 ─────────────────────────────────────────────────────────────────
+    /** 综合销售线索人数 */
+    private Long overallLeadsPurchaseCount;
+    /** 有效线索次数 */
+    private Long effectiveLeadsCount;
+    /** 有效线索成本(分) */
+    private Long effectiveCost;
+    /** 有效线索人数 */
+    private Long effectLeadsPurchaseCount;
+    /** 有效线索成本人数(分) */
+    private Long effectLeadsPurchaseCost;
+
+    // ── 落地页 ────────────────────────────────────────────────────────────────
+    /** 落地页曝光次数 */
+    private Long platformPageViewCount;
+    /** 落地页曝光率 */
+    private BigDecimal platformPageViewRate;
+    /** 落地页组件点击次数 */
+    private Long lanButtonClickCount;
+    /** 落地页组件点击人数 */
+    private Long lanJumpButtonClickers;
+    /** 落地页点击成本(分) */
+    private Long lanButtonClickCost;
+    /** 落地页点击率(人数) */
+    private BigDecimal lanJumpButtonCtr;
+    /** 落地页点击成本人数(分) */
+    private Long lanJumpButtonClickCost;
+
+    // ── 关键页面 ──────────────────────────────────────────────────────────────
+    /** 关键页面访问次数 */
+    private Long keyPageViewCount;
+    /** 关键页面访问次数(曝光归因) */
+    private Long keyPageViewByDisplayCount;
+    /** 关键页面访问次数(点击归因) */
+    private Long keyPageViewByClickCount;
+    /** 关键页面访问人数 */
+    private Long keyPageUv;
+    /** 关键页面访问成本(分) */
+    private Long keyPageViewCost;
+    /** 关键页面访问率 */
+    private BigDecimal keyPageViewRate;
+
+    // ── 商品页 ────────────────────────────────────────────────────────────────
+    /** 商品页浏览次数 */
+    private Long landingCommodityDetailExpPv;
+    /** 商品页浏览次数(曝光归因) */
+    private Long appCommodityPageViewByDisplayCount;
+    /** 商品页浏览次数(点击归因) */
+    private Long appCommodityPageViewByClickCount;
+    /** 商品页浏览人数 */
+    private Long viewCommodityPageUv;
+    /** 商品页浏览率 */
+    private BigDecimal webCommodityPageViewRate;
+    /** 商品页浏览成本(分) */
+    private Long webCommodityPageViewCost;
+
+    // ── 导航 ─────────────────────────────────────────────────────────────────
+    /** 自有页导航次数 */
+    private Long ownPageNavigationCount;
+    /** 自有页导航成本(分) */
+    private Long ownPageNaviCost;
+    /** 平台页导航次数 */
+    private Long platformPageNavigationCount;
+    /** 平台页导航成本(分) */
+    private Long platformPageNavigationCost;
+    /** 平台页门店点击次数 */
+    private Long platformShopNavigationCount;
+    /** 平台页门店页导航成本(分) */
+    private Long platformShopNavigationCost;
+
+    // ── 活动页/加粉 ───────────────────────────────────────────────────────────
+    /** 活动页面访问次数 */
+    private Long activePageViews;
+    /** 活动页面访问人数 */
+    private Long activePageViewers;
+    /** 活动页面互动次数 */
+    private Long activePageInteractionAmount;
+    /** 活动页面互动人数 */
+    private Long activePageInteractionUsers;
+    /** 加粉引导页浏览次数 */
+    private Long guideToFollowPageViews;
+    /** 加粉引导页浏览人数 */
+    private Long guideToFollowPageViewers;
+    /** 加粉引导页互动次数 */
+    private Long guideToFollowPageInteractionAmount;
+    /** 加粉引导页互动人数 */
+    private Long guideToFollowPageInteractionUsers;
+    /** 落地页曝光人数 */
+    private Long platformKeyPageViewUserCount;
+
+    // ── 在线咨询 ──────────────────────────────────────────────────────────────
+    /** 在线咨询次数 */
+    private Long pageConsultCount;
+    /** 在线咨询人数 */
+    private Long consultUvCount;
+    /** 在线咨询率 */
+    private BigDecimal pageConsultRate;
+    /** 在线咨询成本(分) */
+    private Long pageConsultCost;
+    /** 咨询留资人数 */
+    private Long consultLeaveInfoUsers;
+    /** 咨询留咨成本(分) */
+    private Long consultLeaveInfoCost;
+    /** 潜在客户线索次数-咨询 */
+    private Long potentialConsultCount;
+    /** 有效线索次数-咨询 */
+    private Long effectiveConsultCount;
+    /** 附加创意智能咨询次数 */
+    private Long toolConsultCount;
+
+    // ── 表单预约 ──────────────────────────────────────────────────────────────
+    /** 表单预约次数 */
+    private Long pageReservationCount;
+    /** 表单预约次数(曝光归因) */
+    private Long pageReservationByDisplayCount;
+    /** 表单预约次数(点击归因) */
+    private Long pageReservationByClickCount;
+    /** 表单预约人数 */
+    private Long reservationUv;
+    /** 表单预约金额(分) */
+    private Long reservationAmount;
+    /** 表单预约成本(分) */
+    private Long pageReservationCost;
+    /** 表单预约成本人数(分) */
+    private Long pageReservationCostWithPeople;
+    /** 表单预约率 */
+    private BigDecimal pageReservationRate;
+    /** 表单预约ROI */
+    private BigDecimal pageReservationRoi;
+    /** 公众号内表单预约人数 */
+    private Long bizReservationUv;
+    /** 公众号内表单预约率 */
+    private BigDecimal bizReservationFollowRate;
+    /** 附加创意表单预约次数 */
+    private Long externalFormReservationCount;
+    /** 潜在客户线索次数-表单 */
+    private Long potentialReserveCount;
+    /** 意向表单人数 */
+    private Long reservationCheckUv;
+    /** 意向表单成本(分) */
+    private Long reservationCheckUvCost;
+    /** 意向表单率(人数) */
+    private BigDecimal reservationCheckUvRate;
+    /** 有效线索次数-表单 */
+    private Long effectiveReserveCount;
+    /** 有效线索人数-表单 */
+    private Long validLeadsUv;
+    /** 排程人数 */
+    private Long tryOutIntentionUv;
+    /** 无效线索人数 */
+    private Long ineffectiveLeadsUv;
+
+    // ── 优惠券 ────────────────────────────────────────────────────────────────
+    /** 领券次数 */
+    private Long couponGetPv;
+    /** 领券成本(分) */
+    private Long couponGetCost;
+    /** 领券率 */
+    private BigDecimal couponGetRate;
+    /** 平台页卡券点击次数 */
+    private Long platformCouponClickCount;
+    /** 平台页卡券购买次数 */
+    private Long purchaseAmountWithCoupon;
+    /** 平台页卡券购买率 */
+    private BigDecimal couponPurchaseRate;
+    /** 平台页卡券购买成本(分) */
+    private Long purchaseAmountWithCouponCost;
+    /** 优惠券使用次数 */
+    private Long couponUsageNumber;
+
+    // ── 电话直拨 ──────────────────────────────────────────────────────────────
+    /** 电话直拨次数 */
+    private Long pagePhoneCallDirectCount;
+    /** 电话直拨率 */
+    private BigDecimal pagePhoneCallDirectRate;
+    /** 电话直拨成本(分) */
+    private Long pagePhoneCallDirectCost;
+    /** 潜在客户线索次数-电话 */
+    private Long potentialPhoneCount;
+    /** 潜在客户人数-电话 */
+    private Long potentialCustomerPhoneUv;
+    /** 有效线索次数-电话 */
+    private Long effectivePhoneCount;
+    /** 有效线索人数-电话 */
+    private Long validPhoneUv;
+
+    // ── ROI收益(LTV) ────────────────────────────────────────────────────────
+    /** 1天收益(分) */
+    @TableField("income_val_1")
+    private Long incomeVal1;
+    /** 1天ROI */
+    @TableField("income_roi_1")
+    private BigDecimal incomeRoi1;
+    /** 3天收益(分) */
+    @TableField("income_val_3")
+    private Long incomeVal3;
+    /** 3天ROI */
+    @TableField("income_roi_3")
+    private BigDecimal incomeRoi3;
+    /** 7天收益(分) */
+    @TableField("income_val_7")
+    private Long incomeVal7;
+    /** 7天ROI */
+    @TableField("income_roi_7")
+    private BigDecimal incomeRoi7;
+    /** 14天收益(分) */
+    @TableField("income_val_14")
+    private Long incomeVal14;
+    /** 14天ROI */
+    @TableField("income_roi_14")
+    private BigDecimal incomeRoi14;
+    /** 24小时收益(分) */
+    @TableField("income_val_24h")
+    private Long incomeVal24h;
+    /** 1天24小时ROI */
+    @TableField("income_roi_1_24h")
+    private BigDecimal incomeRoi1_24h;
+
+    // ── 审计字段 ──────────────────────────────────────────────────────────────
+    /** 创建时间 */
+    private LocalDateTime createdTime;
+
+    /** 更新时间 */
+    private LocalDateTime updatedTime;
+}

+ 17 - 0
src/main/java/com/moka/gdtauto/entity/RepDailyCreativeReport.java

@@ -0,0 +1,17 @@
+package com.moka.gdtauto.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 动态创意日报表(统计时间口径 REPORTING_TIME)
+ *
+ * @author moka
+ * @since 2026-03-03
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("rep_daily_creative_report")
+public class RepDailyCreativeReport extends BaseDailyCreativeReport {
+}

+ 17 - 0
src/main/java/com/moka/gdtauto/entity/ReqDailyCreativeReport.java

@@ -0,0 +1,17 @@
+package com.moka.gdtauto.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 动态创意日报表(请求时间口径 REQUEST_TIME)
+ *
+ * @author moka
+ * @since 2026-03-03
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("req_daily_creative_report")
+public class ReqDailyCreativeReport extends BaseDailyCreativeReport {
+}

+ 24 - 0
src/main/java/com/moka/gdtauto/mapper/RepDailyCreativeReportMapper.java

@@ -0,0 +1,24 @@
+package com.moka.gdtauto.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.moka.gdtauto.entity.RepDailyCreativeReport;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 动态创意日报表 Mapper(统计时间口径 REPORTING_TIME)
+ *
+ * @author moka
+ * @since 2026-03-03
+ */
+@Mapper
+public interface RepDailyCreativeReportMapper extends BaseMapper<RepDailyCreativeReport> {
+
+    /**
+     * 插入或更新(ON DUPLICATE KEY UPDATE)
+     * 以 account_id + dynamic_creative_id + date 为唯一键进行 upsert
+     *
+     * @param report 报表数据
+     */
+    void upsert(@Param("report") RepDailyCreativeReport report);
+}

+ 24 - 0
src/main/java/com/moka/gdtauto/mapper/ReqDailyCreativeReportMapper.java

@@ -0,0 +1,24 @@
+package com.moka.gdtauto.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.moka.gdtauto.entity.ReqDailyCreativeReport;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 动态创意日报表 Mapper(请求时间口径 REQUEST_TIME)
+ *
+ * @author moka
+ * @since 2026-03-03
+ */
+@Mapper
+public interface ReqDailyCreativeReportMapper extends BaseMapper<ReqDailyCreativeReport> {
+
+    /**
+     * 插入或更新(ON DUPLICATE KEY UPDATE)
+     * 以 account_id + dynamic_creative_id + date 为唯一键进行 upsert
+     *
+     * @param report 报表数据
+     */
+    void upsert(@Param("report") ReqDailyCreativeReport report);
+}

+ 387 - 0
src/main/java/com/moka/gdtauto/service/DailyReportService.java

@@ -0,0 +1,387 @@
+package com.moka.gdtauto.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.moka.gdtauto.client.TencentAdsApiClientFactory;
+import com.moka.gdtauto.entity.AccountGroup;
+import com.moka.gdtauto.entity.AccountGroupAccountRelationship;
+import com.moka.gdtauto.entity.BaseDailyCreativeReport;
+import com.moka.gdtauto.entity.RepDailyCreativeReport;
+import com.moka.gdtauto.entity.ReqDailyCreativeReport;
+import com.moka.gdtauto.entity.TencentAccount;
+import com.moka.gdtauto.mapper.AccountGroupAccountRelationshipMapper;
+import com.moka.gdtauto.mapper.AccountGroupMapper;
+import com.moka.gdtauto.mapper.RepDailyCreativeReportMapper;
+import com.moka.gdtauto.mapper.ReqDailyCreativeReportMapper;
+import com.tencent.ads.model.v3.DailyReportsGetResponseData;
+import com.tencent.ads.model.v3.ReportDateRange;
+import com.tencent.ads.model.v3.ReportStruct;
+import com.tencent.ads.v3.TencentAds;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 动态创意日报表 Service
+ * 支持双口径(REQUEST_TIME / REPORTING_TIME)同步与查询
+ *
+ * @author moka
+ * @since 2026-03-03
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class DailyReportService {
+
+    private final TencentAdsApiClientFactory clientFactory;
+    private final TencentAccountService accountService;
+    private final AccountGroupAccountRelationshipMapper relationshipMapper;
+    private final AccountGroupMapper accountGroupMapper;
+    private final ReqDailyCreativeReportMapper reqMapper;
+    private final RepDailyCreativeReportMapper repMapper;
+
+    /** 同步时请求的指标字段 */
+    private static final List<String> SYNC_FIELDS = Arrays.asList(
+            "dynamic_creative_id", "date",
+            // 曝光点击
+            "view_count", "view_user_count", "avg_view_per_user",
+            "valid_click_count", "click_user_count", "cpc", "ctr",
+            "valuable_click_count", "valuable_click_cost", "valuable_click_rate",
+            // 花费
+            "cost", "thousand_display_price",
+            // 转化
+            "conversions_count", "conversions_rate", "conversions_cost",
+            "deep_conversions_count", "deep_conversions_rate", "deep_conversions_cost",
+            "conversions_by_display_count", "conversions_by_click_count",
+            "preview_conversions_count", "preview_deep_conversions_count",
+            // 视频
+            "video_outer_play_count", "video_outer_play_user_count", "avg_user_play_count",
+            "video_outer_play_time_count", "video_outer_play_rate", "video_outer_play_cost",
+            "video_outer_play3s_count", "video_outer_play3s_rate",
+            "video_outer_play25_count", "video_outer_play50_count",
+            "video_outer_play75_count", "video_outer_play100_count",
+            // 互动
+            "read_count", "comment_count", "praise_count", "forward_count",
+            // 落地页
+            "platform_page_view_count", "platform_page_view_rate",
+            "lan_button_click_count", "lan_jump_button_clickers",
+            // 关键页面
+            "key_page_view_count", "key_page_uv",
+            // ROI/LTV
+            "income_val_1", "income_roi_1",
+            "income_val_3", "income_roi_3",
+            "income_val_7", "income_roi_7",
+            "income_val_14", "income_roi_14",
+            "income_val_24h", "income_roi_1_24h"
+    );
+
+    // ─── 同步方法 ─────────────────────────────────────────────────────────────
+
+    /**
+     * 同步指定账户的日报表(分页拉取直到全量完成)
+     *
+     * @param jobNumber    工号(用于获取 access_token)
+     * @param orgAccountId 组织账户ID
+     * @param accountId    广告账户ID
+     * @param groupId      账号组ID
+     * @param groupName    账号组名称
+     * @param startDate    开始日期 yyyy-MM-dd
+     * @param endDate      结束日期 yyyy-MM-dd
+     * @param timeLine     时间口径 REQUEST_TIME / REPORTING_TIME
+     * @return 成功写入行数
+     */
+    public int syncReport(String jobNumber, Long orgAccountId, Long accountId,
+                          Long groupId, String groupName,
+                          String startDate, String endDate, String timeLine) throws Exception {
+        log.info("开始同步日报表 accountId={} timeLine={} [{}, {}]", accountId, timeLine, startDate, endDate);
+
+        TencentAds tencentAds = clientFactory.getTencentAds(jobNumber, orgAccountId);
+
+        ReportDateRange dateRange = new ReportDateRange();
+        dateRange.setStartDate(startDate);
+        dateRange.setEndDate(endDate);
+
+        List<String> groupBy = Arrays.asList("dynamic_creative_id", "date");
+
+        long page = 1L;
+        long pageSize = 1000L;
+        int totalSaved = 0;
+
+        while (true) {
+            DailyReportsGetResponseData response = tencentAds.dailyReports().dailyReportsGet(
+                    "REPORT_LEVEL_DYNAMIC_CREATIVE",
+                    dateRange,
+                    groupBy,
+                    SYNC_FIELDS,
+                    accountId,
+                    null,
+                    null,
+                    timeLine,
+                    page,
+                    pageSize,
+                    null
+            );
+
+            if (response == null || response.getList() == null || response.getList().isEmpty()) {
+                break;
+            }
+
+            List<ReportStruct> list = response.getList();
+            for (ReportStruct rs : list) {
+                if (rs.getDynamicCreativeId() == null || rs.getDate() == null) {
+                    continue;
+                }
+                if ("REQUEST_TIME".equals(timeLine)) {
+                    ReqDailyCreativeReport entity = toReqEntity(accountId, groupId, groupName, rs);
+                    reqMapper.upsert(entity);
+                } else {
+                    RepDailyCreativeReport entity = toRepEntity(accountId, groupId, groupName, rs);
+                    repMapper.upsert(entity);
+                }
+                totalSaved++;
+            }
+
+            long totalNumber = response.getPageInfo() != null
+                    ? response.getPageInfo().getTotalNumber() : 0L;
+            if (page * pageSize >= totalNumber) {
+                break;
+            }
+            page++;
+        }
+
+        log.info("日报表同步完成 accountId={} timeLine={} saved={}", accountId, timeLine, totalSaved);
+        return totalSaved;
+    }
+
+    /**
+     * 同步所有账户(定时任务调用)——通过 AccountGroupAccountRelationship 关联获取 groupId / groupName
+     *
+     * @param startDate 开始日期
+     * @param endDate   结束日期
+     * @param timeLine  时间口径
+     * @return 成功保存总行数
+     */
+    public int syncAllAccounts(String startDate, String endDate, String timeLine) {
+        // 查询所有账号组-账户关系
+        List<AccountGroupAccountRelationship> relationships = relationshipMapper.selectList(null);
+        if (relationships.isEmpty()) {
+            log.warn("没有可同步的账户(AccountGroupAccountRelationship 为空)");
+            return 0;
+        }
+
+        // 预载所有账号组信息(减少重复查询)
+        java.util.Map<Long, AccountGroup> groupMap = new java.util.HashMap<>();
+        accountGroupMapper.selectList(new LambdaQueryWrapper<AccountGroup>().eq(AccountGroup::getDeleted, 0))
+                .forEach(g -> groupMap.put(g.getId(), g));
+
+        log.info("开始批量同步日报表 relationships={} timeLine={} [{}, {}]",
+                relationships.size(), timeLine, startDate, endDate);
+
+        int total = 0;
+        for (AccountGroupAccountRelationship rel : relationships) {
+            Long groupId = rel.getGroupId();
+            Long accountId = rel.getAccountId();
+            AccountGroup group = groupMap.get(groupId);
+
+            if (group == null) {
+                log.warn("账号组信息不存在 groupId={}", groupId);
+                continue;
+            }
+           
+            try {
+                int saved = syncReport(
+                        "12458",
+                        41644744L,
+                        accountId,
+                        groupId,
+                        group.getGroupName(),
+                        startDate, endDate, timeLine
+                );
+                total += saved;
+            } catch (Exception e) {
+                log.error("同步日报表失败 groupId={} accountId={}", groupId, accountId, e);
+            }
+        }
+        log.info("批量同步日报表完成 total={}", total);
+        return total;
+    }
+
+    // ─── 查询方法 ─────────────────────────────────────────────────────────────
+
+    /**
+     * 分页查询日报表
+     *
+     * @param timeLine  时间口径(决定查哪张表)
+     * @param groupId   可选,账号组ID
+     * @param accountId 可选,广告账户ID
+     * @param startDate 可选,开始日期
+     * @param endDate   可选,结束日期
+     * @param pageNum   页码
+     * @param pageSize  每页大小
+     * @return 分页结果
+     */
+    public Page<? extends BaseDailyCreativeReport> listReports(
+            String timeLine, Long groupId, Long accountId, String startDate, String endDate,
+            long pageNum, long pageSize) {
+
+        if ("REPORTING_TIME".equals(timeLine)) {
+            LambdaQueryWrapper<RepDailyCreativeReport> wrapper = buildRepWrapper(groupId, accountId, startDate, endDate);
+            return repMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
+        } else {
+            LambdaQueryWrapper<ReqDailyCreativeReport> wrapper = buildReqWrapper(groupId, accountId, startDate, endDate);
+            return reqMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
+        }
+    }
+
+    private LambdaQueryWrapper<ReqDailyCreativeReport> buildReqWrapper(
+            Long groupId, Long accountId, String startDate, String endDate) {
+        LambdaQueryWrapper<ReqDailyCreativeReport> wrapper = new LambdaQueryWrapper<>();
+        if (groupId != null) {
+            wrapper.eq(ReqDailyCreativeReport::getGroupId, groupId);
+        }
+        if (accountId != null) {
+            wrapper.eq(ReqDailyCreativeReport::getAccountId, accountId);
+        }
+        if (StringUtils.hasText(startDate)) {
+            wrapper.ge(ReqDailyCreativeReport::getDate, LocalDate.parse(startDate));
+        }
+        if (StringUtils.hasText(endDate)) {
+            wrapper.le(ReqDailyCreativeReport::getDate, LocalDate.parse(endDate));
+        }
+        wrapper.orderByDesc(ReqDailyCreativeReport::getDate);
+        return wrapper;
+    }
+
+    private LambdaQueryWrapper<RepDailyCreativeReport> buildRepWrapper(
+            Long groupId, Long accountId, String startDate, String endDate) {
+        LambdaQueryWrapper<RepDailyCreativeReport> wrapper = new LambdaQueryWrapper<>();
+        if (groupId != null) {
+            wrapper.eq(RepDailyCreativeReport::getGroupId, groupId);
+        }
+        if (accountId != null) {
+            wrapper.eq(RepDailyCreativeReport::getAccountId, accountId);
+        }
+        if (StringUtils.hasText(startDate)) {
+            wrapper.ge(RepDailyCreativeReport::getDate, LocalDate.parse(startDate));
+        }
+        if (StringUtils.hasText(endDate)) {
+            wrapper.le(RepDailyCreativeReport::getDate, LocalDate.parse(endDate));
+        }
+        wrapper.orderByDesc(RepDailyCreativeReport::getDate);
+        return wrapper;
+    }
+
+    // ─── 映射方法 ─────────────────────────────────────────────────────────────
+
+    private ReqDailyCreativeReport toReqEntity(Long accountId, Long groupId, String groupName, ReportStruct rs) {
+        ReqDailyCreativeReport e = new ReqDailyCreativeReport();
+        fillFields(e, accountId, groupId, groupName, rs);
+        return e;
+    }
+
+    private RepDailyCreativeReport toRepEntity(Long accountId, Long groupId, String groupName, ReportStruct rs) {
+        RepDailyCreativeReport e = new RepDailyCreativeReport();
+        fillFields(e, accountId, groupId, groupName, rs);
+        return e;
+    }
+
+    private void fillFields(BaseDailyCreativeReport e, Long accountId, Long groupId, String groupName, ReportStruct rs) {
+        e.setAccountId(accountId);
+        e.setGroupId(groupId);
+        e.setGroupName(groupName);
+        e.setDynamicCreativeId(rs.getDynamicCreativeId());
+        e.setDate(LocalDate.parse(rs.getDate()));
+        // 基础
+        e.setViewCount(rs.getViewCount());
+        e.setViewUserCount(rs.getViewUserCount());
+        e.setAvgViewPerUser(d2b(rs.getAvgViewPerUser()));
+        e.setValidClickCount(rs.getValidClickCount());
+        e.setClickUserCount(rs.getClickUserCount());
+        e.setCpc(rs.getCpc());
+        e.setCtr(d2b(rs.getCtr()));
+        e.setValuableClickCount(rs.getValuableClickCount());
+        e.setValuableClickCost(rs.getValuableClickCost());
+        e.setValuableClickRate(d2b(rs.getValuableClickRate()));
+        // 花费
+        e.setCost(rs.getCost());
+        e.setAcquisitionCost(rs.getAcquisitionCost());
+        e.setThousandDisplayPrice(rs.getThousandDisplayPrice());
+        // 转化
+        e.setConversionsCount(rs.getConversionsCount());
+        e.setConversionsRate(d2b(rs.getConversionsRate()));
+        e.setConversionsCost(rs.getConversionsCost());
+        e.setDeepConversionsCount(rs.getDeepConversionsCount());
+        e.setDeepConversionsRate(d2b(rs.getDeepConversionsRate()));
+        e.setDeepConversionsCost(rs.getDeepConversionsCost());
+        e.setConversionsByDisplayCount(rs.getConversionsByDisplayCount());
+        e.setConversionsByDisplayRate(d2b(rs.getConversionsByDisplayRate()));
+        e.setConversionsByDisplayCost(rs.getConversionsByDisplayCost());
+        e.setConversionsByClickCount(rs.getConversionsByClickCount());
+        e.setConversionsByClickRate(d2b(rs.getConversionsByClickRate()));
+        e.setConversionsByClickCost(rs.getConversionsByClickCost());
+        e.setPreviewConversionsCount(rs.getPreviewConversionsCount());
+        e.setPreviewDeepConversionsCount(rs.getPreviewDeepConversionsCount());
+        // 视频
+        e.setVideoOuterPlayCount(rs.getVideoOuterPlayCount());
+        e.setVideoOuterPlayUserCount(rs.getVideoOuterPlayUserCount());
+        e.setAvgUserPlayCount(d2b(rs.getAvgUserPlayCount()));
+        e.setVideoOuterPlayTimeCount(d2b(rs.getVideoOuterPlayTimeCount()));
+        e.setVideoOuterPlayTimeAvgRate(d2b(rs.getVideoOuterPlayTimeAvgRate()));
+        e.setVideoOuterPlayRate(d2b(rs.getVideoOuterPlayRate()));
+        e.setVideoOuterPlayCost(rs.getVideoOuterPlayCost());
+        e.setVideoOuterPlay10Count(rs.getVideoOuterPlay10Count());
+        e.setVideoOuterPlay25Count(rs.getVideoOuterPlay25Count());
+        e.setVideoOuterPlay50Count(rs.getVideoOuterPlay50Count());
+        e.setVideoOuterPlay75Count(rs.getVideoOuterPlay75Count());
+        e.setVideoOuterPlay90Count(rs.getVideoOuterPlay90Count());
+        e.setVideoOuterPlay95Count(rs.getVideoOuterPlay95Count());
+        e.setVideoOuterPlay100Count(rs.getVideoOuterPlay100Count());
+        e.setVideoOuterPlay3sCount(rs.getVideoOuterPlay3sCount());
+        e.setVideoOuterPlay3sRate(d2b(rs.getVideoOuterPlay3sRate()));
+        e.setVideoOuterPlay5sCount(rs.getVideoOuterPlay5sCount());
+        e.setVideoOuterPlay7sCount(rs.getVideoOuterPlay7sCount());
+        // 互动
+        e.setReadCount(rs.getReadCount());
+        e.setReadCost(rs.getReadCost());
+        e.setCommentCount(rs.getCommentCount());
+        e.setCommentCost(rs.getCommentCost());
+        e.setPraiseCount(rs.getPraiseCount());
+        e.setPraiseCost(rs.getPraiseCost());
+        e.setForwardCount(rs.getForwardCount());
+        e.setForwardCost(rs.getForwardCost());
+        e.setNoInterestCount(rs.getNoInterestCount());
+        // 落地页
+        e.setPlatformPageViewCount(rs.getPlatformPageViewCount());
+        e.setPlatformPageViewRate(d2b(rs.getPlatformPageViewRate()));
+        e.setLanButtonClickCount(rs.getLanButtonClickCount());
+        e.setLanJumpButtonClickers(rs.getLanJumpButtonClickers());
+        e.setLanButtonClickCost(rs.getLanButtonClickCost());
+        e.setLanJumpButtonCtr(d2b(rs.getLanJumpButtonCtr()));
+        e.setLanJumpButtonClickCost(rs.getLanJumpButtonClickCost());
+        // 关键页面
+        e.setKeyPageViewCount(rs.getKeyPageViewCount());
+        e.setKeyPageUv(rs.getKeyPageUv());
+        // ROI/LTV - 注意:SDK字段名 incomeRoi124h 对应 API income_roi_1_24h
+        e.setIncomeVal1(rs.getIncomeVal1());
+        e.setIncomeRoi1(d2b(rs.getIncomeRoi1()));
+        e.setIncomeVal3(rs.getIncomeVal3());
+        e.setIncomeRoi3(d2b(rs.getIncomeRoi3()));
+        e.setIncomeVal7(rs.getIncomeVal7());
+        e.setIncomeRoi7(d2b(rs.getIncomeRoi7()));
+        e.setIncomeVal14(rs.getIncomeVal14());
+        e.setIncomeRoi14(d2b(rs.getIncomeRoi14()));
+        e.setIncomeVal24h(rs.getIncomeVal24h());
+        e.setIncomeRoi1_24h(d2b(rs.getIncomeRoi124h()));
+    }
+
+    /** Double → BigDecimal 安全转换 */
+    private BigDecimal d2b(Double d) {
+        return d == null ? null : BigDecimal.valueOf(d);
+    }
+}

+ 0 - 2
src/main/java/com/moka/gdtauto/service/TencentAdsAdgroupService.java

@@ -1,6 +1,5 @@
 package com.moka.gdtauto.service;
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.moka.gdtauto.client.TencentAdsApiClientFactory;
 import com.moka.gdtauto.entity.TencentAdsAdgroup;
@@ -265,7 +264,6 @@ public class TencentAdsAdgroupService extends ServiceImpl<TencentAdsAdgroupMappe
         // 调用SDK创建广告
         AdgroupsAddResponseData response = tencentAds.adgroups()
             .adgroupsAdd(request);
-        
         log.info("创建广告成功,adgroupId={}", 
             response.getAdgroupId());
         

+ 0 - 1
src/main/java/com/moka/gdtauto/service/TencentAdsAuthService.java

@@ -3,7 +3,6 @@ package com.moka.gdtauto.service;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.moka.gdtauto.config.TencentAdsConfig;
-import com.moka.gdtauto.entity.SysUser;
 import com.moka.gdtauto.entity.TencentAdsAuth;
 import com.moka.gdtauto.mapper.TencentAdsAuthMapper;
 import com.tencent.ads.ApiContextConfig;

+ 0 - 2
src/main/java/com/moka/gdtauto/service/TencentAssetDramaService.java

@@ -3,14 +3,12 @@ package com.moka.gdtauto.service;
 import com.alibaba.fastjson2.JSON;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.moka.gdtauto.client.TencentAdsApiClientFactory;
-import com.moka.gdtauto.entity.TencentAdsAuth;
 import com.moka.gdtauto.entity.TencentAssetDrama;
 import com.moka.gdtauto.mapper.TencentAssetDramaMapper;
 import com.tencent.ads.exception.TencentAdsResponseException;
 import com.tencent.ads.exception.TencentAdsSDKException;
 import com.tencent.ads.model.v3.FilteringStruct;
 import com.tencent.ads.model.v3.MarketingTargetAssetsGetResponseData;
-import com.tencent.ads.model.v3.MarketingTargetType;
 import com.tencent.ads.v3.TencentAds;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;

+ 0 - 2
src/main/java/com/moka/gdtauto/service/TencentConversionService.java

@@ -3,8 +3,6 @@ package com.moka.gdtauto.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.moka.gdtauto.entity.TencentConversion;
 
-import java.util.List;
-
 /**
  * 腾讯广告转化归因服务接口
  * 

+ 4 - 5
src/main/java/com/moka/gdtauto/service/impl/AdPlanConfServiceImpl.java

@@ -10,7 +10,6 @@ import com.moka.gdtauto.service.AdPlanCreativeService;
 import com.moka.gdtauto.service.TencentAdsAdgroupService;
 import com.moka.gdtauto.service.TencentAccountService;
 import com.moka.gdtauto.client.TencentAdsApiClientFactory;
-import com.moka.gdtauto.entity.TencentAccount;
 
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -778,11 +777,11 @@ public class AdPlanConfServiceImpl extends ServiceImpl<AdPlanConfMapper, AdPlanC
         md.update(bytes);
         byte[] digest = md.digest();
         BigInteger bigInt = new BigInteger(1, digest);
-        String hashtext = bigInt.toString(16);
+        String hashText = bigInt.toString(16);
         // 补齐前导0
-        while (hashtext.length() < 32) {
-            hashtext = "0" + hashtext;
+        while (hashText.length() < 32) {
+            hashText = "0" + hashText;
         }
-        return hashtext;
+        return hashText;
     }
 }

+ 0 - 2
src/main/java/com/moka/gdtauto/service/impl/TencentConversionServiceImpl.java

@@ -1,11 +1,9 @@
 package com.moka.gdtauto.service.impl;
 
-import com.alibaba.fastjson2.JSON;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.moka.gdtauto.client.TencentAdsApiClientFactory;
 import com.moka.gdtauto.entity.TencentConversion;
 import com.moka.gdtauto.mapper.TencentConversionMapper;
-import com.moka.gdtauto.service.TencentAdsAuthService;
 import com.moka.gdtauto.service.TencentConversionService;
 import com.tencent.ads.model.v3.*;
 import com.tencent.ads.v3.TencentAds;

+ 0 - 2
src/main/java/com/moka/gdtauto/service/impl/TencentImagesServiceImpl.java

@@ -1,9 +1,7 @@
 package com.moka.gdtauto.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.moka.gdtauto.annotation.AuthUser;
 import com.moka.gdtauto.client.TencentAdsApiClientFactory;
-import com.moka.gdtauto.entity.SysUser;
 import com.moka.gdtauto.entity.TencentAssetDrama;
 import com.moka.gdtauto.entity.TencentImages;
 import com.moka.gdtauto.mapper.TencentImagesMapper;

+ 0 - 2
src/main/java/com/moka/gdtauto/service/impl/TencentVideoServiceImpl.java

@@ -7,8 +7,6 @@ import com.moka.gdtauto.entity.TencentVideo;
 import com.moka.gdtauto.mapper.TencentVideoMapper;
 import com.moka.gdtauto.service.TencentAssetDramaService;
 import com.moka.gdtauto.service.TencentVideoService;
-import com.moka.gdtauto.annotation.AuthUser;
-import com.moka.gdtauto.entity.SysUser;
 import com.moka.gdtauto.util.VideoWatermarkUtil;
 import com.tencent.ads.model.v3.VideosAddResponseData;
 import com.tencent.ads.v3.TencentAds;

+ 100 - 0
src/main/java/com/moka/gdtauto/task/DailyReportSyncTask.java

@@ -0,0 +1,100 @@
+package com.moka.gdtauto.task;
+
+import com.moka.gdtauto.service.DailyReportService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * 动态创意日报表定时同步任务
+ * 支持双口径(REQUEST_TIME / REPORTING_TIME)
+ *
+ * @author moka
+ * @since 2026-03-03
+ */
+@Slf4j
+// @Component
+@RequiredArgsConstructor
+public class DailyReportSyncTask {
+
+    private final DailyReportService dailyReportService;
+
+    private static final DateTimeFormatter FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+    // ─── 同步当日数据 ────────────────────────────────────────────────────────────
+
+    /**
+     * 同步当日 REQUEST_TIME 口径日报表
+     * cron: 每小时的 2,7,12,17,22,27,32,37,42,47,52,57 分执行
+     */
+    @Scheduled(cron = "0 2,7,12,17,22,27,32,37,42,47,52,57 * * * *")
+    @SchedulerLock(name = "syncTodayReqDailyReport", lockAtMostFor = "4m", lockAtLeastFor = "1m")
+    public void syncTodayRequestTime() {
+        String today = LocalDate.now().format(FMT);
+        log.info("[定时任务] 同步当日 REQUEST_TIME 日报表 date={}", today);
+        try {
+            int total = dailyReportService.syncAllAccounts(today, today, "REQUEST_TIME");
+            log.info("[定时任务] 当日 REQUEST_TIME 日报表同步完成 total={}", total);
+        } catch (Exception e) {
+            log.error("[定时任务] 当日 REQUEST_TIME 日报表同步异常", e);
+        }
+    }
+
+    /**
+     * 同步当日 REPORTING_TIME 口径日报表
+     * cron: 每小时的 2,7,12,17,22,27,32,37,42,47,52,57 分执行(与 REQUEST_TIME 错开 30s 避免并发)
+     */
+    @Scheduled(cron = "30 2,7,12,17,22,27,32,37,42,47,52,57 * * * *")
+    @SchedulerLock(name = "syncTodayRepDailyReport", lockAtMostFor = "4m", lockAtLeastFor = "1m")
+    public void syncTodayReportingTime() {
+        String today = LocalDate.now().format(FMT);
+        log.info("[定时任务] 同步当日 REPORTING_TIME 日报表 date={}", today);
+        try {
+            int total = dailyReportService.syncAllAccounts(today, today, "REPORTING_TIME");
+            log.info("[定时任务] 当日 REPORTING_TIME 日报表同步完成 total={}", total);
+        } catch (Exception e) {
+            log.error("[定时任务] 当日 REPORTING_TIME 日报表同步异常", e);
+        }
+    }
+
+    // ─── 同步昨日数据 ────────────────────────────────────────────────────────────
+
+    /**
+     * 同步昨日 REQUEST_TIME 口径日报表
+     * cron: 每天 0,5,8,11,13,15 点的第 3 分钟执行
+     */
+    @Scheduled(cron = "0 3 0,5,8,11,13,15 * * *")
+    @SchedulerLock(name = "syncYesterdayReqDailyReport", lockAtMostFor = "9m", lockAtLeastFor = "2m")
+    public void syncYesterdayRequestTime() {
+        String yesterday = LocalDate.now().minusDays(1).format(FMT);
+        log.info("[定时任务] 同步昨日 REQUEST_TIME 日报表 date={}", yesterday);
+        try {
+            int total = dailyReportService.syncAllAccounts(yesterday, yesterday, "REQUEST_TIME");
+            log.info("[定时任务] 昨日 REQUEST_TIME 日报表同步完成 total={}", total);
+        } catch (Exception e) {
+            log.error("[定时任务] 昨日 REQUEST_TIME 日报表同步异常", e);
+        }
+    }
+
+    /**
+     * 同步昨日 REPORTING_TIME 口径日报表
+     * cron: 每天 0,5,8,11,13,15 点的第 3 分 30 秒执行
+     */
+    @Scheduled(cron = "30 3 0,5,8,11,13,15 * * *")
+    @SchedulerLock(name = "syncYesterdayRepDailyReport", lockAtMostFor = "9m", lockAtLeastFor = "2m")
+    public void syncYesterdayReportingTime() {
+        String yesterday = LocalDate.now().minusDays(1).format(FMT);
+        log.info("[定时任务] 同步昨日 REPORTING_TIME 日报表 date={}", yesterday);
+        try {
+            int total = dailyReportService.syncAllAccounts(yesterday, yesterday, "REPORTING_TIME");
+            log.info("[定时任务] 昨日 REPORTING_TIME 日报表同步完成 total={}", total);
+        } catch (Exception e) {
+            log.error("[定时任务] 昨日 REPORTING_TIME 日报表同步异常", e);
+        }
+    }
+}

+ 0 - 4
src/main/java/com/moka/gdtauto/util/AdgroupsAddReqPool.java

@@ -1,9 +1,5 @@
 package com.moka.gdtauto.util;
 
-import java.lang.annotation.Target;
-import java.util.ArrayList;
-import java.util.List;
-
 import org.springframework.beans.BeanUtils;
 
 import com.tencent.ads.model.v3.AdgroupsAddRequest;

+ 0 - 1
src/main/java/com/moka/gdtauto/util/VideoWatermarkUtil.java

@@ -10,7 +10,6 @@ import javax.imageio.ImageIO;
 import java.awt.*;
 import java.awt.image.BufferedImage;
 import java.io.File;
-import java.io.IOException;
 
 /**
  * 视频水印工具类

+ 201 - 0
src/main/resources/mapper/RepDailyCreativeReportMapper.xml

@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.moka.gdtauto.mapper.RepDailyCreativeReportMapper">
+
+    <!-- 插入或更新(REPORTING_TIME 口径)唯一键: group_id + account_id + dynamic_creative_id + date -->
+    <insert id="upsert" parameterType="com.moka.gdtauto.entity.RepDailyCreativeReport">
+        INSERT INTO rep_daily_creative_report (
+            group_id, group_name, account_id, dynamic_creative_id, date,
+            view_count, view_user_count, avg_view_per_user,
+            valid_click_count, click_user_count, cpc, ctr,
+            valuable_click_count, valuable_click_cost, valuable_click_rate,
+            cost, acquisition_cost, thousand_display_price,
+            conversions_count, conversions_rate, conversions_cost,
+            deep_conversions_count, deep_conversions_rate, deep_conversions_cost,
+            conversions_by_display_count, conversions_by_display_rate, conversions_by_display_cost,
+            conversions_by_click_count, conversions_by_click_rate, conversions_by_click_cost,
+            preview_conversions_count, preview_deep_conversions_count,
+            video_outer_play_count, video_outer_play_user_count, avg_user_play_count,
+            video_outer_play_time_count, video_outer_play_time_avg_rate,
+            video_outer_play_rate, video_outer_play_cost,
+            video_outer_play10_count, video_outer_play25_count, video_outer_play50_count,
+            video_outer_play75_count, video_outer_play90_count, video_outer_play95_count,
+            video_outer_play100_count, video_outer_play3s_count, video_outer_play3s_rate,
+            video_outer_play5s_count, video_outer_play7s_count,
+            read_count, read_cost, comment_count, comment_cost,
+            praise_count, praise_cost, forward_count, forward_cost, no_interest_count,
+            live_stream_crt_click_cnt, click_image_count, click_head_count,
+            click_detail_count, click_poi_count, zone_header_click_count,
+            basic_info_client_count, account_info_click_count,
+            clk_account_living_status_pv, clk_accountinfo_weapp_pv,
+            clk_accountinfo_finder_pv, clk_accountinfo_biz_pv,
+            clk_account_info_producttab_pv, clk_account_info_productdetail_pv,
+            activity_info_click_count,
+            overall_leads_purchase_count, effective_leads_count, effective_cost,
+            effect_leads_purchase_count, effect_leads_purchase_cost,
+            platform_page_view_count, platform_page_view_rate,
+            lan_button_click_count, lan_jump_button_clickers, lan_button_click_cost,
+            lan_jump_button_ctr, lan_jump_button_click_cost,
+            key_page_view_count, key_page_view_by_display_count, key_page_view_by_click_count,
+            key_page_uv, key_page_view_cost, key_page_view_rate,
+            landing_commodity_detail_exp_pv,
+            app_commodity_page_view_by_display_count, app_commodity_page_view_by_click_count,
+            view_commodity_page_uv, web_commodity_page_view_rate, web_commodity_page_view_cost,
+            own_page_navigation_count, own_page_navi_cost,
+            platform_page_navigation_count, platform_page_navigation_cost,
+            platform_shop_navigation_count, platform_shop_navigation_cost,
+            active_page_views, active_page_viewers,
+            active_page_interaction_amount, active_page_interaction_users,
+            guide_to_follow_page_views, guide_to_follow_page_viewers,
+            guide_to_follow_page_interaction_amount, guide_to_follow_page_interaction_users,
+            platform_key_page_view_user_count,
+            page_consult_count, consult_uv_count, page_consult_rate, page_consult_cost,
+            consult_leave_info_users, consult_leave_info_cost,
+            potential_consult_count, effective_consult_count, tool_consult_count,
+            page_reservation_count, page_reservation_by_display_count, page_reservation_by_click_count,
+            reservation_uv, reservation_amount, page_reservation_cost, page_reservation_cost_with_people,
+            page_reservation_rate, page_reservation_roi,
+            biz_reservation_uv, biz_reservation_follow_rate,
+            external_form_reservation_count, potential_reserve_count,
+            reservation_check_uv, reservation_check_uv_cost, reservation_check_uv_rate,
+            effective_reserve_count, valid_leads_uv, try_out_intention_uv, ineffective_leads_uv,
+            coupon_get_pv, coupon_get_cost, coupon_get_rate,
+            platform_coupon_click_count, purchase_amount_with_coupon,
+            coupon_purchase_rate, purchase_amount_with_coupon_cost, coupon_usage_number,
+            page_phone_call_direct_count, page_phone_call_direct_rate, page_phone_call_direct_cost,
+            potential_phone_count, potential_customer_phone_uv,
+            effective_phone_count, valid_phone_uv,
+            income_val_1, income_roi_1, income_val_3, income_roi_3,
+            income_val_7, income_roi_7, income_val_14, income_roi_14,
+            income_val_24h, income_roi_1_24h
+        ) VALUES (
+            #{report.groupId}, #{report.groupName}, #{report.accountId}, #{report.dynamicCreativeId}, #{report.date},
+            #{report.viewCount}, #{report.viewUserCount}, #{report.avgViewPerUser},
+            #{report.validClickCount}, #{report.clickUserCount}, #{report.cpc}, #{report.ctr},
+            #{report.valuableClickCount}, #{report.valuableClickCost}, #{report.valuableClickRate},
+            #{report.cost}, #{report.acquisitionCost}, #{report.thousandDisplayPrice},
+            #{report.conversionsCount}, #{report.conversionsRate}, #{report.conversionsCost},
+            #{report.deepConversionsCount}, #{report.deepConversionsRate}, #{report.deepConversionsCost},
+            #{report.conversionsByDisplayCount}, #{report.conversionsByDisplayRate}, #{report.conversionsByDisplayCost},
+            #{report.conversionsByClickCount}, #{report.conversionsByClickRate}, #{report.conversionsByClickCost},
+            #{report.previewConversionsCount}, #{report.previewDeepConversionsCount},
+            #{report.videoOuterPlayCount}, #{report.videoOuterPlayUserCount}, #{report.avgUserPlayCount},
+            #{report.videoOuterPlayTimeCount}, #{report.videoOuterPlayTimeAvgRate},
+            #{report.videoOuterPlayRate}, #{report.videoOuterPlayCost},
+            #{report.videoOuterPlay10Count}, #{report.videoOuterPlay25Count}, #{report.videoOuterPlay50Count},
+            #{report.videoOuterPlay75Count}, #{report.videoOuterPlay90Count}, #{report.videoOuterPlay95Count},
+            #{report.videoOuterPlay100Count}, #{report.videoOuterPlay3sCount}, #{report.videoOuterPlay3sRate},
+            #{report.videoOuterPlay5sCount}, #{report.videoOuterPlay7sCount},
+            #{report.readCount}, #{report.readCost}, #{report.commentCount}, #{report.commentCost},
+            #{report.praiseCount}, #{report.praiseCost}, #{report.forwardCount}, #{report.forwardCost}, #{report.noInterestCount},
+            #{report.liveStreamCrtClickCnt}, #{report.clickImageCount}, #{report.clickHeadCount},
+            #{report.clickDetailCount}, #{report.clickPoiCount}, #{report.zoneHeaderClickCount},
+            #{report.basicInfoClientCount}, #{report.accountInfoClickCount},
+            #{report.clkAccountLivingStatusPv}, #{report.clkAccountinfoWeappPv},
+            #{report.clkAccountinfoFinderPv}, #{report.clkAccountinfoBizPv},
+            #{report.clkAccountInfoProducttabPv}, #{report.clkAccountInfoProductdetailPv},
+            #{report.activityInfoClickCount},
+            #{report.overallLeadsPurchaseCount}, #{report.effectiveLeadsCount}, #{report.effectiveCost},
+            #{report.effectLeadsPurchaseCount}, #{report.effectLeadsPurchaseCost},
+            #{report.platformPageViewCount}, #{report.platformPageViewRate},
+            #{report.lanButtonClickCount}, #{report.lanJumpButtonClickers}, #{report.lanButtonClickCost},
+            #{report.lanJumpButtonCtr}, #{report.lanJumpButtonClickCost},
+            #{report.keyPageViewCount}, #{report.keyPageViewByDisplayCount}, #{report.keyPageViewByClickCount},
+            #{report.keyPageUv}, #{report.keyPageViewCost}, #{report.keyPageViewRate},
+            #{report.landingCommodityDetailExpPv},
+            #{report.appCommodityPageViewByDisplayCount}, #{report.appCommodityPageViewByClickCount},
+            #{report.viewCommodityPageUv}, #{report.webCommodityPageViewRate}, #{report.webCommodityPageViewCost},
+            #{report.ownPageNavigationCount}, #{report.ownPageNaviCost},
+            #{report.platformPageNavigationCount}, #{report.platformPageNavigationCost},
+            #{report.platformShopNavigationCount}, #{report.platformShopNavigationCost},
+            #{report.activePageViews}, #{report.activePageViewers},
+            #{report.activePageInteractionAmount}, #{report.activePageInteractionUsers},
+            #{report.guideToFollowPageViews}, #{report.guideToFollowPageViewers},
+            #{report.guideToFollowPageInteractionAmount}, #{report.guideToFollowPageInteractionUsers},
+            #{report.platformKeyPageViewUserCount},
+            #{report.pageConsultCount}, #{report.consultUvCount}, #{report.pageConsultRate}, #{report.pageConsultCost},
+            #{report.consultLeaveInfoUsers}, #{report.consultLeaveInfoCost},
+            #{report.potentialConsultCount}, #{report.effectiveConsultCount}, #{report.toolConsultCount},
+            #{report.pageReservationCount}, #{report.pageReservationByDisplayCount}, #{report.pageReservationByClickCount},
+            #{report.reservationUv}, #{report.reservationAmount}, #{report.pageReservationCost}, #{report.pageReservationCostWithPeople},
+            #{report.pageReservationRate}, #{report.pageReservationRoi},
+            #{report.bizReservationUv}, #{report.bizReservationFollowRate},
+            #{report.externalFormReservationCount}, #{report.potentialReserveCount},
+            #{report.reservationCheckUv}, #{report.reservationCheckUvCost}, #{report.reservationCheckUvRate},
+            #{report.effectiveReserveCount}, #{report.validLeadsUv}, #{report.tryOutIntentionUv}, #{report.ineffectiveLeadsUv},
+            #{report.couponGetPv}, #{report.couponGetCost}, #{report.couponGetRate},
+            #{report.platformCouponClickCount}, #{report.purchaseAmountWithCoupon},
+            #{report.couponPurchaseRate}, #{report.purchaseAmountWithCouponCost}, #{report.couponUsageNumber},
+            #{report.pagePhoneCallDirectCount}, #{report.pagePhoneCallDirectRate}, #{report.pagePhoneCallDirectCost},
+            #{report.potentialPhoneCount}, #{report.potentialCustomerPhoneUv},
+            #{report.effectivePhoneCount}, #{report.validPhoneUv},
+            #{report.incomeVal1}, #{report.incomeRoi1}, #{report.incomeVal3}, #{report.incomeRoi3},
+            #{report.incomeVal7}, #{report.incomeRoi7}, #{report.incomeVal14}, #{report.incomeRoi14},
+            #{report.incomeVal24h}, #{report.incomeRoi1_24h}
+        ) ON DUPLICATE KEY UPDATE
+            group_name = VALUES(group_name),
+            view_count = VALUES(view_count), view_user_count = VALUES(view_user_count), avg_view_per_user = VALUES(avg_view_per_user),
+            valid_click_count = VALUES(valid_click_count), click_user_count = VALUES(click_user_count), cpc = VALUES(cpc), ctr = VALUES(ctr),
+            valuable_click_count = VALUES(valuable_click_count), valuable_click_cost = VALUES(valuable_click_cost), valuable_click_rate = VALUES(valuable_click_rate),
+            cost = VALUES(cost), acquisition_cost = VALUES(acquisition_cost), thousand_display_price = VALUES(thousand_display_price),
+            conversions_count = VALUES(conversions_count), conversions_rate = VALUES(conversions_rate), conversions_cost = VALUES(conversions_cost),
+            deep_conversions_count = VALUES(deep_conversions_count), deep_conversions_rate = VALUES(deep_conversions_rate), deep_conversions_cost = VALUES(deep_conversions_cost),
+            conversions_by_display_count = VALUES(conversions_by_display_count), conversions_by_display_rate = VALUES(conversions_by_display_rate), conversions_by_display_cost = VALUES(conversions_by_display_cost),
+            conversions_by_click_count = VALUES(conversions_by_click_count), conversions_by_click_rate = VALUES(conversions_by_click_rate), conversions_by_click_cost = VALUES(conversions_by_click_cost),
+            preview_conversions_count = VALUES(preview_conversions_count), preview_deep_conversions_count = VALUES(preview_deep_conversions_count),
+            video_outer_play_count = VALUES(video_outer_play_count), video_outer_play_user_count = VALUES(video_outer_play_user_count), avg_user_play_count = VALUES(avg_user_play_count),
+            video_outer_play_time_count = VALUES(video_outer_play_time_count), video_outer_play_time_avg_rate = VALUES(video_outer_play_time_avg_rate),
+            video_outer_play_rate = VALUES(video_outer_play_rate), video_outer_play_cost = VALUES(video_outer_play_cost),
+            video_outer_play10_count = VALUES(video_outer_play10_count), video_outer_play25_count = VALUES(video_outer_play25_count), video_outer_play50_count = VALUES(video_outer_play50_count),
+            video_outer_play75_count = VALUES(video_outer_play75_count), video_outer_play90_count = VALUES(video_outer_play90_count), video_outer_play95_count = VALUES(video_outer_play95_count),
+            video_outer_play100_count = VALUES(video_outer_play100_count), video_outer_play3s_count = VALUES(video_outer_play3s_count), video_outer_play3s_rate = VALUES(video_outer_play3s_rate),
+            video_outer_play5s_count = VALUES(video_outer_play5s_count), video_outer_play7s_count = VALUES(video_outer_play7s_count),
+            read_count = VALUES(read_count), read_cost = VALUES(read_cost), comment_count = VALUES(comment_count), comment_cost = VALUES(comment_cost),
+            praise_count = VALUES(praise_count), praise_cost = VALUES(praise_cost), forward_count = VALUES(forward_count), forward_cost = VALUES(forward_cost), no_interest_count = VALUES(no_interest_count),
+            live_stream_crt_click_cnt = VALUES(live_stream_crt_click_cnt), click_image_count = VALUES(click_image_count), click_head_count = VALUES(click_head_count),
+            click_detail_count = VALUES(click_detail_count), click_poi_count = VALUES(click_poi_count), zone_header_click_count = VALUES(zone_header_click_count),
+            basic_info_client_count = VALUES(basic_info_client_count), account_info_click_count = VALUES(account_info_click_count),
+            clk_account_living_status_pv = VALUES(clk_account_living_status_pv), clk_accountinfo_weapp_pv = VALUES(clk_accountinfo_weapp_pv),
+            clk_accountinfo_finder_pv = VALUES(clk_accountinfo_finder_pv), clk_accountinfo_biz_pv = VALUES(clk_accountinfo_biz_pv),
+            clk_account_info_producttab_pv = VALUES(clk_account_info_producttab_pv), clk_account_info_productdetail_pv = VALUES(clk_account_info_productdetail_pv),
+            activity_info_click_count = VALUES(activity_info_click_count),
+            overall_leads_purchase_count = VALUES(overall_leads_purchase_count), effective_leads_count = VALUES(effective_leads_count), effective_cost = VALUES(effective_cost),
+            effect_leads_purchase_count = VALUES(effect_leads_purchase_count), effect_leads_purchase_cost = VALUES(effect_leads_purchase_cost),
+            platform_page_view_count = VALUES(platform_page_view_count), platform_page_view_rate = VALUES(platform_page_view_rate),
+            lan_button_click_count = VALUES(lan_button_click_count), lan_jump_button_clickers = VALUES(lan_jump_button_clickers), lan_button_click_cost = VALUES(lan_button_click_cost),
+            lan_jump_button_ctr = VALUES(lan_jump_button_ctr), lan_jump_button_click_cost = VALUES(lan_jump_button_click_cost),
+            key_page_view_count = VALUES(key_page_view_count), key_page_view_by_display_count = VALUES(key_page_view_by_display_count), key_page_view_by_click_count = VALUES(key_page_view_by_click_count),
+            key_page_uv = VALUES(key_page_uv), key_page_view_cost = VALUES(key_page_view_cost), key_page_view_rate = VALUES(key_page_view_rate),
+            landing_commodity_detail_exp_pv = VALUES(landing_commodity_detail_exp_pv),
+            app_commodity_page_view_by_display_count = VALUES(app_commodity_page_view_by_display_count), app_commodity_page_view_by_click_count = VALUES(app_commodity_page_view_by_click_count),
+            view_commodity_page_uv = VALUES(view_commodity_page_uv), web_commodity_page_view_rate = VALUES(web_commodity_page_view_rate), web_commodity_page_view_cost = VALUES(web_commodity_page_view_cost),
+            own_page_navigation_count = VALUES(own_page_navigation_count), own_page_navi_cost = VALUES(own_page_navi_cost),
+            platform_page_navigation_count = VALUES(platform_page_navigation_count), platform_page_navigation_cost = VALUES(platform_page_navigation_cost),
+            platform_shop_navigation_count = VALUES(platform_shop_navigation_count), platform_shop_navigation_cost = VALUES(platform_shop_navigation_cost),
+            active_page_views = VALUES(active_page_views), active_page_viewers = VALUES(active_page_viewers),
+            active_page_interaction_amount = VALUES(active_page_interaction_amount), active_page_interaction_users = VALUES(active_page_interaction_users),
+            guide_to_follow_page_views = VALUES(guide_to_follow_page_views), guide_to_follow_page_viewers = VALUES(guide_to_follow_page_viewers),
+            guide_to_follow_page_interaction_amount = VALUES(guide_to_follow_page_interaction_amount), guide_to_follow_page_interaction_users = VALUES(guide_to_follow_page_interaction_users),
+            platform_key_page_view_user_count = VALUES(platform_key_page_view_user_count),
+            page_consult_count = VALUES(page_consult_count), consult_uv_count = VALUES(consult_uv_count), page_consult_rate = VALUES(page_consult_rate), page_consult_cost = VALUES(page_consult_cost),
+            consult_leave_info_users = VALUES(consult_leave_info_users), consult_leave_info_cost = VALUES(consult_leave_info_cost),
+            potential_consult_count = VALUES(potential_consult_count), effective_consult_count = VALUES(effective_consult_count), tool_consult_count = VALUES(tool_consult_count),
+            page_reservation_count = VALUES(page_reservation_count), page_reservation_by_display_count = VALUES(page_reservation_by_display_count), page_reservation_by_click_count = VALUES(page_reservation_by_click_count),
+            reservation_uv = VALUES(reservation_uv), reservation_amount = VALUES(reservation_amount), page_reservation_cost = VALUES(page_reservation_cost), page_reservation_cost_with_people = VALUES(page_reservation_cost_with_people),
+            page_reservation_rate = VALUES(page_reservation_rate), page_reservation_roi = VALUES(page_reservation_roi),
+            biz_reservation_uv = VALUES(biz_reservation_uv), biz_reservation_follow_rate = VALUES(biz_reservation_follow_rate),
+            external_form_reservation_count = VALUES(external_form_reservation_count), potential_reserve_count = VALUES(potential_reserve_count),
+            reservation_check_uv = VALUES(reservation_check_uv), reservation_check_uv_cost = VALUES(reservation_check_uv_cost), reservation_check_uv_rate = VALUES(reservation_check_uv_rate),
+            effective_reserve_count = VALUES(effective_reserve_count), valid_leads_uv = VALUES(valid_leads_uv), try_out_intention_uv = VALUES(try_out_intention_uv), ineffective_leads_uv = VALUES(ineffective_leads_uv),
+            coupon_get_pv = VALUES(coupon_get_pv), coupon_get_cost = VALUES(coupon_get_cost), coupon_get_rate = VALUES(coupon_get_rate),
+            platform_coupon_click_count = VALUES(platform_coupon_click_count), purchase_amount_with_coupon = VALUES(purchase_amount_with_coupon),
+            coupon_purchase_rate = VALUES(coupon_purchase_rate), purchase_amount_with_coupon_cost = VALUES(purchase_amount_with_coupon_cost), coupon_usage_number = VALUES(coupon_usage_number),
+            page_phone_call_direct_count = VALUES(page_phone_call_direct_count), page_phone_call_direct_rate = VALUES(page_phone_call_direct_rate), page_phone_call_direct_cost = VALUES(page_phone_call_direct_cost),
+            potential_phone_count = VALUES(potential_phone_count), potential_customer_phone_uv = VALUES(potential_customer_phone_uv),
+            effective_phone_count = VALUES(effective_phone_count), valid_phone_uv = VALUES(valid_phone_uv),
+            income_val_1 = VALUES(income_val_1), income_roi_1 = VALUES(income_roi_1), income_val_3 = VALUES(income_val_3), income_roi_3 = VALUES(income_roi_3),
+            income_val_7 = VALUES(income_val_7), income_roi_7 = VALUES(income_roi_7), income_val_14 = VALUES(income_val_14), income_roi_14 = VALUES(income_roi_14),
+            income_val_24h = VALUES(income_val_24h), income_roi_1_24h = VALUES(income_roi_1_24h)
+    </insert>
+
+</mapper>

+ 201 - 0
src/main/resources/mapper/ReqDailyCreativeReportMapper.xml

@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.moka.gdtauto.mapper.ReqDailyCreativeReportMapper">
+
+    <!-- 插入或更新(REQUEST_TIME 口径)唯一键: group_id + account_id + dynamic_creative_id + date -->
+    <insert id="upsert" parameterType="com.moka.gdtauto.entity.ReqDailyCreativeReport">
+        INSERT INTO req_daily_creative_report (
+            group_id, group_name, account_id, dynamic_creative_id, date,
+            view_count, view_user_count, avg_view_per_user,
+            valid_click_count, click_user_count, cpc, ctr,
+            valuable_click_count, valuable_click_cost, valuable_click_rate,
+            cost, acquisition_cost, thousand_display_price,
+            conversions_count, conversions_rate, conversions_cost,
+            deep_conversions_count, deep_conversions_rate, deep_conversions_cost,
+            conversions_by_display_count, conversions_by_display_rate, conversions_by_display_cost,
+            conversions_by_click_count, conversions_by_click_rate, conversions_by_click_cost,
+            preview_conversions_count, preview_deep_conversions_count,
+            video_outer_play_count, video_outer_play_user_count, avg_user_play_count,
+            video_outer_play_time_count, video_outer_play_time_avg_rate,
+            video_outer_play_rate, video_outer_play_cost,
+            video_outer_play10_count, video_outer_play25_count, video_outer_play50_count,
+            video_outer_play75_count, video_outer_play90_count, video_outer_play95_count,
+            video_outer_play100_count, video_outer_play3s_count, video_outer_play3s_rate,
+            video_outer_play5s_count, video_outer_play7s_count,
+            read_count, read_cost, comment_count, comment_cost,
+            praise_count, praise_cost, forward_count, forward_cost, no_interest_count,
+            live_stream_crt_click_cnt, click_image_count, click_head_count,
+            click_detail_count, click_poi_count, zone_header_click_count,
+            basic_info_client_count, account_info_click_count,
+            clk_account_living_status_pv, clk_accountinfo_weapp_pv,
+            clk_accountinfo_finder_pv, clk_accountinfo_biz_pv,
+            clk_account_info_producttab_pv, clk_account_info_productdetail_pv,
+            activity_info_click_count,
+            overall_leads_purchase_count, effective_leads_count, effective_cost,
+            effect_leads_purchase_count, effect_leads_purchase_cost,
+            platform_page_view_count, platform_page_view_rate,
+            lan_button_click_count, lan_jump_button_clickers, lan_button_click_cost,
+            lan_jump_button_ctr, lan_jump_button_click_cost,
+            key_page_view_count, key_page_view_by_display_count, key_page_view_by_click_count,
+            key_page_uv, key_page_view_cost, key_page_view_rate,
+            landing_commodity_detail_exp_pv,
+            app_commodity_page_view_by_display_count, app_commodity_page_view_by_click_count,
+            view_commodity_page_uv, web_commodity_page_view_rate, web_commodity_page_view_cost,
+            own_page_navigation_count, own_page_navi_cost,
+            platform_page_navigation_count, platform_page_navigation_cost,
+            platform_shop_navigation_count, platform_shop_navigation_cost,
+            active_page_views, active_page_viewers,
+            active_page_interaction_amount, active_page_interaction_users,
+            guide_to_follow_page_views, guide_to_follow_page_viewers,
+            guide_to_follow_page_interaction_amount, guide_to_follow_page_interaction_users,
+            platform_key_page_view_user_count,
+            page_consult_count, consult_uv_count, page_consult_rate, page_consult_cost,
+            consult_leave_info_users, consult_leave_info_cost,
+            potential_consult_count, effective_consult_count, tool_consult_count,
+            page_reservation_count, page_reservation_by_display_count, page_reservation_by_click_count,
+            reservation_uv, reservation_amount, page_reservation_cost, page_reservation_cost_with_people,
+            page_reservation_rate, page_reservation_roi,
+            biz_reservation_uv, biz_reservation_follow_rate,
+            external_form_reservation_count, potential_reserve_count,
+            reservation_check_uv, reservation_check_uv_cost, reservation_check_uv_rate,
+            effective_reserve_count, valid_leads_uv, try_out_intention_uv, ineffective_leads_uv,
+            coupon_get_pv, coupon_get_cost, coupon_get_rate,
+            platform_coupon_click_count, purchase_amount_with_coupon,
+            coupon_purchase_rate, purchase_amount_with_coupon_cost, coupon_usage_number,
+            page_phone_call_direct_count, page_phone_call_direct_rate, page_phone_call_direct_cost,
+            potential_phone_count, potential_customer_phone_uv,
+            effective_phone_count, valid_phone_uv,
+            income_val_1, income_roi_1, income_val_3, income_roi_3,
+            income_val_7, income_roi_7, income_val_14, income_roi_14,
+            income_val_24h, income_roi_1_24h
+        ) VALUES (
+            #{report.groupId}, #{report.groupName}, #{report.accountId}, #{report.dynamicCreativeId}, #{report.date},
+            #{report.viewCount}, #{report.viewUserCount}, #{report.avgViewPerUser},
+            #{report.validClickCount}, #{report.clickUserCount}, #{report.cpc}, #{report.ctr},
+            #{report.valuableClickCount}, #{report.valuableClickCost}, #{report.valuableClickRate},
+            #{report.cost}, #{report.acquisitionCost}, #{report.thousandDisplayPrice},
+            #{report.conversionsCount}, #{report.conversionsRate}, #{report.conversionsCost},
+            #{report.deepConversionsCount}, #{report.deepConversionsRate}, #{report.deepConversionsCost},
+            #{report.conversionsByDisplayCount}, #{report.conversionsByDisplayRate}, #{report.conversionsByDisplayCost},
+            #{report.conversionsByClickCount}, #{report.conversionsByClickRate}, #{report.conversionsByClickCost},
+            #{report.previewConversionsCount}, #{report.previewDeepConversionsCount},
+            #{report.videoOuterPlayCount}, #{report.videoOuterPlayUserCount}, #{report.avgUserPlayCount},
+            #{report.videoOuterPlayTimeCount}, #{report.videoOuterPlayTimeAvgRate},
+            #{report.videoOuterPlayRate}, #{report.videoOuterPlayCost},
+            #{report.videoOuterPlay10Count}, #{report.videoOuterPlay25Count}, #{report.videoOuterPlay50Count},
+            #{report.videoOuterPlay75Count}, #{report.videoOuterPlay90Count}, #{report.videoOuterPlay95Count},
+            #{report.videoOuterPlay100Count}, #{report.videoOuterPlay3sCount}, #{report.videoOuterPlay3sRate},
+            #{report.videoOuterPlay5sCount}, #{report.videoOuterPlay7sCount},
+            #{report.readCount}, #{report.readCost}, #{report.commentCount}, #{report.commentCost},
+            #{report.praiseCount}, #{report.praiseCost}, #{report.forwardCount}, #{report.forwardCost}, #{report.noInterestCount},
+            #{report.liveStreamCrtClickCnt}, #{report.clickImageCount}, #{report.clickHeadCount},
+            #{report.clickDetailCount}, #{report.clickPoiCount}, #{report.zoneHeaderClickCount},
+            #{report.basicInfoClientCount}, #{report.accountInfoClickCount},
+            #{report.clkAccountLivingStatusPv}, #{report.clkAccountinfoWeappPv},
+            #{report.clkAccountinfoFinderPv}, #{report.clkAccountinfoBizPv},
+            #{report.clkAccountInfoProducttabPv}, #{report.clkAccountInfoProductdetailPv},
+            #{report.activityInfoClickCount},
+            #{report.overallLeadsPurchaseCount}, #{report.effectiveLeadsCount}, #{report.effectiveCost},
+            #{report.effectLeadsPurchaseCount}, #{report.effectLeadsPurchaseCost},
+            #{report.platformPageViewCount}, #{report.platformPageViewRate},
+            #{report.lanButtonClickCount}, #{report.lanJumpButtonClickers}, #{report.lanButtonClickCost},
+            #{report.lanJumpButtonCtr}, #{report.lanJumpButtonClickCost},
+            #{report.keyPageViewCount}, #{report.keyPageViewByDisplayCount}, #{report.keyPageViewByClickCount},
+            #{report.keyPageUv}, #{report.keyPageViewCost}, #{report.keyPageViewRate},
+            #{report.landingCommodityDetailExpPv},
+            #{report.appCommodityPageViewByDisplayCount}, #{report.appCommodityPageViewByClickCount},
+            #{report.viewCommodityPageUv}, #{report.webCommodityPageViewRate}, #{report.webCommodityPageViewCost},
+            #{report.ownPageNavigationCount}, #{report.ownPageNaviCost},
+            #{report.platformPageNavigationCount}, #{report.platformPageNavigationCost},
+            #{report.platformShopNavigationCount}, #{report.platformShopNavigationCost},
+            #{report.activePageViews}, #{report.activePageViewers},
+            #{report.activePageInteractionAmount}, #{report.activePageInteractionUsers},
+            #{report.guideToFollowPageViews}, #{report.guideToFollowPageViewers},
+            #{report.guideToFollowPageInteractionAmount}, #{report.guideToFollowPageInteractionUsers},
+            #{report.platformKeyPageViewUserCount},
+            #{report.pageConsultCount}, #{report.consultUvCount}, #{report.pageConsultRate}, #{report.pageConsultCost},
+            #{report.consultLeaveInfoUsers}, #{report.consultLeaveInfoCost},
+            #{report.potentialConsultCount}, #{report.effectiveConsultCount}, #{report.toolConsultCount},
+            #{report.pageReservationCount}, #{report.pageReservationByDisplayCount}, #{report.pageReservationByClickCount},
+            #{report.reservationUv}, #{report.reservationAmount}, #{report.pageReservationCost}, #{report.pageReservationCostWithPeople},
+            #{report.pageReservationRate}, #{report.pageReservationRoi},
+            #{report.bizReservationUv}, #{report.bizReservationFollowRate},
+            #{report.externalFormReservationCount}, #{report.potentialReserveCount},
+            #{report.reservationCheckUv}, #{report.reservationCheckUvCost}, #{report.reservationCheckUvRate},
+            #{report.effectiveReserveCount}, #{report.validLeadsUv}, #{report.tryOutIntentionUv}, #{report.ineffectiveLeadsUv},
+            #{report.couponGetPv}, #{report.couponGetCost}, #{report.couponGetRate},
+            #{report.platformCouponClickCount}, #{report.purchaseAmountWithCoupon},
+            #{report.couponPurchaseRate}, #{report.purchaseAmountWithCouponCost}, #{report.couponUsageNumber},
+            #{report.pagePhoneCallDirectCount}, #{report.pagePhoneCallDirectRate}, #{report.pagePhoneCallDirectCost},
+            #{report.potentialPhoneCount}, #{report.potentialCustomerPhoneUv},
+            #{report.effectivePhoneCount}, #{report.validPhoneUv},
+            #{report.incomeVal1}, #{report.incomeRoi1}, #{report.incomeVal3}, #{report.incomeRoi3},
+            #{report.incomeVal7}, #{report.incomeRoi7}, #{report.incomeVal14}, #{report.incomeRoi14},
+            #{report.incomeVal24h}, #{report.incomeRoi1_24h}
+        ) ON DUPLICATE KEY UPDATE
+            group_name = VALUES(group_name),
+            view_count = VALUES(view_count), view_user_count = VALUES(view_user_count), avg_view_per_user = VALUES(avg_view_per_user),
+            valid_click_count = VALUES(valid_click_count), click_user_count = VALUES(click_user_count), cpc = VALUES(cpc), ctr = VALUES(ctr),
+            valuable_click_count = VALUES(valuable_click_count), valuable_click_cost = VALUES(valuable_click_cost), valuable_click_rate = VALUES(valuable_click_rate),
+            cost = VALUES(cost), acquisition_cost = VALUES(acquisition_cost), thousand_display_price = VALUES(thousand_display_price),
+            conversions_count = VALUES(conversions_count), conversions_rate = VALUES(conversions_rate), conversions_cost = VALUES(conversions_cost),
+            deep_conversions_count = VALUES(deep_conversions_count), deep_conversions_rate = VALUES(deep_conversions_rate), deep_conversions_cost = VALUES(deep_conversions_cost),
+            conversions_by_display_count = VALUES(conversions_by_display_count), conversions_by_display_rate = VALUES(conversions_by_display_rate), conversions_by_display_cost = VALUES(conversions_by_display_cost),
+            conversions_by_click_count = VALUES(conversions_by_click_count), conversions_by_click_rate = VALUES(conversions_by_click_rate), conversions_by_click_cost = VALUES(conversions_by_click_cost),
+            preview_conversions_count = VALUES(preview_conversions_count), preview_deep_conversions_count = VALUES(preview_deep_conversions_count),
+            video_outer_play_count = VALUES(video_outer_play_count), video_outer_play_user_count = VALUES(video_outer_play_user_count), avg_user_play_count = VALUES(avg_user_play_count),
+            video_outer_play_time_count = VALUES(video_outer_play_time_count), video_outer_play_time_avg_rate = VALUES(video_outer_play_time_avg_rate),
+            video_outer_play_rate = VALUES(video_outer_play_rate), video_outer_play_cost = VALUES(video_outer_play_cost),
+            video_outer_play10_count = VALUES(video_outer_play10_count), video_outer_play25_count = VALUES(video_outer_play25_count), video_outer_play50_count = VALUES(video_outer_play50_count),
+            video_outer_play75_count = VALUES(video_outer_play75_count), video_outer_play90_count = VALUES(video_outer_play90_count), video_outer_play95_count = VALUES(video_outer_play95_count),
+            video_outer_play100_count = VALUES(video_outer_play100_count), video_outer_play3s_count = VALUES(video_outer_play3s_count), video_outer_play3s_rate = VALUES(video_outer_play3s_rate),
+            video_outer_play5s_count = VALUES(video_outer_play5s_count), video_outer_play7s_count = VALUES(video_outer_play7s_count),
+            read_count = VALUES(read_count), read_cost = VALUES(read_cost), comment_count = VALUES(comment_count), comment_cost = VALUES(comment_cost),
+            praise_count = VALUES(praise_count), praise_cost = VALUES(praise_cost), forward_count = VALUES(forward_count), forward_cost = VALUES(forward_cost), no_interest_count = VALUES(no_interest_count),
+            live_stream_crt_click_cnt = VALUES(live_stream_crt_click_cnt), click_image_count = VALUES(click_image_count), click_head_count = VALUES(click_head_count),
+            click_detail_count = VALUES(click_detail_count), click_poi_count = VALUES(click_poi_count), zone_header_click_count = VALUES(zone_header_click_count),
+            basic_info_client_count = VALUES(basic_info_client_count), account_info_click_count = VALUES(account_info_click_count),
+            clk_account_living_status_pv = VALUES(clk_account_living_status_pv), clk_accountinfo_weapp_pv = VALUES(clk_accountinfo_weapp_pv),
+            clk_accountinfo_finder_pv = VALUES(clk_accountinfo_finder_pv), clk_accountinfo_biz_pv = VALUES(clk_accountinfo_biz_pv),
+            clk_account_info_producttab_pv = VALUES(clk_account_info_producttab_pv), clk_account_info_productdetail_pv = VALUES(clk_account_info_productdetail_pv),
+            activity_info_click_count = VALUES(activity_info_click_count),
+            overall_leads_purchase_count = VALUES(overall_leads_purchase_count), effective_leads_count = VALUES(effective_leads_count), effective_cost = VALUES(effective_cost),
+            effect_leads_purchase_count = VALUES(effect_leads_purchase_count), effect_leads_purchase_cost = VALUES(effect_leads_purchase_cost),
+            platform_page_view_count = VALUES(platform_page_view_count), platform_page_view_rate = VALUES(platform_page_view_rate),
+            lan_button_click_count = VALUES(lan_button_click_count), lan_jump_button_clickers = VALUES(lan_jump_button_clickers), lan_button_click_cost = VALUES(lan_button_click_cost),
+            lan_jump_button_ctr = VALUES(lan_jump_button_ctr), lan_jump_button_click_cost = VALUES(lan_jump_button_click_cost),
+            key_page_view_count = VALUES(key_page_view_count), key_page_view_by_display_count = VALUES(key_page_view_by_display_count), key_page_view_by_click_count = VALUES(key_page_view_by_click_count),
+            key_page_uv = VALUES(key_page_uv), key_page_view_cost = VALUES(key_page_view_cost), key_page_view_rate = VALUES(key_page_view_rate),
+            landing_commodity_detail_exp_pv = VALUES(landing_commodity_detail_exp_pv),
+            app_commodity_page_view_by_display_count = VALUES(app_commodity_page_view_by_display_count), app_commodity_page_view_by_click_count = VALUES(app_commodity_page_view_by_click_count),
+            view_commodity_page_uv = VALUES(view_commodity_page_uv), web_commodity_page_view_rate = VALUES(web_commodity_page_view_rate), web_commodity_page_view_cost = VALUES(web_commodity_page_view_cost),
+            own_page_navigation_count = VALUES(own_page_navigation_count), own_page_navi_cost = VALUES(own_page_navi_cost),
+            platform_page_navigation_count = VALUES(platform_page_navigation_count), platform_page_navigation_cost = VALUES(platform_page_navigation_cost),
+            platform_shop_navigation_count = VALUES(platform_shop_navigation_count), platform_shop_navigation_cost = VALUES(platform_shop_navigation_cost),
+            active_page_views = VALUES(active_page_views), active_page_viewers = VALUES(active_page_viewers),
+            active_page_interaction_amount = VALUES(active_page_interaction_amount), active_page_interaction_users = VALUES(active_page_interaction_users),
+            guide_to_follow_page_views = VALUES(guide_to_follow_page_views), guide_to_follow_page_viewers = VALUES(guide_to_follow_page_viewers),
+            guide_to_follow_page_interaction_amount = VALUES(guide_to_follow_page_interaction_amount), guide_to_follow_page_interaction_users = VALUES(guide_to_follow_page_interaction_users),
+            platform_key_page_view_user_count = VALUES(platform_key_page_view_user_count),
+            page_consult_count = VALUES(page_consult_count), consult_uv_count = VALUES(consult_uv_count), page_consult_rate = VALUES(page_consult_rate), page_consult_cost = VALUES(page_consult_cost),
+            consult_leave_info_users = VALUES(consult_leave_info_users), consult_leave_info_cost = VALUES(consult_leave_info_cost),
+            potential_consult_count = VALUES(potential_consult_count), effective_consult_count = VALUES(effective_consult_count), tool_consult_count = VALUES(tool_consult_count),
+            page_reservation_count = VALUES(page_reservation_count), page_reservation_by_display_count = VALUES(page_reservation_by_display_count), page_reservation_by_click_count = VALUES(page_reservation_by_click_count),
+            reservation_uv = VALUES(reservation_uv), reservation_amount = VALUES(reservation_amount), page_reservation_cost = VALUES(page_reservation_cost), page_reservation_cost_with_people = VALUES(page_reservation_cost_with_people),
+            page_reservation_rate = VALUES(page_reservation_rate), page_reservation_roi = VALUES(page_reservation_roi),
+            biz_reservation_uv = VALUES(biz_reservation_uv), biz_reservation_follow_rate = VALUES(biz_reservation_follow_rate),
+            external_form_reservation_count = VALUES(external_form_reservation_count), potential_reserve_count = VALUES(potential_reserve_count),
+            reservation_check_uv = VALUES(reservation_check_uv), reservation_check_uv_cost = VALUES(reservation_check_uv_cost), reservation_check_uv_rate = VALUES(reservation_check_uv_rate),
+            effective_reserve_count = VALUES(effective_reserve_count), valid_leads_uv = VALUES(valid_leads_uv), try_out_intention_uv = VALUES(try_out_intention_uv), ineffective_leads_uv = VALUES(ineffective_leads_uv),
+            coupon_get_pv = VALUES(coupon_get_pv), coupon_get_cost = VALUES(coupon_get_cost), coupon_get_rate = VALUES(coupon_get_rate),
+            platform_coupon_click_count = VALUES(platform_coupon_click_count), purchase_amount_with_coupon = VALUES(purchase_amount_with_coupon),
+            coupon_purchase_rate = VALUES(coupon_purchase_rate), purchase_amount_with_coupon_cost = VALUES(purchase_amount_with_coupon_cost), coupon_usage_number = VALUES(coupon_usage_number),
+            page_phone_call_direct_count = VALUES(page_phone_call_direct_count), page_phone_call_direct_rate = VALUES(page_phone_call_direct_rate), page_phone_call_direct_cost = VALUES(page_phone_call_direct_cost),
+            potential_phone_count = VALUES(potential_phone_count), potential_customer_phone_uv = VALUES(potential_customer_phone_uv),
+            effective_phone_count = VALUES(effective_phone_count), valid_phone_uv = VALUES(valid_phone_uv),
+            income_val_1 = VALUES(income_val_1), income_roi_1 = VALUES(income_roi_1), income_val_3 = VALUES(income_val_3), income_roi_3 = VALUES(income_roi_3),
+            income_val_7 = VALUES(income_val_7), income_roi_7 = VALUES(income_roi_7), income_val_14 = VALUES(income_val_14), income_roi_14 = VALUES(income_roi_14),
+            income_val_24h = VALUES(income_val_24h), income_roi_1_24h = VALUES(income_roi_1_24h)
+    </insert>
+
+</mapper>

+ 398 - 0
src/main/resources/sql/create_daily_creative_report_tables.sql

@@ -0,0 +1,398 @@
+-- 动态创意日报表(请求时间口径)
+-- time_line = REQUEST_TIME
+CREATE TABLE IF NOT EXISTS `req_daily_creative_report` (
+    `id`                                        BIGINT(20)     NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+    `group_id`                                  BIGINT(20)     NOT NULL DEFAULT 0 COMMENT '账号组ID,关联account_group表',
+    `group_name`                                VARCHAR(100)   DEFAULT NULL COMMENT '账号组名称',
+    `account_id`                                BIGINT(20)     NOT NULL COMMENT '广告主账号ID',
+    `dynamic_creative_id`                       BIGINT(20)     NOT NULL COMMENT '动态创意ID',
+    `date`                                      DATE           NOT NULL COMMENT '日期',
+    -- 基础曝光点击
+    `view_count`                                BIGINT         DEFAULT NULL COMMENT '曝光次数',
+    `view_user_count`                           BIGINT         DEFAULT NULL COMMENT '曝光人数',
+    `avg_view_per_user`                         DECIMAL(12,4)  DEFAULT NULL COMMENT '人均曝光次数',
+    `valid_click_count`                         BIGINT         DEFAULT NULL COMMENT '点击次数',
+    `click_user_count`                          BIGINT         DEFAULT NULL COMMENT '点击人数',
+    `cpc`                                       BIGINT         DEFAULT NULL COMMENT '点击均价(分)',
+    `ctr`                                       DECIMAL(12,4)  DEFAULT NULL COMMENT '点击率',
+    `valuable_click_count`                      BIGINT         DEFAULT NULL COMMENT '可转化点击次数',
+    `valuable_click_cost`                       BIGINT         DEFAULT NULL COMMENT '可转化点击成本(分)',
+    `valuable_click_rate`                       DECIMAL(12,4)  DEFAULT NULL COMMENT '可转化点击率',
+    -- 花费
+    `cost`                                      BIGINT         DEFAULT NULL COMMENT '花费(分)',
+    `acquisition_cost`                          BIGINT         DEFAULT NULL COMMENT '一键起量消耗(分)',
+    `thousand_display_price`                    BIGINT         DEFAULT NULL COMMENT '千次展现均价(分)',
+    -- 转化
+    `conversions_count`                         BIGINT         DEFAULT NULL COMMENT '目标转化量',
+    `conversions_rate`                          DECIMAL(12,4)  DEFAULT NULL COMMENT '目标转化率',
+    `conversions_cost`                          BIGINT         DEFAULT NULL COMMENT '目标转化成本(分)',
+    `deep_conversions_count`                    BIGINT         DEFAULT NULL COMMENT '深度目标转化量',
+    `deep_conversions_rate`                     DECIMAL(12,4)  DEFAULT NULL COMMENT '深度目标转化率',
+    `deep_conversions_cost`                     BIGINT         DEFAULT NULL COMMENT '深度转化成本(分)',
+    `conversions_by_display_count`              BIGINT         DEFAULT NULL COMMENT '目标转化量(曝光归因)',
+    `conversions_by_display_rate`               DECIMAL(12,4)  DEFAULT NULL COMMENT '目标转化率(曝光归因)',
+    `conversions_by_display_cost`               BIGINT         DEFAULT NULL COMMENT '目标转化成本(曝光归因,分)',
+    `conversions_by_click_count`                BIGINT         DEFAULT NULL COMMENT '目标转化量(点击归因)',
+    `conversions_by_click_rate`                 DECIMAL(12,4)  DEFAULT NULL COMMENT '目标转化率(点击归因)',
+    `conversions_by_click_cost`                 BIGINT         DEFAULT NULL COMMENT '目标转化成本(点击归因,分)',
+    `preview_conversions_count`                 BIGINT         DEFAULT NULL COMMENT '目标转化量(在线预览)',
+    `preview_deep_conversions_count`            BIGINT         DEFAULT NULL COMMENT '深度目标转化量(在线预览)',
+    -- 视频播放
+    `video_outer_play_count`                    BIGINT         DEFAULT NULL COMMENT '视频有效播放次数',
+    `video_outer_play_user_count`               BIGINT         DEFAULT NULL COMMENT '视频有效播放人数',
+    `avg_user_play_count`                       DECIMAL(12,4)  DEFAULT NULL COMMENT '人均播放次数',
+    `video_outer_play_time_count`               DECIMAL(12,4)  DEFAULT NULL COMMENT '平均有效播放时长(秒)',
+    `video_outer_play_time_avg_rate`            DECIMAL(12,4)  DEFAULT NULL COMMENT '平均有效播放进度',
+    `video_outer_play_rate`                     DECIMAL(12,4)  DEFAULT NULL COMMENT '有效播放率',
+    `video_outer_play_cost`                     BIGINT         DEFAULT NULL COMMENT '有效播放成本(分)',
+    `video_outer_play10_count`                  BIGINT         DEFAULT NULL COMMENT '10%进度播放次数',
+    `video_outer_play25_count`                  BIGINT         DEFAULT NULL COMMENT '25%进度播放次数',
+    `video_outer_play50_count`                  BIGINT         DEFAULT NULL COMMENT '50%进度播放次数',
+    `video_outer_play75_count`                  BIGINT         DEFAULT NULL COMMENT '75%进度播放次数',
+    `video_outer_play90_count`                  BIGINT         DEFAULT NULL COMMENT '90%进度播放次数',
+    `video_outer_play95_count`                  BIGINT         DEFAULT NULL COMMENT '95%进度播放次数',
+    `video_outer_play100_count`                 BIGINT         DEFAULT NULL COMMENT '100%进度播放次数',
+    `video_outer_play3s_count`                  BIGINT         DEFAULT NULL COMMENT '3s播放完成次数',
+    `video_outer_play3s_rate`                   DECIMAL(12,4)  DEFAULT NULL COMMENT '3s播放完成率',
+    `video_outer_play5s_count`                  BIGINT         DEFAULT NULL COMMENT '5s播放完成次数',
+    `video_outer_play7s_count`                  BIGINT         DEFAULT NULL COMMENT '7s播放完成次数',
+    -- 互动
+    `read_count`                                BIGINT         DEFAULT NULL COMMENT '阅读次数',
+    `read_cost`                                 BIGINT         DEFAULT NULL COMMENT '阅读成本(分)',
+    `comment_count`                             BIGINT         DEFAULT NULL COMMENT '评论次数',
+    `comment_cost`                              BIGINT         DEFAULT NULL COMMENT '评论成本(分)',
+    `praise_count`                              BIGINT         DEFAULT NULL COMMENT '点赞次数',
+    `praise_cost`                               BIGINT         DEFAULT NULL COMMENT '点赞成本(分)',
+    `forward_count`                             BIGINT         DEFAULT NULL COMMENT '分享次数',
+    `forward_cost`                              BIGINT         DEFAULT NULL COMMENT '分享成本(分)',
+    `no_interest_count`                         BIGINT         DEFAULT NULL COMMENT '不感兴趣点击次数',
+    -- 素材点击
+    `live_stream_crt_click_cnt`                 BIGINT         DEFAULT NULL COMMENT '素材点击次数',
+    `click_image_count`                         BIGINT         DEFAULT NULL COMMENT '外层图片点击次数',
+    `click_head_count`                          BIGINT         DEFAULT NULL COMMENT '头像点击次数',
+    `click_detail_count`                        BIGINT         DEFAULT NULL COMMENT '文字链点击次数',
+    `click_poi_count`                           BIGINT         DEFAULT NULL COMMENT '本地门店点击次数',
+    `zone_header_click_count`                   BIGINT         DEFAULT NULL COMMENT '顶部运营位点击次数',
+    `basic_info_client_count`                   BIGINT         DEFAULT NULL COMMENT '官方信息区点击次数',
+    `account_info_click_count`                  BIGINT         DEFAULT NULL COMMENT '官方账号区点击次数',
+    `clk_account_living_status_pv`              BIGINT         DEFAULT NULL COMMENT '官方账号区直播中头像点击次数',
+    `clk_accountinfo_weapp_pv`                  BIGINT         DEFAULT NULL COMMENT '官方账号区小程序组件点击次数',
+    `clk_accountinfo_finder_pv`                 BIGINT         DEFAULT NULL COMMENT '官方账号区视频号组件点击次数',
+    `clk_accountinfo_biz_pv`                    BIGINT         DEFAULT NULL COMMENT '官方账号区公众号组件点击次数',
+    `clk_account_info_producttab_pv`            BIGINT         DEFAULT NULL COMMENT '官方账号区系列tab总点击次数',
+    `clk_account_info_productdetail_pv`         BIGINT         DEFAULT NULL COMMENT '官方账号区商品卡总点击次数',
+    `activity_info_click_count`                 BIGINT         DEFAULT NULL COMMENT '热门活动区点击次数',
+    -- 线索
+    `overall_leads_purchase_count`              BIGINT         DEFAULT NULL COMMENT '综合销售线索人数',
+    `effective_leads_count`                     BIGINT         DEFAULT NULL COMMENT '有效线索次数',
+    `effective_cost`                            BIGINT         DEFAULT NULL COMMENT '有效线索成本(分)',
+    `effect_leads_purchase_count`               BIGINT         DEFAULT NULL COMMENT '有效线索人数',
+    `effect_leads_purchase_cost`                BIGINT         DEFAULT NULL COMMENT '有效线索成本人数(分)',
+    -- 落地页
+    `platform_page_view_count`                  BIGINT         DEFAULT NULL COMMENT '落地页曝光次数',
+    `platform_page_view_rate`                   DECIMAL(12,4)  DEFAULT NULL COMMENT '落地页曝光率',
+    `lan_button_click_count`                    BIGINT         DEFAULT NULL COMMENT '落地页组件点击次数',
+    `lan_jump_button_clickers`                  BIGINT         DEFAULT NULL COMMENT '落地页组件点击人数',
+    `lan_button_click_cost`                     BIGINT         DEFAULT NULL COMMENT '落地页点击成本(分)',
+    `lan_jump_button_ctr`                       DECIMAL(12,4)  DEFAULT NULL COMMENT '落地页点击率(人数)',
+    `lan_jump_button_click_cost`                BIGINT         DEFAULT NULL COMMENT '落地页点击成本人数(分)',
+    -- 关键页面
+    `key_page_view_count`                       BIGINT         DEFAULT NULL COMMENT '关键页面访问次数',
+    `key_page_view_by_display_count`            BIGINT         DEFAULT NULL COMMENT '关键页面访问次数(曝光归因)',
+    `key_page_view_by_click_count`              BIGINT         DEFAULT NULL COMMENT '关键页面访问次数(点击归因)',
+    `key_page_uv`                               BIGINT         DEFAULT NULL COMMENT '关键页面访问人数',
+    `key_page_view_cost`                        BIGINT         DEFAULT NULL COMMENT '关键页面访问成本(分)',
+    `key_page_view_rate`                        DECIMAL(12,4)  DEFAULT NULL COMMENT '关键页面访问率',
+    -- 商品页
+    `landing_commodity_detail_exp_pv`           BIGINT         DEFAULT NULL COMMENT '商品页浏览次数',
+    `app_commodity_page_view_by_display_count`  BIGINT         DEFAULT NULL COMMENT '商品页浏览次数(曝光归因)',
+    `app_commodity_page_view_by_click_count`    BIGINT         DEFAULT NULL COMMENT '商品页浏览次数(点击归因)',
+    `view_commodity_page_uv`                    BIGINT         DEFAULT NULL COMMENT '商品页浏览人数',
+    `web_commodity_page_view_rate`              DECIMAL(12,4)  DEFAULT NULL COMMENT '商品页浏览率',
+    `web_commodity_page_view_cost`              BIGINT         DEFAULT NULL COMMENT '商品页浏览成本(分)',
+    -- 导航
+    `own_page_navigation_count`                 BIGINT         DEFAULT NULL COMMENT '自有页导航次数',
+    `own_page_navi_cost`                        BIGINT         DEFAULT NULL COMMENT '自有页导航成本(分)',
+    `platform_page_navigation_count`            BIGINT         DEFAULT NULL COMMENT '平台页导航次数',
+    `platform_page_navigation_cost`             BIGINT         DEFAULT NULL COMMENT '平台页导航成本(分)',
+    `platform_shop_navigation_count`            BIGINT         DEFAULT NULL COMMENT '平台页门店点击次数',
+    `platform_shop_navigation_cost`             BIGINT         DEFAULT NULL COMMENT '平台页门店页导航成本(分)',
+    -- 活动页/加粉
+    `active_page_views`                         BIGINT         DEFAULT NULL COMMENT '活动页面访问次数',
+    `active_page_viewers`                       BIGINT         DEFAULT NULL COMMENT '活动页面访问人数',
+    `active_page_interaction_amount`            BIGINT         DEFAULT NULL COMMENT '活动页面互动次数',
+    `active_page_interaction_users`             BIGINT         DEFAULT NULL COMMENT '活动页面互动人数',
+    `guide_to_follow_page_views`                BIGINT         DEFAULT NULL COMMENT '加粉引导页浏览次数',
+    `guide_to_follow_page_viewers`              BIGINT         DEFAULT NULL COMMENT '加粉引导页浏览人数',
+    `guide_to_follow_page_interaction_amount`   BIGINT         DEFAULT NULL COMMENT '加粉引导页互动次数',
+    `guide_to_follow_page_interaction_users`    BIGINT         DEFAULT NULL COMMENT '加粉引导页互动人数',
+    `platform_key_page_view_user_count`         BIGINT         DEFAULT NULL COMMENT '落地页曝光人数',
+    -- 在线咨询
+    `page_consult_count`                        BIGINT         DEFAULT NULL COMMENT '在线咨询次数',
+    `consult_uv_count`                          BIGINT         DEFAULT NULL COMMENT '在线咨询人数',
+    `page_consult_rate`                         DECIMAL(12,4)  DEFAULT NULL COMMENT '在线咨询率',
+    `page_consult_cost`                         BIGINT         DEFAULT NULL COMMENT '在线咨询成本(分)',
+    `consult_leave_info_users`                  BIGINT         DEFAULT NULL COMMENT '咨询留资人数',
+    `consult_leave_info_cost`                   BIGINT         DEFAULT NULL COMMENT '咨询留咨成本(分)',
+    `potential_consult_count`                   BIGINT         DEFAULT NULL COMMENT '潜在客户线索次数-咨询',
+    `effective_consult_count`                   BIGINT         DEFAULT NULL COMMENT '有效线索次数-咨询',
+    `tool_consult_count`                        BIGINT         DEFAULT NULL COMMENT '附加创意智能咨询次数',
+    -- 表单预约
+    `page_reservation_count`                    BIGINT         DEFAULT NULL COMMENT '表单预约次数',
+    `page_reservation_by_display_count`         BIGINT         DEFAULT NULL COMMENT '表单预约次数(曝光归因)',
+    `page_reservation_by_click_count`           BIGINT         DEFAULT NULL COMMENT '表单预约次数(点击归因)',
+    `reservation_uv`                            BIGINT         DEFAULT NULL COMMENT '表单预约人数',
+    `reservation_amount`                        BIGINT         DEFAULT NULL COMMENT '表单预约金额(分)',
+    `page_reservation_cost`                     BIGINT         DEFAULT NULL COMMENT '表单预约成本(分)',
+    `page_reservation_cost_with_people`         BIGINT         DEFAULT NULL COMMENT '表单预约成本人数(分)',
+    `page_reservation_rate`                     DECIMAL(12,4)  DEFAULT NULL COMMENT '表单预约率',
+    `page_reservation_roi`                      DECIMAL(12,4)  DEFAULT NULL COMMENT '表单预约ROI',
+    `biz_reservation_uv`                        BIGINT         DEFAULT NULL COMMENT '公众号内表单预约人数',
+    `biz_reservation_follow_rate`               DECIMAL(12,4)  DEFAULT NULL COMMENT '公众号内表单预约率',
+    `external_form_reservation_count`           BIGINT         DEFAULT NULL COMMENT '附加创意表单预约次数',
+    `potential_reserve_count`                   BIGINT         DEFAULT NULL COMMENT '潜在客户线索次数-表单',
+    `reservation_check_uv`                      BIGINT         DEFAULT NULL COMMENT '意向表单人数',
+    `reservation_check_uv_cost`                 BIGINT         DEFAULT NULL COMMENT '意向表单成本(分)',
+    `reservation_check_uv_rate`                 DECIMAL(12,4)  DEFAULT NULL COMMENT '意向表单率(人数)',
+    `effective_reserve_count`                   BIGINT         DEFAULT NULL COMMENT '有效线索次数-表单',
+    `valid_leads_uv`                            BIGINT         DEFAULT NULL COMMENT '有效线索人数-表单',
+    `try_out_intention_uv`                      BIGINT         DEFAULT NULL COMMENT '排程人数',
+    `ineffective_leads_uv`                      BIGINT         DEFAULT NULL COMMENT '无效线索人数',
+    -- 优惠券
+    `coupon_get_pv`                             BIGINT         DEFAULT NULL COMMENT '领券次数',
+    `coupon_get_cost`                           BIGINT         DEFAULT NULL COMMENT '领券成本(分)',
+    `coupon_get_rate`                           DECIMAL(12,4)  DEFAULT NULL COMMENT '领券率',
+    `platform_coupon_click_count`               BIGINT         DEFAULT NULL COMMENT '平台页卡券点击次数',
+    `purchase_amount_with_coupon`               BIGINT         DEFAULT NULL COMMENT '平台页卡券购买次数',
+    `coupon_purchase_rate`                      DECIMAL(12,4)  DEFAULT NULL COMMENT '平台页卡券购买率',
+    `purchase_amount_with_coupon_cost`          BIGINT         DEFAULT NULL COMMENT '平台页卡券购买成本(分)',
+    `coupon_usage_number`                       BIGINT         DEFAULT NULL COMMENT '优惠券使用次数',
+    -- 电话直拨
+    `page_phone_call_direct_count`              BIGINT         DEFAULT NULL COMMENT '电话直拨次数',
+    `page_phone_call_direct_rate`               DECIMAL(12,4)  DEFAULT NULL COMMENT '电话直拨率',
+    `page_phone_call_direct_cost`               BIGINT         DEFAULT NULL COMMENT '电话直拨成本(分)',
+    `potential_phone_count`                     BIGINT         DEFAULT NULL COMMENT '潜在客户线索次数-电话',
+    `potential_customer_phone_uv`               BIGINT         DEFAULT NULL COMMENT '潜在客户人数-电话',
+    `effective_phone_count`                     BIGINT         DEFAULT NULL COMMENT '有效线索次数-电话',
+    `valid_phone_uv`                            BIGINT         DEFAULT NULL COMMENT '有效线索人数-电话',
+    -- ROI收益(LTV)
+    `income_val_1`                              BIGINT         DEFAULT NULL COMMENT '1天收益(分)',
+    `income_roi_1`                              DECIMAL(12,4)  DEFAULT NULL COMMENT '1天ROI',
+    `income_val_3`                              BIGINT         DEFAULT NULL COMMENT '3天收益(分)',
+    `income_roi_3`                              DECIMAL(12,4)  DEFAULT NULL COMMENT '3天ROI',
+    `income_val_7`                              BIGINT         DEFAULT NULL COMMENT '7天收益(分)',
+    `income_roi_7`                              DECIMAL(12,4)  DEFAULT NULL COMMENT '7天ROI',
+    `income_val_14`                             BIGINT         DEFAULT NULL COMMENT '14天收益(分)',
+    `income_roi_14`                             DECIMAL(12,4)  DEFAULT NULL COMMENT '14天ROI',
+    `income_val_24h`                            BIGINT         DEFAULT NULL COMMENT '24小时收益(分)',
+    `income_roi_1_24h`                          DECIMAL(12,4)  DEFAULT NULL COMMENT '1天24小时ROI',
+    -- 审计字段
+    `created_time`  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+    `updated_time`  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+    PRIMARY KEY (`id`),
+    UNIQUE KEY `uk_group_account_creative_date` (`group_id`, `account_id`, `dynamic_creative_id`, `date`),
+    KEY `idx_date` (`date`),
+    KEY `idx_group_id` (`group_id`),
+    KEY `idx_account_id` (`account_id`),
+    KEY `idx_dynamic_creative_id` (`dynamic_creative_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='动态创意日报表(请求时间口径 REQUEST_TIME)';
+
+
+-- 动态创意日报表(统计时间口径)
+-- time_line = REPORTING_TIME
+CREATE TABLE IF NOT EXISTS `rep_daily_creative_report` (
+    `id`                                        BIGINT(20)     NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+    `group_id`                                  BIGINT(20)     NOT NULL DEFAULT 0 COMMENT '账号组ID,关联account_group表',
+    `group_name`                                VARCHAR(100)   DEFAULT NULL COMMENT '账号组名称',
+    `account_id`                                BIGINT(20)     NOT NULL COMMENT '广告主账号ID',
+    `dynamic_creative_id`                       BIGINT(20)     NOT NULL COMMENT '动态创意ID',
+    `date`                                      DATE           NOT NULL COMMENT '日期',
+    -- 基础曝光点击
+    `view_count`                                BIGINT         DEFAULT NULL COMMENT '曝光次数',
+    `view_user_count`                           BIGINT         DEFAULT NULL COMMENT '曝光人数',
+    `avg_view_per_user`                         DECIMAL(12,4)  DEFAULT NULL COMMENT '人均曝光次数',
+    `valid_click_count`                         BIGINT         DEFAULT NULL COMMENT '点击次数',
+    `click_user_count`                          BIGINT         DEFAULT NULL COMMENT '点击人数',
+    `cpc`                                       BIGINT         DEFAULT NULL COMMENT '点击均价(分)',
+    `ctr`                                       DECIMAL(12,4)  DEFAULT NULL COMMENT '点击率',
+    `valuable_click_count`                      BIGINT         DEFAULT NULL COMMENT '可转化点击次数',
+    `valuable_click_cost`                       BIGINT         DEFAULT NULL COMMENT '可转化点击成本(分)',
+    `valuable_click_rate`                       DECIMAL(12,4)  DEFAULT NULL COMMENT '可转化点击率',
+    -- 花费
+    `cost`                                      BIGINT         DEFAULT NULL COMMENT '花费(分)',
+    `acquisition_cost`                          BIGINT         DEFAULT NULL COMMENT '一键起量消耗(分)',
+    `thousand_display_price`                    BIGINT         DEFAULT NULL COMMENT '千次展现均价(分)',
+    -- 转化
+    `conversions_count`                         BIGINT         DEFAULT NULL COMMENT '目标转化量',
+    `conversions_rate`                          DECIMAL(12,4)  DEFAULT NULL COMMENT '目标转化率',
+    `conversions_cost`                          BIGINT         DEFAULT NULL COMMENT '目标转化成本(分)',
+    `deep_conversions_count`                    BIGINT         DEFAULT NULL COMMENT '深度目标转化量',
+    `deep_conversions_rate`                     DECIMAL(12,4)  DEFAULT NULL COMMENT '深度目标转化率',
+    `deep_conversions_cost`                     BIGINT         DEFAULT NULL COMMENT '深度转化成本(分)',
+    `conversions_by_display_count`              BIGINT         DEFAULT NULL COMMENT '目标转化量(曝光归因)',
+    `conversions_by_display_rate`               DECIMAL(12,4)  DEFAULT NULL COMMENT '目标转化率(曝光归因)',
+    `conversions_by_display_cost`               BIGINT         DEFAULT NULL COMMENT '目标转化成本(曝光归因,分)',
+    `conversions_by_click_count`                BIGINT         DEFAULT NULL COMMENT '目标转化量(点击归因)',
+    `conversions_by_click_rate`                 DECIMAL(12,4)  DEFAULT NULL COMMENT '目标转化率(点击归因)',
+    `conversions_by_click_cost`                 BIGINT         DEFAULT NULL COMMENT '目标转化成本(点击归因,分)',
+    `preview_conversions_count`                 BIGINT         DEFAULT NULL COMMENT '目标转化量(在线预览)',
+    `preview_deep_conversions_count`            BIGINT         DEFAULT NULL COMMENT '深度目标转化量(在线预览)',
+    -- 视频播放
+    `video_outer_play_count`                    BIGINT         DEFAULT NULL COMMENT '视频有效播放次数',
+    `video_outer_play_user_count`               BIGINT         DEFAULT NULL COMMENT '视频有效播放人数',
+    `avg_user_play_count`                       DECIMAL(12,4)  DEFAULT NULL COMMENT '人均播放次数',
+    `video_outer_play_time_count`               DECIMAL(12,4)  DEFAULT NULL COMMENT '平均有效播放时长(秒)',
+    `video_outer_play_time_avg_rate`            DECIMAL(12,4)  DEFAULT NULL COMMENT '平均有效播放进度',
+    `video_outer_play_rate`                     DECIMAL(12,4)  DEFAULT NULL COMMENT '有效播放率',
+    `video_outer_play_cost`                     BIGINT         DEFAULT NULL COMMENT '有效播放成本(分)',
+    `video_outer_play10_count`                  BIGINT         DEFAULT NULL COMMENT '10%进度播放次数',
+    `video_outer_play25_count`                  BIGINT         DEFAULT NULL COMMENT '25%进度播放次数',
+    `video_outer_play50_count`                  BIGINT         DEFAULT NULL COMMENT '50%进度播放次数',
+    `video_outer_play75_count`                  BIGINT         DEFAULT NULL COMMENT '75%进度播放次数',
+    `video_outer_play90_count`                  BIGINT         DEFAULT NULL COMMENT '90%进度播放次数',
+    `video_outer_play95_count`                  BIGINT         DEFAULT NULL COMMENT '95%进度播放次数',
+    `video_outer_play100_count`                 BIGINT         DEFAULT NULL COMMENT '100%进度播放次数',
+    `video_outer_play3s_count`                  BIGINT         DEFAULT NULL COMMENT '3s播放完成次数',
+    `video_outer_play3s_rate`                   DECIMAL(12,4)  DEFAULT NULL COMMENT '3s播放完成率',
+    `video_outer_play5s_count`                  BIGINT         DEFAULT NULL COMMENT '5s播放完成次数',
+    `video_outer_play7s_count`                  BIGINT         DEFAULT NULL COMMENT '7s播放完成次数',
+    -- 互动
+    `read_count`                                BIGINT         DEFAULT NULL COMMENT '阅读次数',
+    `read_cost`                                 BIGINT         DEFAULT NULL COMMENT '阅读成本(分)',
+    `comment_count`                             BIGINT         DEFAULT NULL COMMENT '评论次数',
+    `comment_cost`                              BIGINT         DEFAULT NULL COMMENT '评论成本(分)',
+    `praise_count`                              BIGINT         DEFAULT NULL COMMENT '点赞次数',
+    `praise_cost`                               BIGINT         DEFAULT NULL COMMENT '点赞成本(分)',
+    `forward_count`                             BIGINT         DEFAULT NULL COMMENT '分享次数',
+    `forward_cost`                              BIGINT         DEFAULT NULL COMMENT '分享成本(分)',
+    `no_interest_count`                         BIGINT         DEFAULT NULL COMMENT '不感兴趣点击次数',
+    -- 素材点击
+    `live_stream_crt_click_cnt`                 BIGINT         DEFAULT NULL COMMENT '素材点击次数',
+    `click_image_count`                         BIGINT         DEFAULT NULL COMMENT '外层图片点击次数',
+    `click_head_count`                          BIGINT         DEFAULT NULL COMMENT '头像点击次数',
+    `click_detail_count`                        BIGINT         DEFAULT NULL COMMENT '文字链点击次数',
+    `click_poi_count`                           BIGINT         DEFAULT NULL COMMENT '本地门店点击次数',
+    `zone_header_click_count`                   BIGINT         DEFAULT NULL COMMENT '顶部运营位点击次数',
+    `basic_info_client_count`                   BIGINT         DEFAULT NULL COMMENT '官方信息区点击次数',
+    `account_info_click_count`                  BIGINT         DEFAULT NULL COMMENT '官方账号区点击次数',
+    `clk_account_living_status_pv`              BIGINT         DEFAULT NULL COMMENT '官方账号区直播中头像点击次数',
+    `clk_accountinfo_weapp_pv`                  BIGINT         DEFAULT NULL COMMENT '官方账号区小程序组件点击次数',
+    `clk_accountinfo_finder_pv`                 BIGINT         DEFAULT NULL COMMENT '官方账号区视频号组件点击次数',
+    `clk_accountinfo_biz_pv`                    BIGINT         DEFAULT NULL COMMENT '官方账号区公众号组件点击次数',
+    `clk_account_info_producttab_pv`            BIGINT         DEFAULT NULL COMMENT '官方账号区系列tab总点击次数',
+    `clk_account_info_productdetail_pv`         BIGINT         DEFAULT NULL COMMENT '官方账号区商品卡总点击次数',
+    `activity_info_click_count`                 BIGINT         DEFAULT NULL COMMENT '热门活动区点击次数',
+    -- 线索
+    `overall_leads_purchase_count`              BIGINT         DEFAULT NULL COMMENT '综合销售线索人数',
+    `effective_leads_count`                     BIGINT         DEFAULT NULL COMMENT '有效线索次数',
+    `effective_cost`                            BIGINT         DEFAULT NULL COMMENT '有效线索成本(分)',
+    `effect_leads_purchase_count`               BIGINT         DEFAULT NULL COMMENT '有效线索人数',
+    `effect_leads_purchase_cost`                BIGINT         DEFAULT NULL COMMENT '有效线索成本人数(分)',
+    -- 落地页
+    `platform_page_view_count`                  BIGINT         DEFAULT NULL COMMENT '落地页曝光次数',
+    `platform_page_view_rate`                   DECIMAL(12,4)  DEFAULT NULL COMMENT '落地页曝光率',
+    `lan_button_click_count`                    BIGINT         DEFAULT NULL COMMENT '落地页组件点击次数',
+    `lan_jump_button_clickers`                  BIGINT         DEFAULT NULL COMMENT '落地页组件点击人数',
+    `lan_button_click_cost`                     BIGINT         DEFAULT NULL COMMENT '落地页点击成本(分)',
+    `lan_jump_button_ctr`                       DECIMAL(12,4)  DEFAULT NULL COMMENT '落地页点击率(人数)',
+    `lan_jump_button_click_cost`                BIGINT         DEFAULT NULL COMMENT '落地页点击成本人数(分)',
+    -- 关键页面
+    `key_page_view_count`                       BIGINT         DEFAULT NULL COMMENT '关键页面访问次数',
+    `key_page_view_by_display_count`            BIGINT         DEFAULT NULL COMMENT '关键页面访问次数(曝光归因)',
+    `key_page_view_by_click_count`              BIGINT         DEFAULT NULL COMMENT '关键页面访问次数(点击归因)',
+    `key_page_uv`                               BIGINT         DEFAULT NULL COMMENT '关键页面访问人数',
+    `key_page_view_cost`                        BIGINT         DEFAULT NULL COMMENT '关键页面访问成本(分)',
+    `key_page_view_rate`                        DECIMAL(12,4)  DEFAULT NULL COMMENT '关键页面访问率',
+    -- 商品页
+    `landing_commodity_detail_exp_pv`           BIGINT         DEFAULT NULL COMMENT '商品页浏览次数',
+    `app_commodity_page_view_by_display_count`  BIGINT         DEFAULT NULL COMMENT '商品页浏览次数(曝光归因)',
+    `app_commodity_page_view_by_click_count`    BIGINT         DEFAULT NULL COMMENT '商品页浏览次数(点击归因)',
+    `view_commodity_page_uv`                    BIGINT         DEFAULT NULL COMMENT '商品页浏览人数',
+    `web_commodity_page_view_rate`              DECIMAL(12,4)  DEFAULT NULL COMMENT '商品页浏览率',
+    `web_commodity_page_view_cost`              BIGINT         DEFAULT NULL COMMENT '商品页浏览成本(分)',
+    -- 导航
+    `own_page_navigation_count`                 BIGINT         DEFAULT NULL COMMENT '自有页导航次数',
+    `own_page_navi_cost`                        BIGINT         DEFAULT NULL COMMENT '自有页导航成本(分)',
+    `platform_page_navigation_count`            BIGINT         DEFAULT NULL COMMENT '平台页导航次数',
+    `platform_page_navigation_cost`             BIGINT         DEFAULT NULL COMMENT '平台页导航成本(分)',
+    `platform_shop_navigation_count`            BIGINT         DEFAULT NULL COMMENT '平台页门店点击次数',
+    `platform_shop_navigation_cost`             BIGINT         DEFAULT NULL COMMENT '平台页门店页导航成本(分)',
+    -- 活动页/加粉
+    `active_page_views`                         BIGINT         DEFAULT NULL COMMENT '活动页面访问次数',
+    `active_page_viewers`                       BIGINT         DEFAULT NULL COMMENT '活动页面访问人数',
+    `active_page_interaction_amount`            BIGINT         DEFAULT NULL COMMENT '活动页面互动次数',
+    `active_page_interaction_users`             BIGINT         DEFAULT NULL COMMENT '活动页面互动人数',
+    `guide_to_follow_page_views`                BIGINT         DEFAULT NULL COMMENT '加粉引导页浏览次数',
+    `guide_to_follow_page_viewers`              BIGINT         DEFAULT NULL COMMENT '加粉引导页浏览人数',
+    `guide_to_follow_page_interaction_amount`   BIGINT         DEFAULT NULL COMMENT '加粉引导页互动次数',
+    `guide_to_follow_page_interaction_users`    BIGINT         DEFAULT NULL COMMENT '加粉引导页互动人数',
+    `platform_key_page_view_user_count`         BIGINT         DEFAULT NULL COMMENT '落地页曝光人数',
+    -- 在线咨询
+    `page_consult_count`                        BIGINT         DEFAULT NULL COMMENT '在线咨询次数',
+    `consult_uv_count`                          BIGINT         DEFAULT NULL COMMENT '在线咨询人数',
+    `page_consult_rate`                         DECIMAL(12,4)  DEFAULT NULL COMMENT '在线咨询率',
+    `page_consult_cost`                         BIGINT         DEFAULT NULL COMMENT '在线咨询成本(分)',
+    `consult_leave_info_users`                  BIGINT         DEFAULT NULL COMMENT '咨询留资人数',
+    `consult_leave_info_cost`                   BIGINT         DEFAULT NULL COMMENT '咨询留咨成本(分)',
+    `potential_consult_count`                   BIGINT         DEFAULT NULL COMMENT '潜在客户线索次数-咨询',
+    `effective_consult_count`                   BIGINT         DEFAULT NULL COMMENT '有效线索次数-咨询',
+    `tool_consult_count`                        BIGINT         DEFAULT NULL COMMENT '附加创意智能咨询次数',
+    -- 表单预约
+    `page_reservation_count`                    BIGINT         DEFAULT NULL COMMENT '表单预约次数',
+    `page_reservation_by_display_count`         BIGINT         DEFAULT NULL COMMENT '表单预约次数(曝光归因)',
+    `page_reservation_by_click_count`           BIGINT         DEFAULT NULL COMMENT '表单预约次数(点击归因)',
+    `reservation_uv`                            BIGINT         DEFAULT NULL COMMENT '表单预约人数',
+    `reservation_amount`                        BIGINT         DEFAULT NULL COMMENT '表单预约金额(分)',
+    `page_reservation_cost`                     BIGINT         DEFAULT NULL COMMENT '表单预约成本(分)',
+    `page_reservation_cost_with_people`         BIGINT         DEFAULT NULL COMMENT '表单预约成本人数(分)',
+    `page_reservation_rate`                     DECIMAL(12,4)  DEFAULT NULL COMMENT '表单预约率',
+    `page_reservation_roi`                      DECIMAL(12,4)  DEFAULT NULL COMMENT '表单预约ROI',
+    `biz_reservation_uv`                        BIGINT         DEFAULT NULL COMMENT '公众号内表单预约人数',
+    `biz_reservation_follow_rate`               DECIMAL(12,4)  DEFAULT NULL COMMENT '公众号内表单预约率',
+    `external_form_reservation_count`           BIGINT         DEFAULT NULL COMMENT '附加创意表单预约次数',
+    `potential_reserve_count`                   BIGINT         DEFAULT NULL COMMENT '潜在客户线索次数-表单',
+    `reservation_check_uv`                      BIGINT         DEFAULT NULL COMMENT '意向表单人数',
+    `reservation_check_uv_cost`                 BIGINT         DEFAULT NULL COMMENT '意向表单成本(分)',
+    `reservation_check_uv_rate`                 DECIMAL(12,4)  DEFAULT NULL COMMENT '意向表单率(人数)',
+    `effective_reserve_count`                   BIGINT         DEFAULT NULL COMMENT '有效线索次数-表单',
+    `valid_leads_uv`                            BIGINT         DEFAULT NULL COMMENT '有效线索人数-表单',
+    `try_out_intention_uv`                      BIGINT         DEFAULT NULL COMMENT '排程人数',
+    `ineffective_leads_uv`                      BIGINT         DEFAULT NULL COMMENT '无效线索人数',
+    -- 优惠券
+    `coupon_get_pv`                             BIGINT         DEFAULT NULL COMMENT '领券次数',
+    `coupon_get_cost`                           BIGINT         DEFAULT NULL COMMENT '领券成本(分)',
+    `coupon_get_rate`                           DECIMAL(12,4)  DEFAULT NULL COMMENT '领券率',
+    `platform_coupon_click_count`               BIGINT         DEFAULT NULL COMMENT '平台页卡券点击次数',
+    `purchase_amount_with_coupon`               BIGINT         DEFAULT NULL COMMENT '平台页卡券购买次数',
+    `coupon_purchase_rate`                      DECIMAL(12,4)  DEFAULT NULL COMMENT '平台页卡券购买率',
+    `purchase_amount_with_coupon_cost`          BIGINT         DEFAULT NULL COMMENT '平台页卡券购买成本(分)',
+    `coupon_usage_number`                       BIGINT         DEFAULT NULL COMMENT '优惠券使用次数',
+    -- 电话直拨
+    `page_phone_call_direct_count`              BIGINT         DEFAULT NULL COMMENT '电话直拨次数',
+    `page_phone_call_direct_rate`               DECIMAL(12,4)  DEFAULT NULL COMMENT '电话直拨率',
+    `page_phone_call_direct_cost`               BIGINT         DEFAULT NULL COMMENT '电话直拨成本(分)',
+    `potential_phone_count`                     BIGINT         DEFAULT NULL COMMENT '潜在客户线索次数-电话',
+    `potential_customer_phone_uv`               BIGINT         DEFAULT NULL COMMENT '潜在客户人数-电话',
+    `effective_phone_count`                     BIGINT         DEFAULT NULL COMMENT '有效线索次数-电话',
+    `valid_phone_uv`                            BIGINT         DEFAULT NULL COMMENT '有效线索人数-电话',
+    -- ROI收益(LTV)
+    `income_val_1`                              BIGINT         DEFAULT NULL COMMENT '1天收益(分)',
+    `income_roi_1`                              DECIMAL(12,4)  DEFAULT NULL COMMENT '1天ROI',
+    `income_val_3`                              BIGINT         DEFAULT NULL COMMENT '3天收益(分)',
+    `income_roi_3`                              DECIMAL(12,4)  DEFAULT NULL COMMENT '3天ROI',
+    `income_val_7`                              BIGINT         DEFAULT NULL COMMENT '7天收益(分)',
+    `income_roi_7`                              DECIMAL(12,4)  DEFAULT NULL COMMENT '7天ROI',
+    `income_val_14`                             BIGINT         DEFAULT NULL COMMENT '14天收益(分)',
+    `income_roi_14`                             DECIMAL(12,4)  DEFAULT NULL COMMENT '14天ROI',
+    `income_val_24h`                            BIGINT         DEFAULT NULL COMMENT '24小时收益(分)',
+    `income_roi_1_24h`                          DECIMAL(12,4)  DEFAULT NULL COMMENT '1天24小时ROI',
+    -- 审计字段
+    `created_time`  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+    `updated_time`  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+    PRIMARY KEY (`id`),
+    UNIQUE KEY `uk_group_account_creative_date` (`group_id`, `account_id`, `dynamic_creative_id`, `date`),
+    KEY `idx_date` (`date`),
+    KEY `idx_group_id` (`group_id`),
+    KEY `idx_account_id` (`account_id`),
+    KEY `idx_dynamic_creative_id` (`dynamic_creative_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='动态创意日报表(统计时间口径 REPORTING_TIME)';

+ 0 - 1
src/test/java/com/moka/gdtauto/integration/AdgroupsApiManualTest.java

@@ -5,7 +5,6 @@ import com.moka.gdtauto.GdtAutoApplication;
 import com.moka.gdtauto.service.TencentAdsAccountService;
 import com.tencent.ads.model.v3.AdgroupsGetResponseData;
 
-import org.aspectj.weaver.ast.Or;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;

+ 73 - 0
src/test/java/com/moka/gdtauto/service/DailyReportTest.java

@@ -0,0 +1,73 @@
+package com.moka.gdtauto.service;
+
+import com.moka.gdtauto.GdtAutoApplication;
+import org.junit.jupiter.api.DisplayName;
+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;
+
+/**
+ * 腾讯广告 日报表同步入库测试
+ * https://developers.e.qq.com/v3.0/docs/api/daily_reports/get
+ *
+ * mvn test -Dtest=DailyReportTest -Dspring.profiles.active=test
+ *
+ * @author moka
+ * @since 2026-03-03
+ */
+@SpringBootTest(classes = GdtAutoApplication.class)
+@ActiveProfiles("test")
+class DailyReportTest {
+
+    @Autowired
+    private DailyReportService dailyReportService;
+
+    private static final Long ORG_ACCOUNT_ID = 41644744L;
+    private static final Long TEST_ACCOUNT_ID = 69781948L;
+    private static final String TEST_JOB_NUMBER = "12458";
+    private static final Long TEST_GROUP_ID = 1L;
+    private static final String TEST_GROUP_NAME = "蒲栋良测试组";
+
+    @Test
+    @DisplayName("同步 REQUEST_TIME 口径日报表并入库")
+    void testSyncRequestTime() throws Exception {
+        System.out.println("\n========================================");
+        System.out.println("开始同步 REQUEST_TIME 日报表");
+        System.out.println("账户ID: " + TEST_ACCOUNT_ID);
+        System.out.println("========================================\n");
+
+        int saved = dailyReportService.syncReport(
+                TEST_JOB_NUMBER,
+                ORG_ACCOUNT_ID,
+                TEST_ACCOUNT_ID,
+                TEST_GROUP_ID,
+                TEST_GROUP_NAME,
+                "2026-02-20",
+                "2026-03-03",
+                "REQUEST_TIME"
+        );
+        System.out.println("✅ REQUEST_TIME 同步完成,入库条数: " + saved);
+    }
+
+    @Test
+    @DisplayName("同步 REPORTING_TIME 口径日报表并入库")
+    void testSyncReportingTime() throws Exception {
+        System.out.println("\n========================================");
+        System.out.println("开始同步 REPORTING_TIME 日报表");
+        System.out.println("账户ID: " + TEST_ACCOUNT_ID);
+        System.out.println("========================================\n");
+
+        int saved = dailyReportService.syncReport(
+                TEST_JOB_NUMBER,
+                ORG_ACCOUNT_ID,
+                TEST_ACCOUNT_ID,
+                TEST_GROUP_ID,
+                TEST_GROUP_NAME,
+                "2026-02-20",
+                "2026-03-03",
+                "REPORTING_TIME"
+        );
+        System.out.println("✅ REPORTING_TIME 同步完成,入库条数: " + saved);
+    }
+}

+ 0 - 2
src/test/java/com/moka/gdtauto/service/TencentAssetDramaTest.java

@@ -1,12 +1,10 @@
 package com.moka.gdtauto.service;
 
-import com.alibaba.fastjson2.JSON;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.moka.gdtauto.GdtAutoApplication;
 import com.moka.gdtauto.client.TencentAdsApiClientFactory;
 import com.tencent.ads.model.v3.MarketingTargetAssetsGetResponseData;
-import com.tencent.ads.model.v3.MarketingTargetType;
 import com.tencent.ads.v3.TencentAds;
 
 import org.junit.jupiter.api.DisplayName;

+ 1 - 0
src/test/java/com/moka/gdtauto/util/VideoWatermarkSimpleTest.java

@@ -59,6 +59,7 @@ public class VideoWatermarkSimpleTest {
     /**
      * 创建测试视频
      */
+    @SuppressWarnings("resource")
     private static void createTestVideo(String path, int width, int height, double frameRate, int duration) throws Exception {
         FFmpegFrameRecorder recorder = null;
         Java2DFrameConverter converter = new Java2DFrameConverter();

+ 1 - 2
src/test/java/com/moka/gdtauto/util/VideoWatermarkUtilTest.java

@@ -6,11 +6,9 @@ import org.bytedeco.javacv.Java2DFrameConverter;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
-import javax.imageio.ImageIO;
 import java.awt.*;
 import java.awt.image.BufferedImage;
 import java.io.File;
-import java.io.IOException;
 
 /**
  * 视频水印工具类测试
@@ -121,6 +119,7 @@ class VideoWatermarkUtilTest {
      * @param frameRate 帧率
      * @param duration  时长(秒)
      */
+    @SuppressWarnings("resource")
     private void createTestVideo(String path, int width, int height, double frameRate, int duration) throws Exception {
         log.info("开始创建测试视频: {}, 尺寸: {}x{}, 帧率: {}, 时长: {}秒", path, width, height, frameRate, duration);
 

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio