Browse Source

网站质量检查结果功能完善联调测试通过

Jack 10 months ago
parent
commit
386838fb0d
22 changed files with 1656 additions and 26 deletions
  1. 37 26
      .idea/workspace.xml
  2. 279 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/controller/OkkiYoutubeMarketingDataController.java
  3. 58 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/entity/OkkiYoutubeMarketingData.java
  4. 85 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/entity/OkkiYoutubeMarketingDataDetail.java
  5. 32 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/mapper/OkkiYoutubeMarketingDataDetailMapper.java
  6. 14 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/mapper/OkkiYoutubeMarketingDataMapper.java
  7. 16 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/mapper/xml/OkkiYoutubeMarketingDataDetailMapper.xml
  8. 5 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/mapper/xml/OkkiYoutubeMarketingDataMapper.xml
  9. 30 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/param/ReportListParam.java
  10. 13 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/param/YoutubeMarketingDataParam.java
  11. 22 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/service/IOkkiYoutubeMarketingDataDetailService.java
  12. 49 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/service/IOkkiYoutubeMarketingDataService.java
  13. 27 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/service/impl/OkkiYoutubeMarketingDataDetailServiceImpl.java
  14. 144 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/service/impl/OkkiYoutubeMarketingDataServiceImpl.java
  15. 59 0
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/vo/OkkiYoutubeMarketingDataPage.java
  16. 77 0
      jeecgboot-vue3/src/views/okki/youtube/OkkiYoutubeMarketingData.api.ts
  17. 183 0
      jeecgboot-vue3/src/views/okki/youtube/OkkiYoutubeMarketingData.data.ts
  18. 208 0
      jeecgboot-vue3/src/views/okki/youtube/OkkiYoutubeMarketingDataList.vue
  19. 26 0
      jeecgboot-vue3/src/views/okki/youtube/V20240516_1__menu_insert_OkkiYoutubeMarketingData.sql
  20. 134 0
      jeecgboot-vue3/src/views/okki/youtube/components/OkkiYoutubeMarketingDataForm.vue
  21. 114 0
      jeecgboot-vue3/src/views/okki/youtube/components/OkkiYoutubeMarketingDataModal.vue
  22. 44 0
      jeecgboot-vue3/src/views/okki/youtube/subTables/OkkiYoutubeMarketingDataDetailSubTable.vue

+ 37 - 26
.idea/workspace.xml

@@ -4,26 +4,28 @@
     <option name="autoReloadType" value="SELECTIVE" />
   </component>
   <component name="ChangeListManager">
-    <list default="true" id="ed63665b-8c5d-41ac-a75b-7a0cfc2d6ec5" name="Default Changelist" comment="showlist功能完善联调测试通过">
-      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality/controller/OkkiWebsiteQualityApiController.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality/controller/OkkiWebsiteQualityController.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality/entity/OkkiWebsiteQuality.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality/mapper/OkkiWebsiteQualityMapper.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality/mapper/xml/OkkiWebsiteQualityMapper.xml" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality/param/DomainStatusParam.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality/param/GaStatusParam.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality/param/InquiryEmailStatusParam.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality/param/LoadSpeedStatusParam.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality/param/OkkiWebsiteQualityParam.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality/param/SitemapStatusParam.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality/service/IOkkiWebsiteQualityService.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality/service/impl/OkkiWebsiteQualityServiceImpl.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecgboot-vue3/src/views/okki/websitequality/OkkiWebsiteQuality.api.ts" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecgboot-vue3/src/views/okki/websitequality/OkkiWebsiteQuality.data.ts" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecgboot-vue3/src/views/okki/websitequality/OkkiWebsiteQualityList.vue" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecgboot-vue3/src/views/okki/websitequality/V20240515_1__menu_insert_OkkiWebsiteQuality.sql" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecgboot-vue3/src/views/okki/websitequality/components/OkkiWebsiteQualityForm.vue" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/jeecgboot-vue3/src/views/okki/websitequality/components/OkkiWebsiteQualityModal.vue" afterDir="false" />
+    <list default="true" id="ed63665b-8c5d-41ac-a75b-7a0cfc2d6ec5" name="Default Changelist" comment="网站质量检查结果功能完善联调测试通过">
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/controller/OkkiYoutubeMarketingDataController.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/entity/OkkiYoutubeMarketingData.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/entity/OkkiYoutubeMarketingDataDetail.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/mapper/OkkiYoutubeMarketingDataDetailMapper.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/mapper/OkkiYoutubeMarketingDataMapper.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/mapper/xml/OkkiYoutubeMarketingDataDetailMapper.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/mapper/xml/OkkiYoutubeMarketingDataMapper.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/param/ReportListParam.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/param/YoutubeMarketingDataParam.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/service/IOkkiYoutubeMarketingDataDetailService.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/service/IOkkiYoutubeMarketingDataService.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/service/impl/OkkiYoutubeMarketingDataDetailServiceImpl.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/service/impl/OkkiYoutubeMarketingDataServiceImpl.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/vo/OkkiYoutubeMarketingDataPage.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecgboot-vue3/src/views/okki/youtube/OkkiYoutubeMarketingData.api.ts" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecgboot-vue3/src/views/okki/youtube/OkkiYoutubeMarketingData.data.ts" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecgboot-vue3/src/views/okki/youtube/OkkiYoutubeMarketingDataList.vue" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecgboot-vue3/src/views/okki/youtube/V20240516_1__menu_insert_OkkiYoutubeMarketingData.sql" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecgboot-vue3/src/views/okki/youtube/components/OkkiYoutubeMarketingDataForm.vue" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecgboot-vue3/src/views/okki/youtube/components/OkkiYoutubeMarketingDataModal.vue" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/jeecgboot-vue3/src/views/okki/youtube/subTables/OkkiYoutubeMarketingDataDetailSubTable.vue" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
     </list>
     <option name="SHOW_DIALOG" value="false" />
@@ -89,7 +91,7 @@
     "Spring Boot.JeecgSystemApplication.executor": "Debug",
     "git-widget-placeholder": "master",
     "kotlin-language-version-configured": "true",
-    "last_opened_file_path": "D:/ProjectsCode/okki-oms/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/websitequality",
+    "last_opened_file_path": "D:/ProjectsCode/okki-oms/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube",
     "node.js.detected.package.eslint": "true",
     "node.js.detected.package.stylelint": "true",
     "node.js.detected.package.tslint": "true",
@@ -115,11 +117,11 @@
   </component>
   <component name="RecentsManager">
     <key name="CopyFile.RECENT_KEYS">
+      <recent name="D:\ProjectsCode\okki-oms\jeecg-boot\jeecg-module-system\jeecg-system-biz\src\main\java\org\jeecg\modules\okki\youtube" />
+      <recent name="D:\ProjectsCode\okki-oms\jeecgboot-vue3\src\views\okki\youtube" />
       <recent name="D:\ProjectsCode\okki-oms\jeecg-boot\jeecg-module-system\jeecg-system-biz\src\main\java\org\jeecg\modules\okki\websitequality" />
       <recent name="D:\ProjectsCode\okki-oms\jeecgboot-vue3\src\views\okki\websitequality" />
       <recent name="D:\ProjectsCode\okki-oms\jeecg-boot\jeecg-module-system\jeecg-system-biz\src\main\java\org\jeecg\modules\okki\showlist\entity" />
-      <recent name="D:\ProjectsCode\okki-oms\jeecg-boot\jeecg-module-system\jeecg-system-biz\src\main\java\org\jeecg\modules\okki\showlist" />
-      <recent name="D:\ProjectsCode\okki-oms\jeecgboot-vue3\src\views\okki\showlist" />
     </key>
     <key name="CopyClassDialog.RECENTS_KEY">
       <recent name="org.jeecg.modules.okki.websitequality.param" />
@@ -182,7 +184,7 @@
       <workItem from="1714957905106" duration="25834000" />
       <workItem from="1715333910993" duration="2376000" />
       <workItem from="1715391022847" duration="21115000" />
-      <workItem from="1715648405916" duration="39732000" />
+      <workItem from="1715648405916" duration="48519000" />
     </task>
     <task id="LOCAL-00001" summary="增加添加站点对外接口">
       <option name="closed" value="true" />
@@ -328,7 +330,15 @@
       <option name="project" value="LOCAL" />
       <updated>1715766634432</updated>
     </task>
-    <option name="localTasksCounter" value="19" />
+    <task id="LOCAL-00019" summary="网站质量检查结果功能完善联调测试通过">
+      <option name="closed" value="true" />
+      <created>1715828313692</created>
+      <option name="number" value="00019" />
+      <option name="presentableId" value="LOCAL-00019" />
+      <option name="project" value="LOCAL" />
+      <updated>1715828313692</updated>
+    </task>
+    <option name="localTasksCounter" value="20" />
     <servers />
   </component>
   <component name="TypeScriptGeneratedFilesManager">
@@ -350,7 +360,8 @@
     <MESSAGE value="新增状态变更记录" />
     <MESSAGE value="新增showlist功能" />
     <MESSAGE value="showlist功能完善联调测试通过" />
-    <option name="LAST_COMMIT_MESSAGE" value="showlist功能完善联调测试通过" />
+    <MESSAGE value="网站质量检查结果功能完善联调测试通过" />
+    <option name="LAST_COMMIT_MESSAGE" value="网站质量检查结果功能完善联调测试通过" />
   </component>
   <component name="XSLT-Support.FileAssociations.UIState">
     <expand />

+ 279 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/controller/OkkiYoutubeMarketingDataController.java

@@ -0,0 +1,279 @@
+package org.jeecg.modules.okki.youtube.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
+import org.jeecg.common.system.query.QueryGenerator;
+import org.jeecg.common.system.vo.LoginUser;
+import org.jeecg.common.util.oConvertUtils;
+import org.jeecg.modules.okki.youtube.entity.OkkiYoutubeMarketingData;
+import org.jeecg.modules.okki.youtube.entity.OkkiYoutubeMarketingDataDetail;
+import org.jeecg.modules.okki.youtube.service.IOkkiYoutubeMarketingDataDetailService;
+import org.jeecg.modules.okki.youtube.service.IOkkiYoutubeMarketingDataService;
+import org.jeecg.modules.okki.youtube.vo.OkkiYoutubeMarketingDataPage;
+import org.jeecgframework.poi.excel.ExcelImportUtil;
+import org.jeecgframework.poi.excel.def.NormalExcelConstants;
+import org.jeecgframework.poi.excel.entity.ExportParams;
+import org.jeecgframework.poi.excel.entity.ImportParams;
+import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+ /**
+ * @Description: Youtube营销效果数据
+ * @Author: jeecg-boot
+ * @Date:   2024-05-16
+ * @Version: V1.0
+ */
+@Api(tags="Youtube营销效果数据")
+@RestController
+@RequestMapping("/youtube/okkiYoutubeMarketingData")
+@Slf4j
+public class OkkiYoutubeMarketingDataController {
+	@Autowired
+	private IOkkiYoutubeMarketingDataService okkiYoutubeMarketingDataService;
+	@Autowired
+	private IOkkiYoutubeMarketingDataDetailService okkiYoutubeMarketingDataDetailService;
+	
+	/**
+	 * 分页列表查询
+	 *
+	 * @param okkiYoutubeMarketingData
+	 * @param pageNo
+	 * @param pageSize
+	 * @param req
+	 * @return
+	 */
+	//@AutoLog(value = "Youtube营销效果数据-分页列表查询")
+	@ApiOperation(value="Youtube营销效果数据-分页列表查询", notes="Youtube营销效果数据-分页列表查询")
+	@GetMapping(value = "/list")
+	public Result<IPage<OkkiYoutubeMarketingData>> queryPageList(OkkiYoutubeMarketingData okkiYoutubeMarketingData,
+								   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
+								   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
+								   HttpServletRequest req) {
+		QueryWrapper<OkkiYoutubeMarketingData> queryWrapper = QueryGenerator.initQueryWrapper(okkiYoutubeMarketingData, req.getParameterMap());
+		Page<OkkiYoutubeMarketingData> page = new Page<OkkiYoutubeMarketingData>(pageNo, pageSize);
+		IPage<OkkiYoutubeMarketingData> pageList = okkiYoutubeMarketingDataService.page(page, queryWrapper);
+		return Result.OK(pageList);
+	}
+	
+	/**
+	 *   添加
+	 *
+	 * @param okkiYoutubeMarketingDataPage
+	 * @return
+	 */
+	@AutoLog(value = "Youtube营销效果数据-添加")
+	@ApiOperation(value="Youtube营销效果数据-添加", notes="Youtube营销效果数据-添加")
+    @RequiresPermissions("youtube:okki_youtube_marketing_data:add")
+	@PostMapping(value = "/add")
+	public Result<String> add(@RequestBody OkkiYoutubeMarketingDataPage okkiYoutubeMarketingDataPage) {
+		OkkiYoutubeMarketingData okkiYoutubeMarketingData = new OkkiYoutubeMarketingData();
+		BeanUtils.copyProperties(okkiYoutubeMarketingDataPage, okkiYoutubeMarketingData);
+		okkiYoutubeMarketingDataService.saveMain(okkiYoutubeMarketingData, okkiYoutubeMarketingDataPage.getOkkiYoutubeMarketingDataDetailList());
+		return Result.OK("添加成功!");
+	}
+	
+	/**
+	 *  编辑
+	 *
+	 * @param okkiYoutubeMarketingDataPage
+	 * @return
+	 */
+	@AutoLog(value = "Youtube营销效果数据-编辑")
+	@ApiOperation(value="Youtube营销效果数据-编辑", notes="Youtube营销效果数据-编辑")
+    @RequiresPermissions("youtube:okki_youtube_marketing_data:edit")
+	@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
+	public Result<String> edit(@RequestBody OkkiYoutubeMarketingDataPage okkiYoutubeMarketingDataPage) {
+		OkkiYoutubeMarketingData okkiYoutubeMarketingData = new OkkiYoutubeMarketingData();
+		BeanUtils.copyProperties(okkiYoutubeMarketingDataPage, okkiYoutubeMarketingData);
+		OkkiYoutubeMarketingData okkiYoutubeMarketingDataEntity = okkiYoutubeMarketingDataService.getById(okkiYoutubeMarketingData.getId());
+		if(okkiYoutubeMarketingDataEntity==null) {
+			return Result.error("未找到对应数据");
+		}
+		okkiYoutubeMarketingData.setStatus(0);
+		okkiYoutubeMarketingDataService.updateMain(okkiYoutubeMarketingData, okkiYoutubeMarketingDataPage.getOkkiYoutubeMarketingDataDetailList());
+		return Result.OK("编辑成功!");
+	}
+	
+	/**
+	 *   通过id删除
+	 *
+	 * @param id
+	 * @return
+	 */
+	@AutoLog(value = "Youtube营销效果数据-通过id删除")
+	@ApiOperation(value="Youtube营销效果数据-通过id删除", notes="Youtube营销效果数据-通过id删除")
+    @RequiresPermissions("youtube:okki_youtube_marketing_data:delete")
+	@DeleteMapping(value = "/delete")
+	public Result<String> delete(@RequestParam(name="id",required=true) String id) {
+		okkiYoutubeMarketingDataService.delMain(id);
+		return Result.OK("删除成功!");
+	}
+	
+	/**
+	 *  批量删除
+	 *
+	 * @param ids
+	 * @return
+	 */
+	@AutoLog(value = "Youtube营销效果数据-批量删除")
+	@ApiOperation(value="Youtube营销效果数据-批量删除", notes="Youtube营销效果数据-批量删除")
+    @RequiresPermissions("youtube:okki_youtube_marketing_data:deleteBatch")
+	@DeleteMapping(value = "/deleteBatch")
+	public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
+		this.okkiYoutubeMarketingDataService.delBatchMain(Arrays.asList(ids.split(",")));
+		return Result.OK("批量删除成功!");
+	}
+	
+	/**
+	 * 通过id查询
+	 *
+	 * @param id
+	 * @return
+	 */
+	//@AutoLog(value = "Youtube营销效果数据-通过id查询")
+	@ApiOperation(value="Youtube营销效果数据-通过id查询", notes="Youtube营销效果数据-通过id查询")
+	@GetMapping(value = "/queryById")
+	public Result<OkkiYoutubeMarketingData> queryById(@RequestParam(name="id",required=true) String id) {
+		OkkiYoutubeMarketingData okkiYoutubeMarketingData = okkiYoutubeMarketingDataService.getById(id);
+		if(okkiYoutubeMarketingData==null) {
+			return Result.error("未找到对应数据");
+		}
+		return Result.OK(okkiYoutubeMarketingData);
+
+	}
+	
+	/**
+	 * 通过id查询
+	 *
+	 * @param id
+	 * @return
+	 */
+	//@AutoLog(value = "Youtube营销效果数据详情-通过主表ID查询")
+	@ApiOperation(value="Youtube营销效果数据详情-通过主表ID查询", notes="Youtube营销效果数据详情-通过主表ID查询")
+	@GetMapping(value = "/queryOkkiYoutubeMarketingDataDetailByMainId")
+	public Result<IPage<OkkiYoutubeMarketingDataDetail>> queryOkkiYoutubeMarketingDataDetailListByMainId(@RequestParam(name="id",required=true) String id) {
+		List<OkkiYoutubeMarketingDataDetail> okkiYoutubeMarketingDataDetailList = okkiYoutubeMarketingDataDetailService.selectByMainId(id);
+		IPage <OkkiYoutubeMarketingDataDetail> page = new Page<>();
+		page.setRecords(okkiYoutubeMarketingDataDetailList);
+		page.setTotal(okkiYoutubeMarketingDataDetailList.size());
+		return Result.OK(page);
+	}
+
+    /**
+    * 导出excel
+    *
+    * @param request
+    * @param okkiYoutubeMarketingData
+    */
+    @RequiresPermissions("youtube:okki_youtube_marketing_data:exportXls")
+    @RequestMapping(value = "/exportXls")
+    public ModelAndView exportXls(HttpServletRequest request, OkkiYoutubeMarketingData okkiYoutubeMarketingData) {
+      // Step.1 组装查询条件查询数据
+      QueryWrapper<OkkiYoutubeMarketingData> queryWrapper = QueryGenerator.initQueryWrapper(okkiYoutubeMarketingData, request.getParameterMap());
+      LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+
+     //配置选中数据查询条件
+      String selections = request.getParameter("selections");
+      if(oConvertUtils.isNotEmpty(selections)) {
+           List<String> selectionList = Arrays.asList(selections.split(","));
+           queryWrapper.in("id",selectionList);
+      }
+      //Step.2 获取导出数据
+      List<OkkiYoutubeMarketingData>  okkiYoutubeMarketingDataList = okkiYoutubeMarketingDataService.list(queryWrapper);
+
+      // Step.3 组装pageList
+      List<OkkiYoutubeMarketingDataPage> pageList = new ArrayList<OkkiYoutubeMarketingDataPage>();
+      for (OkkiYoutubeMarketingData main : okkiYoutubeMarketingDataList) {
+          OkkiYoutubeMarketingDataPage vo = new OkkiYoutubeMarketingDataPage();
+          BeanUtils.copyProperties(main, vo);
+          List<OkkiYoutubeMarketingDataDetail> okkiYoutubeMarketingDataDetailList = okkiYoutubeMarketingDataDetailService.selectByMainId(main.getId());
+          vo.setOkkiYoutubeMarketingDataDetailList(okkiYoutubeMarketingDataDetailList);
+          pageList.add(vo);
+      }
+
+      // Step.4 AutoPoi 导出Excel
+      ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
+      mv.addObject(NormalExcelConstants.FILE_NAME, "Youtube营销效果数据列表");
+      mv.addObject(NormalExcelConstants.CLASS, OkkiYoutubeMarketingDataPage.class);
+      mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("Youtube营销效果数据数据", "导出人:"+sysUser.getRealname(), "Youtube营销效果数据"));
+      mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
+      return mv;
+    }
+
+    /**
+    * 通过excel导入数据
+    *
+    * @param request
+    * @param response
+    * @return
+    */
+    @RequiresPermissions("youtube:okki_youtube_marketing_data:importExcel")
+    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
+    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
+      MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
+      Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
+      for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
+          // 获取上传文件对象
+          MultipartFile file = entity.getValue();
+          ImportParams params = new ImportParams();
+          params.setTitleRows(2);
+          params.setHeadRows(1);
+          params.setNeedSave(true);
+          try {
+              List<OkkiYoutubeMarketingDataPage> list = ExcelImportUtil.importExcel(file.getInputStream(), OkkiYoutubeMarketingDataPage.class, params);
+              for (OkkiYoutubeMarketingDataPage page : list) {
+                  OkkiYoutubeMarketingData po = new OkkiYoutubeMarketingData();
+                  BeanUtils.copyProperties(page, po);
+                  okkiYoutubeMarketingDataService.saveMain(po, page.getOkkiYoutubeMarketingDataDetailList());
+              }
+              return Result.OK("文件导入成功!数据行数:" + list.size());
+          } catch (Exception e) {
+              log.error(e.getMessage(),e);
+              return Result.error("文件导入失败:"+e.getMessage());
+          } finally {
+              try {
+                  file.getInputStream().close();
+              } catch (IOException e) {
+                  e.printStackTrace();
+              }
+          }
+      }
+      return Result.OK("文件导入失败!");
+    }
+
+	 /**
+	  * 变更状态
+	  * @param okkiYoutubeMarketingData
+	  * @return
+	  */
+	 @PostMapping(value = "/status")
+	 public Result<String> changeStatus(@RequestBody OkkiYoutubeMarketingData okkiYoutubeMarketingData) throws Exception {
+		 boolean result = okkiYoutubeMarketingDataService.changeStatus(okkiYoutubeMarketingData);
+		 if (result) {
+			 return Result.OK("操作成功");
+		 }else {
+			 return Result.error("操作失败");
+		 }
+	 }
+}

+ 58 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/entity/OkkiYoutubeMarketingData.java

@@ -0,0 +1,58 @@
+package org.jeecg.modules.okki.youtube.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.jeecg.common.aspect.annotation.Dict;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Description: Youtube营销效果数据
+ * @Author: jeecg-boot
+ * @Date:   2024-05-16
+ * @Version: V1.0
+ */
+@ApiModel(value="okki_youtube_marketing_data对象", description="Youtube营销效果数据")
+@Data
+@TableName("okki_youtube_marketing_data")
+public class OkkiYoutubeMarketingData implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	/**主键*/
+	@TableId(type = IdType.ASSIGN_ID)
+    @ApiModelProperty(value = "主键")
+    private String id;
+	/**创建人*/
+    @ApiModelProperty(value = "创建人")
+    private String createBy;
+	/**更新人*/
+    @ApiModelProperty(value = "更新人")
+    private String updateBy;
+	/**更新日期*/
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "更新日期")
+    private Date updateTime;
+	/**站点id*/
+	@Excel(name = "站点id", width = 15)
+    @ApiModelProperty(value = "站点id")
+    private String siteId;
+	/**同步状态*/
+	@Excel(name = "同步状态", width = 15, dicCode = "blog_status")
+    @Dict(dicCode = "blog_status")
+    @ApiModelProperty(value = "同步状态")
+    private Integer status;
+	/**创建日期*/
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "创建日期")
+    private Date createTime;
+}

+ 85 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/entity/OkkiYoutubeMarketingDataDetail.java

@@ -0,0 +1,85 @@
+package org.jeecg.modules.okki.youtube.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Description: Youtube营销效果数据详情
+ * @Author: jeecg-boot
+ * @Date:   2024-05-16
+ * @Version: V1.0
+ */
+@ApiModel(value="okki_youtube_marketing_data_detail对象", description="Youtube营销效果数据详情")
+@Data
+@TableName("okki_youtube_marketing_data_detail")
+public class OkkiYoutubeMarketingDataDetail implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	/**主键*/
+	@TableId(type = IdType.ASSIGN_ID)
+    @ApiModelProperty(value = "主键")
+    private String id;
+	/**创建人*/
+    @ApiModelProperty(value = "创建人")
+    private String createBy;
+	/**创建日期*/
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "创建日期")
+    private Date createTime;
+	/**更新人*/
+    @ApiModelProperty(value = "更新人")
+    private String updateBy;
+	/**更新日期*/
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "更新日期")
+    private Date updateTime;
+	/**关联id*/
+    @ApiModelProperty(value = "关联id")
+    private String okkiYoutubeMarketingDataId;
+	/**视频id*/
+	@Excel(name = "视频id", width = 15)
+    @ApiModelProperty(value = "视频id")
+    private String vid;
+	/**视频标题*/
+	@Excel(name = "视频标题", width = 15)
+    @ApiModelProperty(value = "视频标题")
+    private String title;
+	/**视频创建时间*/
+	@Excel(name = "视频创建时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "视频创建时间")
+    private Date addtime;
+	/**视频当月观看次数*/
+	@Excel(name = "视频当月观看次数", width = 15)
+    @ApiModelProperty(value = "视频当月观看次数")
+    private Integer views;
+	/**视频当月总观看时长 (单位:小时)*/
+	@Excel(name = "视频当月总观看时长 (单位:小时)", width = 15)
+    @ApiModelProperty(value = "视频当月总观看时长 (单位:小时)")
+    private Double duration;
+	/**当月订阅量*/
+	@Excel(name = "当月订阅量", width = 15)
+    @ApiModelProperty(value = "当月订阅量")
+    private Integer subscribe;
+	/**当月曝光数量*/
+	@Excel(name = "当月曝光数量", width = 15)
+    @ApiModelProperty(value = "当月曝光数量")
+    private Integer showtimes;
+	/**月份*/
+	@Excel(name = "月份", width = 15)
+    @ApiModelProperty(value = "月份")
+    private String month;
+}

+ 32 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/mapper/OkkiYoutubeMarketingDataDetailMapper.java

@@ -0,0 +1,32 @@
+package org.jeecg.modules.okki.youtube.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.jeecg.modules.okki.youtube.entity.OkkiYoutubeMarketingDataDetail;
+
+import java.util.List;
+
+/**
+ * @Description: Youtube营销效果数据详情
+ * @Author: jeecg-boot
+ * @Date:   2024-05-16
+ * @Version: V1.0
+ */
+public interface OkkiYoutubeMarketingDataDetailMapper extends BaseMapper<OkkiYoutubeMarketingDataDetail> {
+
+	/**
+	 * 通过主表id删除子表数据
+	 *
+	 * @param mainId 主表id
+	 * @return boolean
+	 */
+	public boolean deleteByMainId(@Param("mainId") String mainId);
+
+  /**
+   * 通过主表id查询子表数据
+   *
+   * @param mainId 主表id
+   * @return List<OkkiYoutubeMarketingDataDetail>
+   */
+	public List<OkkiYoutubeMarketingDataDetail> selectByMainId(@Param("mainId") String mainId);
+}

+ 14 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/mapper/OkkiYoutubeMarketingDataMapper.java

@@ -0,0 +1,14 @@
+package org.jeecg.modules.okki.youtube.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.okki.youtube.entity.OkkiYoutubeMarketingData;
+
+/**
+ * @Description: Youtube营销效果数据
+ * @Author: jeecg-boot
+ * @Date:   2024-05-16
+ * @Version: V1.0
+ */
+public interface OkkiYoutubeMarketingDataMapper extends BaseMapper<OkkiYoutubeMarketingData> {
+
+}

+ 16 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/mapper/xml/OkkiYoutubeMarketingDataDetailMapper.xml

@@ -0,0 +1,16 @@
+<?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="org.jeecg.modules.okki.youtube.mapper.OkkiYoutubeMarketingDataDetailMapper">
+
+	<delete id="deleteByMainId" parameterType="java.lang.String">
+		DELETE 
+		FROM  okki_youtube_marketing_data_detail 
+		WHERE
+			 okki_youtube_marketing_data_id = #{mainId} 	</delete>
+	
+	<select id="selectByMainId" parameterType="java.lang.String" resultType="org.jeecg.modules.okki.youtube.entity.OkkiYoutubeMarketingDataDetail">
+		SELECT * 
+		FROM  okki_youtube_marketing_data_detail
+		WHERE
+			 okki_youtube_marketing_data_id = #{mainId} 	</select>
+</mapper>

+ 5 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/mapper/xml/OkkiYoutubeMarketingDataMapper.xml

@@ -0,0 +1,5 @@
+<?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="org.jeecg.modules.okki.youtube.mapper.OkkiYoutubeMarketingDataMapper">
+
+</mapper>

+ 30 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/param/ReportListParam.java

@@ -0,0 +1,30 @@
+package org.jeecg.modules.okki.youtube.param;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+@Data
+public class ReportListParam {
+
+    /**视频id*/
+    private String vid;
+    /**视频标题*/
+    private String title;
+    /**视频创建时间*/
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    private Date addtime;
+    /**视频当月观看次数*/
+    private Integer views;
+    /**视频当月总观看时长 (单位:小时)*/
+    private Double duration;
+    /**当月订阅量*/
+    private Integer subscribe;
+    /**当月曝光数量*/
+    private Integer showtimes;
+    /**月份*/
+    private String month;
+}

+ 13 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/param/YoutubeMarketingDataParam.java

@@ -0,0 +1,13 @@
+package org.jeecg.modules.okki.youtube.param;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class YoutubeMarketingDataParam {
+
+    private List<ReportListParam> report_list;
+
+    private Integer count;
+}

+ 22 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/service/IOkkiYoutubeMarketingDataDetailService.java

@@ -0,0 +1,22 @@
+package org.jeecg.modules.okki.youtube.service;
+
+import org.jeecg.modules.okki.youtube.entity.OkkiYoutubeMarketingDataDetail;
+import com.baomidou.mybatisplus.extension.service.IService;
+import java.util.List;
+
+/**
+ * @Description: Youtube营销效果数据详情
+ * @Author: jeecg-boot
+ * @Date:   2024-05-16
+ * @Version: V1.0
+ */
+public interface IOkkiYoutubeMarketingDataDetailService extends IService<OkkiYoutubeMarketingDataDetail> {
+
+	/**
+	 * 通过主表id查询子表数据
+	 *
+	 * @param mainId 主表id
+	 * @return List<OkkiYoutubeMarketingDataDetail>
+	 */
+	public List<OkkiYoutubeMarketingDataDetail> selectByMainId(String mainId);
+}

+ 49 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/service/IOkkiYoutubeMarketingDataService.java

@@ -0,0 +1,49 @@
+package org.jeecg.modules.okki.youtube.service;
+
+import org.jeecg.modules.okki.youtube.entity.OkkiYoutubeMarketingDataDetail;
+import org.jeecg.modules.okki.youtube.entity.OkkiYoutubeMarketingData;
+import com.baomidou.mybatisplus.extension.service.IService;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @Description: Youtube营销效果数据
+ * @Author: jeecg-boot
+ * @Date:   2024-05-16
+ * @Version: V1.0
+ */
+public interface IOkkiYoutubeMarketingDataService extends IService<OkkiYoutubeMarketingData> {
+
+	/**
+	 * 添加一对多
+	 *
+	 * @param okkiYoutubeMarketingData
+	 * @param okkiYoutubeMarketingDataDetailList
+	 */
+	public void saveMain(OkkiYoutubeMarketingData okkiYoutubeMarketingData,List<OkkiYoutubeMarketingDataDetail> okkiYoutubeMarketingDataDetailList) ;
+	
+	/**
+	 * 修改一对多
+	 *
+	 * @param okkiYoutubeMarketingData
+	 * @param okkiYoutubeMarketingDataDetailList
+	 */
+	public void updateMain(OkkiYoutubeMarketingData okkiYoutubeMarketingData,List<OkkiYoutubeMarketingDataDetail> okkiYoutubeMarketingDataDetailList);
+	
+	/**
+	 * 删除一对多
+	 *
+	 * @param id
+	 */
+	public void delMain (String id);
+	
+	/**
+	 * 批量删除一对多
+	 *
+	 * @param idList
+	 */
+	public void delBatchMain (Collection<? extends Serializable> idList);
+
+	boolean changeStatus(OkkiYoutubeMarketingData okkiYoutubeMarketingData);
+}

+ 27 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/service/impl/OkkiYoutubeMarketingDataDetailServiceImpl.java

@@ -0,0 +1,27 @@
+package org.jeecg.modules.okki.youtube.service.impl;
+
+import org.jeecg.modules.okki.youtube.entity.OkkiYoutubeMarketingDataDetail;
+import org.jeecg.modules.okki.youtube.mapper.OkkiYoutubeMarketingDataDetailMapper;
+import org.jeecg.modules.okki.youtube.service.IOkkiYoutubeMarketingDataDetailService;
+import org.springframework.stereotype.Service;
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * @Description: Youtube营销效果数据详情
+ * @Author: jeecg-boot
+ * @Date:   2024-05-16
+ * @Version: V1.0
+ */
+@Service
+public class OkkiYoutubeMarketingDataDetailServiceImpl extends ServiceImpl<OkkiYoutubeMarketingDataDetailMapper, OkkiYoutubeMarketingDataDetail> implements IOkkiYoutubeMarketingDataDetailService {
+	
+	@Autowired
+	private OkkiYoutubeMarketingDataDetailMapper okkiYoutubeMarketingDataDetailMapper;
+	
+	@Override
+	public List<OkkiYoutubeMarketingDataDetail> selectByMainId(String mainId) {
+		return okkiYoutubeMarketingDataDetailMapper.selectByMainId(mainId);
+	}
+}

+ 144 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/service/impl/OkkiYoutubeMarketingDataServiceImpl.java

@@ -0,0 +1,144 @@
+package org.jeecg.modules.okki.youtube.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.modules.okki.utils.HttpClientUtils;
+import org.jeecg.modules.okki.youtube.entity.OkkiYoutubeMarketingData;
+import org.jeecg.modules.okki.youtube.entity.OkkiYoutubeMarketingDataDetail;
+import org.jeecg.modules.okki.youtube.mapper.OkkiYoutubeMarketingDataDetailMapper;
+import org.jeecg.modules.okki.youtube.mapper.OkkiYoutubeMarketingDataMapper;
+import org.jeecg.modules.okki.youtube.param.ReportListParam;
+import org.jeecg.modules.okki.youtube.param.YoutubeMarketingDataParam;
+import org.jeecg.modules.okki.youtube.service.IOkkiYoutubeMarketingDataService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * @Description: Youtube营销效果数据
+ * @Author: jeecg-boot
+ * @Date:   2024-05-16
+ * @Version: V1.0
+ */
+@Slf4j
+@Service
+public class OkkiYoutubeMarketingDataServiceImpl extends ServiceImpl<OkkiYoutubeMarketingDataMapper, OkkiYoutubeMarketingData> implements IOkkiYoutubeMarketingDataService {
+
+	@Value("${OKKI.BASE_URL}")
+	private String URL;
+
+	@Value("${OKKI.CLIENT_SECRET}")
+	private String CLIENT_SECRET;
+
+
+	@Autowired
+	private OkkiYoutubeMarketingDataMapper okkiYoutubeMarketingDataMapper;
+	@Autowired
+	private OkkiYoutubeMarketingDataDetailMapper okkiYoutubeMarketingDataDetailMapper;
+	
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void saveMain(OkkiYoutubeMarketingData okkiYoutubeMarketingData, List<OkkiYoutubeMarketingDataDetail> okkiYoutubeMarketingDataDetailList) {
+		okkiYoutubeMarketingDataMapper.insert(okkiYoutubeMarketingData);
+		if(okkiYoutubeMarketingDataDetailList!=null && okkiYoutubeMarketingDataDetailList.size()>0) {
+			for(OkkiYoutubeMarketingDataDetail entity:okkiYoutubeMarketingDataDetailList) {
+				//外键设置
+				entity.setOkkiYoutubeMarketingDataId(okkiYoutubeMarketingData.getId());
+				okkiYoutubeMarketingDataDetailMapper.insert(entity);
+			}
+		}
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void updateMain(OkkiYoutubeMarketingData okkiYoutubeMarketingData,List<OkkiYoutubeMarketingDataDetail> okkiYoutubeMarketingDataDetailList) {
+		okkiYoutubeMarketingDataMapper.updateById(okkiYoutubeMarketingData);
+		
+		//1.先删除子表数据
+		okkiYoutubeMarketingDataDetailMapper.deleteByMainId(okkiYoutubeMarketingData.getId());
+		
+		//2.子表数据重新插入
+		if(okkiYoutubeMarketingDataDetailList!=null && okkiYoutubeMarketingDataDetailList.size()>0) {
+			for(OkkiYoutubeMarketingDataDetail entity:okkiYoutubeMarketingDataDetailList) {
+				//外键设置
+				entity.setOkkiYoutubeMarketingDataId(okkiYoutubeMarketingData.getId());
+				okkiYoutubeMarketingDataDetailMapper.insert(entity);
+			}
+		}
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void delMain(String id) {
+		okkiYoutubeMarketingDataDetailMapper.deleteByMainId(id);
+		okkiYoutubeMarketingDataMapper.deleteById(id);
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void delBatchMain(Collection<? extends Serializable> idList) {
+		for(Serializable id:idList) {
+			okkiYoutubeMarketingDataDetailMapper.deleteByMainId(id.toString());
+			okkiYoutubeMarketingDataMapper.deleteById(id);
+		}
+	}
+
+	@Override
+	public boolean changeStatus(OkkiYoutubeMarketingData param) {
+		OkkiYoutubeMarketingData okkiYoutubeMarketingData = okkiYoutubeMarketingDataMapper.selectById(param.getId());
+		// 请求okki平台接口
+		Map<String, String> query = new TreeMap<>();
+		query.put("sign_method", "hmac-md5");
+		query.put("timestamp", String.valueOf(System.currentTimeMillis()));
+		query.put("site_id", String.valueOf(okkiYoutubeMarketingData.getSiteId()));
+		query.put("method", "youtube_report");
+		okkiYoutubeMarketingData.setStatus(1);
+		YoutubeMarketingDataParam youtubeMarketingDataParam = new YoutubeMarketingDataParam();
+		try {
+			String queryStr = HttpClientUtils.buildQueryString(query);
+			List<OkkiYoutubeMarketingDataDetail> okkiYoutubeMarketingDataDetails = okkiYoutubeMarketingDataDetailMapper.selectByMainId(okkiYoutubeMarketingData.getId());
+			ArrayList<ReportListParam> reportListParams = new ArrayList<>();
+			for (OkkiYoutubeMarketingDataDetail okkiYoutubeMarketingDataDetail : okkiYoutubeMarketingDataDetails) {
+				ReportListParam reportListParam = new ReportListParam();
+				reportListParam.setVid(okkiYoutubeMarketingDataDetail.getVid());
+				reportListParam.setTitle(okkiYoutubeMarketingDataDetail.getTitle());
+				reportListParam.setAddtime(okkiYoutubeMarketingDataDetail.getAddtime());
+				reportListParam.setViews(okkiYoutubeMarketingDataDetail.getViews());
+				reportListParam.setDuration(okkiYoutubeMarketingDataDetail.getDuration());
+				reportListParam.setSubscribe(okkiYoutubeMarketingDataDetail.getSubscribe());
+				reportListParam.setShowtimes(okkiYoutubeMarketingDataDetail.getShowtimes());
+				reportListParam.setMonth(okkiYoutubeMarketingDataDetail.getMonth());
+				reportListParams.add(reportListParam);
+			}
+			youtubeMarketingDataParam.setReport_list(reportListParams);
+			youtubeMarketingDataParam.setCount(reportListParams.size());
+			String body = HttpClientUtils.toJsonString(youtubeMarketingDataParam);
+			String signStr = queryStr + body;
+			query.put("signature", HttpClientUtils.generateHmacMD5(signStr, CLIENT_SECRET));
+			String okkiUrl = URL + "?" + HttpClientUtils.buildQueryString(query);
+			log.info("url:" + okkiUrl + ",body:" + body);
+			String res = HttpClientUtils.doPost(okkiUrl, body);
+			log.info(res);
+			// {"code":0,"msg":"success","now":"2024-05-06 15:34:54","data":[]}
+			JSONObject jsonObject= JSONObject.parseObject(res);
+			if (jsonObject.get("code").equals(0)) {
+				int result = okkiYoutubeMarketingDataMapper.updateById(okkiYoutubeMarketingData);
+				if (result == 0) {
+					return false;
+				}else {
+					return true;
+				}
+			}else {
+				throw new RuntimeException(jsonObject.get("msg").toString());
+			}
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+}

+ 59 - 0
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/okki/youtube/vo/OkkiYoutubeMarketingDataPage.java

@@ -0,0 +1,59 @@
+package org.jeecg.modules.okki.youtube.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.jeecg.common.aspect.annotation.Dict;
+import org.jeecg.modules.okki.youtube.entity.OkkiYoutubeMarketingDataDetail;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.jeecgframework.poi.excel.annotation.ExcelCollection;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Description: Youtube营销效果数据
+ * @Author: jeecg-boot
+ * @Date:   2024-05-16
+ * @Version: V1.0
+ */
+@Data
+@ApiModel(value="okki_youtube_marketing_dataPage对象", description="Youtube营销效果数据")
+public class OkkiYoutubeMarketingDataPage {
+
+	/**主键*/
+	@ApiModelProperty(value = "主键")
+    private String id;
+	/**创建人*/
+	@ApiModelProperty(value = "创建人")
+    private String createBy;
+	/**更新人*/
+	@ApiModelProperty(value = "更新人")
+    private String updateBy;
+	/**更新日期*/
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+	@ApiModelProperty(value = "更新日期")
+    private Date updateTime;
+	/**站点id*/
+	@Excel(name = "站点id", width = 15)
+	@ApiModelProperty(value = "站点id")
+    private String siteId;
+	/**同步状态*/
+	@Excel(name = "同步状态", width = 15, dicCode = "blog_status")
+    @Dict(dicCode = "blog_status")
+	@ApiModelProperty(value = "同步状态")
+    private Integer status;
+	/**创建日期*/
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+	@ApiModelProperty(value = "创建日期")
+    private Date createTime;
+	
+	@ExcelCollection(name="Youtube营销效果数据详情")
+	@ApiModelProperty(value = "Youtube营销效果数据详情")
+	private List<OkkiYoutubeMarketingDataDetail> okkiYoutubeMarketingDataDetailList;
+	
+}

+ 77 - 0
jeecgboot-vue3/src/views/okki/youtube/OkkiYoutubeMarketingData.api.ts

@@ -0,0 +1,77 @@
+import {defHttp} from '/@/utils/http/axios';
+import { useMessage } from "/@/hooks/web/useMessage";
+
+const { createConfirm } = useMessage();
+
+enum Api {
+  list = '/youtube/okkiYoutubeMarketingData/list',
+  save='/youtube/okkiYoutubeMarketingData/add',
+  edit='/youtube/okkiYoutubeMarketingData/edit',
+  deleteOne = '/youtube/okkiYoutubeMarketingData/delete',
+  deleteBatch = '/youtube/okkiYoutubeMarketingData/deleteBatch',
+  importExcel = '/youtube/okkiYoutubeMarketingData/importExcel',
+  exportXls = '/youtube/okkiYoutubeMarketingData/exportXls',
+  okkiYoutubeMarketingDataDetailList = '/youtube/okkiYoutubeMarketingData/queryOkkiYoutubeMarketingDataDetailByMainId',
+}
+/**
+ * 导出api
+ * @param params
+ */
+export const getExportUrl = Api.exportXls;
+
+/**
+ * 导入api
+ */
+export const getImportUrl = Api.importExcel;
+/**
+ * 子表单查询接口
+ * @param params
+ */
+export const queryOkkiYoutubeMarketingDataDetail = Api.okkiYoutubeMarketingDataDetailList
+/**
+ * 列表接口
+ * @param params
+ */
+export const list = (params) =>
+  defHttp.get({url: Api.list, params});
+
+/**
+ * 删除单个
+ */
+export const deleteOne = (params,handleSuccess) => {
+  return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
+    handleSuccess();
+  });
+}
+/**
+ * 批量删除
+ * @param params
+ */
+export const batchDelete = (params, handleSuccess) => {
+  createConfirm({
+    iconType: 'warning',
+    title: '确认删除',
+    content: '是否删除选中数据',
+    okText: '确认',
+    cancelText: '取消',
+    onOk: () => {
+      return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
+        handleSuccess();
+      });
+    }
+  });
+}
+/**
+ * 保存或者更新
+ * @param params
+ */
+export const saveOrUpdate = (params, isUpdate) => {
+  let url = isUpdate ? Api.edit : Api.save;
+  return defHttp.post({url: url, params});
+}
+/**
+ * 子表列表接口
+ * @param params
+ */
+export const okkiYoutubeMarketingDataDetailList = (params) =>
+  defHttp.get({url: Api.okkiYoutubeMarketingDataDetailList, params},{isTransformResponse:false});

+ 183 - 0
jeecgboot-vue3/src/views/okki/youtube/OkkiYoutubeMarketingData.data.ts

@@ -0,0 +1,183 @@
+import {BasicColumn} from '/@/components/Table';
+import {FormSchema} from '/@/components/Table';
+import { rules} from '/@/utils/helper/validator';
+import { render } from '/@/utils/common/renderUtils';
+import {JVxeTypes,JVxeColumn} from '/@/components/jeecg/JVxeTable/types'
+//列表数据
+export const columns: BasicColumn[] = [
+   {
+    title: '站点id',
+    align:"center",
+    dataIndex: 'siteId'
+   },
+   {
+    title: '同步状态',
+    align:"center",
+    dataIndex: 'status_dictText'
+   },
+   {
+    title: '创建日期',
+    align:"center",
+    dataIndex: 'createTime'
+   },
+];
+//查询数据
+export const searchFormSchema: FormSchema[] = [
+];
+//表单数据
+export const formSchema: FormSchema[] = [
+  {
+    label: '站点id',
+    field: 'siteId',
+    component: 'Input',
+  },
+	// TODO 主键隐藏字段,目前写死为ID
+	{
+	  label: '',
+	  field: 'id',
+	  component: 'Input',
+	  show: false
+	},
+];
+//子表单数据
+//子表列表数据
+export const okkiYoutubeMarketingDataDetailColumns: BasicColumn[] = [
+   {
+    title: '视频id',
+    align:"center",
+    dataIndex: 'vid'
+   },
+   {
+    title: '视频标题',
+    align:"center",
+    dataIndex: 'title'
+   },
+   {
+    title: '视频创建时间',
+    align:"center",
+    dataIndex: 'addtime'
+   },
+   {
+    title: '视频当月观看次数',
+    align:"center",
+    dataIndex: 'views'
+   },
+   {
+    title: '视频当月总观看时长 (单位:小时)',
+    align:"center",
+    dataIndex: 'duration'
+   },
+   {
+    title: '当月订阅量',
+    align:"center",
+    dataIndex: 'subscribe'
+   },
+   {
+    title: '当月曝光数量',
+    align:"center",
+    dataIndex: 'showtimes'
+   },
+   {
+    title: '月份',
+    align:"center",
+    dataIndex: 'month'
+   },
+];
+//子表表格配置
+export const okkiYoutubeMarketingDataDetailJVxeColumns: JVxeColumn[] = [
+    {
+      title: '视频id',
+      key: 'vid',
+      type: JVxeTypes.input,
+      width:"200px",
+      placeholder: '请输入${title}',
+      defaultValue:'',
+    },
+    {
+      title: '视频标题',
+      key: 'title',
+      type: JVxeTypes.input,
+      width:"200px",
+      placeholder: '请输入${title}',
+      defaultValue:'',
+    },
+    {
+      title: '视频创建时间',
+      key: 'addtime',
+      type: JVxeTypes.datetime,
+      width:"200px",
+      placeholder: '请输入${title}',
+      defaultValue:'',
+    },
+    {
+      title: '视频当月观看次数',
+      key: 'views',
+      type: JVxeTypes.inputNumber,
+      width:"200px",
+      placeholder: '请输入${title}',
+      defaultValue:'',
+    },
+    {
+      title: '视频当月总观看时长 (单位:小时)',
+      key: 'duration',
+      type: JVxeTypes.inputNumber,
+      width:"200px",
+      placeholder: '请输入${title}',
+      defaultValue:'',
+    },
+    {
+      title: '当月订阅量',
+      key: 'subscribe',
+      type: JVxeTypes.inputNumber,
+      width:"200px",
+      placeholder: '请输入${title}',
+      defaultValue:'',
+    },
+    {
+      title: '当月曝光数量',
+      key: 'showtimes',
+      type: JVxeTypes.inputNumber,
+      width:"200px",
+      placeholder: '请输入${title}',
+      defaultValue:'',
+    },
+    {
+      title: '月份',
+      key: 'month',
+      type: JVxeTypes.input,
+      width:"200px",
+      placeholder: '请输入${title}',
+      defaultValue:'',
+    },
+  ]
+
+// 高级查询数据
+export const superQuerySchema = {
+  siteId: {title: '站点id',order: 0,view: 'text', type: 'string',},
+  status: {title: '同步状态',order: 1,view: 'number', type: 'number',},
+  createTime: {title: '创建日期',order: 2,view: 'datetime', type: 'string',},
+  //子表高级查询
+  okkiYoutubeMarketingDataDetail: {
+    title: 'Youtube营销效果数据详情',
+    view: 'table',
+    fields: {
+        vid: {title: '视频id',order: 0,view: 'text', type: 'string',},
+        title: {title: '视频标题',order: 1,view: 'text', type: 'string',},
+        addtime: {title: '视频创建时间',order: 2,view: 'datetime', type: 'string',},
+        views: {title: '视频当月观看次数',order: 3,view: 'number', type: 'number',},
+        duration: {title: '视频当月总观看时长 (单位:小时)',order: 4,view: 'number', type: 'number',},
+        subscribe: {title: '当月订阅量',order: 5,view: 'number', type: 'number',},
+        showtimes: {title: '当月曝光数量',order: 6,view: 'number', type: 'number',},
+        month: {title: '月份',order: 7,view: 'text', type: 'string',},
+    }
+  },
+};
+
+/**
+* 流程表单调用这个方法获取formSchema
+* @param param
+*/
+export function getBpmFormSchema(_formData): FormSchema[]{
+  // 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema
+  return formSchema;
+}

+ 208 - 0
jeecgboot-vue3/src/views/okki/youtube/OkkiYoutubeMarketingDataList.vue

@@ -0,0 +1,208 @@
+<template>
+  <div>
+    <!--引用表格-->
+   <BasicTable @register="registerTable" :rowSelection="rowSelection" :expandedRowKeys="expandedRowKeys"  @expand="handleExpand">
+      <!-- 内嵌table区域 begin -->
+           <template #expandedRowRender="{record}">
+             <a-tabs tabPosition="top">
+               <a-tab-pane tab="Youtube营销效果数据详情" key="okkiYoutubeMarketingDataDetail" forceRender>
+                  <okkiYoutubeMarketingDataDetailSubTable :id="expandedRowKeys[0]"/>
+               </a-tab-pane>
+             </a-tabs>
+           </template>
+     <!-- 内嵌table区域 end -->
+     <!--插槽:table标题-->
+      <template #tableTitle>
+          <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
+          <a-button  type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
+          <j-upload-button  type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
+          <a-dropdown v-if="selectedRowKeys.length > 0">
+              <template #overlay>
+                <a-menu>
+                  <a-menu-item key="1" @click="batchHandleDelete">
+                    <Icon icon="ant-design:delete-outlined"></Icon>
+                    删除
+                  </a-menu-item>
+                </a-menu>
+              </template>
+              <a-button>批量操作
+                <Icon icon="mdi:chevron-down"></Icon>
+              </a-button>
+        </a-dropdown>
+        <!-- 高级查询 -->
+        <super-query :config="superQueryConfig" @search="handleSuperQuery" />
+      </template>
+       <!--操作栏-->
+      <template #action="{ record }">
+        <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
+      </template>
+      <!--字段回显插槽-->
+      <template v-slot:bodyCell="{ column, record, index, text }">
+      </template>
+    </BasicTable>
+    <!-- 表单区域 -->
+    <OkkiYoutubeMarketingDataModal @register="registerModal" @success="handleSuccess"></OkkiYoutubeMarketingDataModal>
+  </div>
+</template>
+
+<script lang="ts" name="youtube-okkiYoutubeMarketingData" setup>
+  import {ref, reactive, computed, unref} from 'vue';
+  import {BasicTable, useTable, TableAction} from '/@/components/Table';
+  import { useListPage } from '/@/hooks/system/useListPage'
+  import {useModal} from '/@/components/Modal';
+  import OkkiYoutubeMarketingDataModal from './components/OkkiYoutubeMarketingDataModal.vue'
+  import OkkiYoutubeMarketingDataDetailSubTable from './subTables/OkkiYoutubeMarketingDataDetailSubTable.vue'
+  import {columns, searchFormSchema, superQuerySchema} from './OkkiYoutubeMarketingData.data';
+  import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './OkkiYoutubeMarketingData.api';
+  import {downloadFile} from '/@/utils/common/renderUtils';
+  import { useUserStore } from '/@/store/modules/user';
+  const queryParam = reactive<any>({});
+   // 展开key
+  const expandedRowKeys = ref<any[]>([]);
+  //注册model
+  const [registerModal, {openModal}] = useModal();
+  const userStore = useUserStore();
+   //注册table数据
+  const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({
+      tableProps:{
+           title: 'Youtube营销效果数据',
+           api: list,
+           columns,
+           canResize:false,
+           formConfig: {
+                //labelWidth: 120,
+                schemas: searchFormSchema,
+                autoSubmitOnEnter:true,
+                showAdvancedButton:true,
+                fieldMapToNumber: [
+                ],
+                fieldMapToTime: [
+                ],
+            },
+           actionColumn: {
+               width: 120,
+               fixed:'right'
+           },
+           beforeFetch: (params) => {
+             return Object.assign(params, queryParam);
+           },
+        },
+        exportConfig: {
+            name:"Youtube营销效果数据",
+            url: getExportUrl,
+            params: queryParam,
+        },
+        importConfig: {
+            url: getImportUrl,
+            success: handleSuccess
+        },
+    })
+
+  const [registerTable, {reload},{ rowSelection, selectedRowKeys }] = tableContext
+
+   // 高级查询配置
+   const superQueryConfig = reactive(superQuerySchema);
+
+   /**
+   * 高级查询事件
+   */
+   function handleSuperQuery(params) {
+     Object.keys(params).map((k) => {
+       queryParam[k] = params[k];
+     });
+     reload();
+   }
+
+   /**
+     * 展开事件
+     * */
+   function handleExpand(expanded, record){
+        expandedRowKeys.value=[];
+        if (expanded === true) {
+           expandedRowKeys.value.push(record.id)
+        }
+    }
+   /**
+    * 新增事件
+    */
+  function handleAdd() {
+     openModal(true, {
+       isUpdate: false,
+       showFooter: true,
+     });
+  }
+   /**
+    * 编辑事件
+    */
+  function handleEdit(record: Recordable) {
+     openModal(true, {
+       record,
+       isUpdate: true,
+       showFooter: true,
+     });
+   }
+   /**
+    * 详情
+   */
+  function handleDetail(record: Recordable) {
+     openModal(true, {
+       record,
+       isUpdate: true,
+       showFooter: false,
+     });
+   }
+   /**
+    * 删除事件
+    */
+  async function handleDelete(record) {
+     await deleteOne({id: record.id}, handleSuccess);
+   }
+   /**
+    * 批量删除事件
+    */
+  async function batchHandleDelete() {
+     await batchDelete({ids: selectedRowKeys.value},handleSuccess);
+   }
+   /**
+    * 成功回调
+    */
+  function handleSuccess() {
+      (selectedRowKeys.value = []) && reload();
+   }
+   /**
+      * 操作栏
+      */
+  function getTableAction(record){
+       return [
+         {
+           label: '编辑',
+           onClick: handleEdit.bind(null, record),
+         }
+       ]
+   }
+
+
+  /**
+   * 下拉操作栏
+   */
+  function getDropDownAction(record){
+    return [
+      {
+        label: '详情',
+        onClick: handleDetail.bind(null, record),
+      }, {
+        label: '删除',
+        popConfirm: {
+          title: '是否确认删除',
+          confirm: handleDelete.bind(null, record),
+          placement: 'topLeft',
+        }
+      }
+    ]
+  }
+
+</script>
+
+<style scoped>
+
+</style>

+ 26 - 0
jeecgboot-vue3/src/views/okki/youtube/V20240516_1__menu_insert_OkkiYoutubeMarketingData.sql

@@ -0,0 +1,26 @@
+-- 注意:该页面对应的前台目录为views/youtube文件夹下
+-- 如果你想更改到其他目录,请修改sql中component字段对应的值
+
+
+INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external) 
+VALUES ('2024051611247440010', NULL, 'Youtube营销效果数据', '/youtube/okkiYoutubeMarketingDataList', 'youtube/OkkiYoutubeMarketingDataList', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2024-05-16 11:24:01', NULL, NULL, 0);
+
+-- 权限控制sql
+-- 新增
+INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
+VALUES ('2024051611247440011', '2024051611247440010', '添加Youtube营销效果数据', NULL, NULL, 0, NULL, NULL, 2, 'youtube:okki_youtube_marketing_data:add', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2024-05-16 11:24:01', NULL, NULL, 0, 0, '1', 0);
+-- 编辑
+INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
+VALUES ('2024051611247440012', '2024051611247440010', '编辑Youtube营销效果数据', NULL, NULL, 0, NULL, NULL, 2, 'youtube:okki_youtube_marketing_data:edit', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2024-05-16 11:24:01', NULL, NULL, 0, 0, '1', 0);
+-- 删除
+INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
+VALUES ('2024051611247440013', '2024051611247440010', '删除Youtube营销效果数据', NULL, NULL, 0, NULL, NULL, 2, 'youtube:okki_youtube_marketing_data:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2024-05-16 11:24:01', NULL, NULL, 0, 0, '1', 0);
+-- 批量删除
+INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
+VALUES ('2024051611247440014', '2024051611247440010', '批量删除Youtube营销效果数据', NULL, NULL, 0, NULL, NULL, 2, 'youtube:okki_youtube_marketing_data:deleteBatch', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2024-05-16 11:24:01', NULL, NULL, 0, 0, '1', 0);
+-- 导出excel
+INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
+VALUES ('2024051611247440015', '2024051611247440010', '导出excel_Youtube营销效果数据', NULL, NULL, 0, NULL, NULL, 2, 'youtube:okki_youtube_marketing_data:exportXls', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2024-05-16 11:24:01', NULL, NULL, 0, 0, '1', 0);
+-- 导入excel
+INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
+VALUES ('2024051611247440016', '2024051611247440010', '导入excel_Youtube营销效果数据', NULL, NULL, 0, NULL, NULL, 2, 'youtube:okki_youtube_marketing_data:importExcel', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2024-05-16 11:24:01', NULL, NULL, 0, 0, '1', 0);

+ 134 - 0
jeecgboot-vue3/src/views/okki/youtube/components/OkkiYoutubeMarketingDataForm.vue

@@ -0,0 +1,134 @@
+<template>
+  <div>
+    <BasicForm @register="registerForm" ref="formRef"/>
+  <!-- 子表单区域 -->
+    <a-tabs v-model:activeKey="activeKey" animated @change="handleChangeTabs">
+      <a-tab-pane tab="Youtube营销效果数据详情" key="okkiYoutubeMarketingDataDetail" :forceRender="true">
+        <JVxeTable
+          v-if="okkiYoutubeMarketingDataDetailTable.show"      
+          keep-source
+          resizable
+          ref="okkiYoutubeMarketingDataDetail"
+          :loading="okkiYoutubeMarketingDataDetailTable.loading"
+          :columns="okkiYoutubeMarketingDataDetailTable.columns"
+          :dataSource="okkiYoutubeMarketingDataDetailTable.dataSource"
+          :height="340"
+          :disabled="formDisabled"
+          :rowNumber="true"
+          :rowSelection="true"
+          :toolbar="true"
+          />
+      </a-tab-pane>
+    </a-tabs>
+    <div style="width: 100%;text-align: center;margin-top: 10px;" v-if="showFlowSubmitButton">
+      <a-button preIcon="ant-design:check-outlined" style="width: 126px" type="primary" @click="handleSubmit">提 交</a-button>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+    import { defHttp } from '/@/utils/http/axios';
+    import {ref, computed, unref,reactive, onMounted, defineProps } from 'vue';
+    import {BasicForm, useForm} from '/@/components/Form/index';
+    import { JVxeTable } from '/@/components/jeecg/JVxeTable'
+    import { useJvxeMethod } from '/@/hooks/system/useJvxeMethods.ts'
+    import {formSchema,okkiYoutubeMarketingDataDetailJVxeColumns} from '../OkkiYoutubeMarketingData.data';
+    import {saveOrUpdate,queryOkkiYoutubeMarketingDataDetail} from '../OkkiYoutubeMarketingData.api';
+    import { VALIDATE_FAILED } from '/@/utils/common/vxeUtils'
+    const isUpdate = ref(true);
+    
+    const refKeys = ref(['okkiYoutubeMarketingDataDetail', ]);
+    const activeKey = ref('okkiYoutubeMarketingDataDetail');
+    const okkiYoutubeMarketingDataDetail = ref();
+    const tableRefs = {okkiYoutubeMarketingDataDetail, };
+    const okkiYoutubeMarketingDataDetailTable = reactive({
+          loading: false,
+          dataSource: [],
+          columns:okkiYoutubeMarketingDataDetailJVxeColumns,
+          show: false
+    })
+
+    const props = defineProps({
+      formData: { type: Object, default: ()=>{} },
+      formBpm: { type: Boolean, default: true }
+    });
+    const formDisabled = computed(()=>{
+      if(props.formBpm === true){
+        if(props.formData.disabled === false){
+          return false;
+        }
+      }
+      return true;
+    });
+    // 是否显示提交按钮
+    const showFlowSubmitButton = computed(()=>{
+      if(props.formBpm === true){
+        if(props.formData.disabled === false){
+          return true
+        }
+      }
+      return false
+    });
+    
+    //表单配置
+    const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
+        labelWidth: 150,
+        schemas: formSchema,
+        showActionButtonGroup: false,
+        baseColProps: {span: 24}
+    });
+
+    onMounted(()=>{
+      initFormData();
+    });
+    //渲染流程表单数据
+    const queryByIdUrl = '/youtube/okkiYoutubeMarketingData/queryById';
+    async function initFormData(){
+      if(props.formBpm === true){
+        await reset();
+        let params = {id: props.formData.dataId};
+        const data = await defHttp.get({url: queryByIdUrl, params});
+        //表单赋值
+        await setFieldsValue({
+          ...data
+        });
+        requestSubTableData(queryOkkiYoutubeMarketingDataDetail, {id: data.id}, okkiYoutubeMarketingDataDetailTable, ()=>{
+          okkiYoutubeMarketingDataDetailTable.show = true;
+        });
+        // 隐藏底部时禁用整个表单
+        setProps({ disabled: formDisabled.value })
+      }
+    }
+    
+    //方法配置
+    const [handleChangeTabs,handleSubmit,requestSubTableData,formRef] = useJvxeMethod(requestAddOrEdit,classifyIntoFormData,tableRefs,activeKey,refKeys);
+
+    async function reset(){
+      await resetFields();
+      activeKey.value = 'okkiYoutubeMarketingDataDetail';
+      okkiYoutubeMarketingDataDetailTable.dataSource = [];
+    }
+    function classifyIntoFormData(allValues) {
+         let main = Object.assign({}, allValues.formValue)
+         return {
+           ...main, // 展开
+           okkiYoutubeMarketingDataDetailList: allValues.tablesValue[0].tableData,
+         }
+       }
+    //表单提交事件
+    async function requestAddOrEdit(values) {
+      //提交表单
+      await saveOrUpdate(values, true);
+    }
+</script>
+
+<style lang="less" scoped>
+	/** 时间和数字输入框样式 */
+    :deep(.ant-input-number){
+		width: 100%
+	}
+
+	:deep(.ant-calendar-picker){
+		width: 100%
+	}
+</style>

+ 114 - 0
jeecgboot-vue3/src/views/okki/youtube/components/OkkiYoutubeMarketingDataModal.vue

@@ -0,0 +1,114 @@
+<template>
+  <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="800" @ok="handleSubmit">
+      <BasicForm @register="registerForm" ref="formRef"/>
+  <!-- 子表单区域 -->
+    <a-tabs v-model:activeKey="activeKey" animated @change="handleChangeTabs">
+      <a-tab-pane tab="Youtube营销效果数据详情" key="okkiYoutubeMarketingDataDetail" :forceRender="true">
+        <JVxeTable
+          keep-source
+          resizable
+          ref="okkiYoutubeMarketingDataDetail"
+          :loading="okkiYoutubeMarketingDataDetailTable.loading"
+          :columns="okkiYoutubeMarketingDataDetailTable.columns"
+          :dataSource="okkiYoutubeMarketingDataDetailTable.dataSource"
+          :height="340"
+          :disabled="formDisabled"
+          :rowNumber="true"
+          :rowSelection="true"
+          :toolbar="true"
+          />
+      </a-tab-pane>
+    </a-tabs>
+  </BasicModal>
+</template>
+
+<script lang="ts" setup>
+    import {ref, computed, unref,reactive} from 'vue';
+    import {BasicModal, useModalInner} from '/@/components/Modal';
+    import {BasicForm, useForm} from '/@/components/Form/index';
+    import { JVxeTable } from '/@/components/jeecg/JVxeTable'
+    import { useJvxeMethod } from '/@/hooks/system/useJvxeMethods.ts'
+    import {formSchema,okkiYoutubeMarketingDataDetailJVxeColumns} from '../OkkiYoutubeMarketingData.data';
+    import {saveOrUpdate,queryOkkiYoutubeMarketingDataDetail} from '../OkkiYoutubeMarketingData.api';
+    import { VALIDATE_FAILED } from '/@/utils/common/vxeUtils'
+    // Emits声明
+    const emit = defineEmits(['register','success']);
+    const isUpdate = ref(true);
+    const formDisabled = ref(false);
+    const refKeys = ref(['okkiYoutubeMarketingDataDetail', ]);
+    const activeKey = ref('okkiYoutubeMarketingDataDetail');
+    const okkiYoutubeMarketingDataDetail = ref();
+    const tableRefs = {okkiYoutubeMarketingDataDetail, };
+    const okkiYoutubeMarketingDataDetailTable = reactive({
+          loading: false,
+          dataSource: [],
+          columns:okkiYoutubeMarketingDataDetailJVxeColumns
+    })
+    //表单配置
+    const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
+        //labelWidth: 150,
+        schemas: formSchema,
+        showActionButtonGroup: false,
+        baseColProps: {span: 24}
+    });
+     //表单赋值
+    const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
+        //重置表单
+        await reset();
+        setModalProps({confirmLoading: false,showCancelBtn:data?.showFooter,showOkBtn:data?.showFooter});
+        isUpdate.value = !!data?.isUpdate;
+        formDisabled.value = !data?.showFooter;
+        if (unref(isUpdate)) {
+            //表单赋值
+            await setFieldsValue({
+                ...data.record,
+            });
+             requestSubTableData(queryOkkiYoutubeMarketingDataDetail, {id:data?.record?.id}, okkiYoutubeMarketingDataDetailTable)
+        }
+        // 隐藏底部时禁用整个表单
+       setProps({ disabled: !data?.showFooter })
+    });
+    //方法配置
+    const [handleChangeTabs,handleSubmit,requestSubTableData,formRef] = useJvxeMethod(requestAddOrEdit,classifyIntoFormData,tableRefs,activeKey,refKeys);
+
+    //设置标题
+    const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
+
+    async function reset(){
+      await resetFields();
+      activeKey.value = 'okkiYoutubeMarketingDataDetail';
+      okkiYoutubeMarketingDataDetailTable.dataSource = [];
+    }
+    function classifyIntoFormData(allValues) {
+         let main = Object.assign({}, allValues.formValue)
+         return {
+           ...main, // 展开
+           okkiYoutubeMarketingDataDetailList: allValues.tablesValue[0].tableData,
+         }
+       }
+    //表单提交事件
+    async function requestAddOrEdit(values) {
+        try {
+            setModalProps({confirmLoading: true});
+            //提交表单
+            await saveOrUpdate(values, isUpdate.value);
+            //关闭弹窗
+            closeModal();
+            //刷新列表
+            emit('success');
+        } finally {
+            setModalProps({confirmLoading: false});
+        }
+    }
+</script>
+
+<style lang="less" scoped>
+	/** 时间和数字输入框样式 */
+    :deep(.ant-input-number){
+		width: 100%
+	}
+
+	:deep(.ant-calendar-picker){
+		width: 100%
+	}
+</style>

+ 44 - 0
jeecgboot-vue3/src/views/okki/youtube/subTables/OkkiYoutubeMarketingDataDetailSubTable.vue

@@ -0,0 +1,44 @@
+<template>
+  <div>
+      <!--引用表格-->
+     <BasicTable bordered size="middle" :loading="loading" rowKey="id" :canResize="false" :columns="okkiYoutubeMarketingDataDetailColumns" :dataSource="dataSource" :pagination="false">
+        <!--字段回显插槽-->
+        <template v-slot:bodyCell="{ column, record, index, text }">
+        </template>
+      </BasicTable>
+    </div>
+</template>
+
+<script lang="ts" setup>
+  import {ref,watchEffect} from 'vue';
+  import {BasicTable} from '/@/components/Table';
+  import {okkiYoutubeMarketingDataDetailColumns} from '../OkkiYoutubeMarketingData.data';
+  import {okkiYoutubeMarketingDataDetailList} from '../OkkiYoutubeMarketingData.api';
+  import { downloadFile } from '/@/utils/common/renderUtils';
+
+  const props = defineProps({
+    id: {
+       type: String,
+       default: '',
+     },
+  })
+
+  const loading = ref(false);
+  const dataSource = ref([]);
+
+  watchEffect(() => {
+      props.id && loadData(props.id);
+   });
+
+   function loadData(id) {
+         dataSource.value = []
+         loading.value = true
+          okkiYoutubeMarketingDataDetailList({id}).then((res) => {
+           if (res.success) {
+              dataSource.value = res.result.records
+           }
+         }).finally(() => {
+           loading.value = false
+         })
+    }
+</script>