Browse Source

[fix]
1、增加发布游记的接口

chenchen 4 months ago
parent
commit
4d3e283182
25 changed files with 1754 additions and 46 deletions
  1. 0 25
      application-webadmin/src/main/java/com/tourism/webadmin/app/website/controller/JobRecordController.java
  2. 1 1
      application-webadmin/src/main/java/com/tourism/webadmin/app/website/service/JobRecordService.java
  3. 1 4
      application-webadmin/src/main/java/com/tourism/webadmin/app/website/service/impl/JobRecordServiceImpl.java
  4. 1 1
      application-webadmin/src/main/java/com/tourism/webadmin/app/website/service/impl/TourismProjectToWebServiceImpl.java
  5. 27 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/controller/ExtraController.java
  6. 307 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/controller/TourismProjectTravelNotesWriteController.java
  7. 179 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/controller/TourismTravelNotesContentWriteController.java
  8. 33 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/dao/TourismProjectTravelNotesWriteMapper.java
  9. 127 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/dao/mapper/TourismProjectTravelNotesWriteMapper.xml
  10. 60 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/dao/mapper/TourismTravelNotesContentWriteMapper.xml
  11. 4 1
      application-webadmin/src/main/java/com/tourism/webadmin/back/dto/TourBookInfoDto.java
  12. 142 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/dto/TourismProjectTravelNotesWriteDto.java
  13. 39 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/dto/TourismTravelNotesContentWriteDto.java
  14. 14 7
      application-webadmin/src/main/java/com/tourism/webadmin/back/model/TourBookInfo.java
  15. 159 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/model/TourismProjectTravelNotesWrite.java
  16. 43 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/model/TourismTravelNotesContentWrite.java
  17. 49 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/model/constant/AuditState.java
  18. 44 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/model/constant/IsComplete.java
  19. 68 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/service/TourismProjectTravelNotesWriteService.java
  20. 76 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/service/TourismTravelNotesContentWriteService.java
  21. 114 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/service/impl/TourismProjectTravelNotesWriteServiceImpl.java
  22. 106 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/service/impl/TourismTravelNotesContentWriteServiceImpl.java
  23. 13 7
      application-webadmin/src/main/java/com/tourism/webadmin/back/vo/TourBookInfoVo.java
  24. 111 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/vo/TourismProjectTravelNotesWriteVo.java
  25. 36 0
      application-webadmin/src/main/java/com/tourism/webadmin/back/vo/TourismTravelNotesContentWriteVo.java

+ 0 - 25
application-webadmin/src/main/java/com/tourism/webadmin/app/website/controller/JobRecordController.java

@@ -1,47 +1,22 @@
 package com.tourism.webadmin.app.website.controller;
 
-import cn.dev33.satoken.annotation.SaIgnore;
-import cn.hutool.db.Page;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.github.pagehelper.page.PageMethod;
-import com.tourism.common.additional.utils.MapConvertUtils;
 import com.tourism.common.core.constant.ErrorCodeEnum;
-import com.tourism.common.core.object.MyOrderParam;
 import com.tourism.common.core.object.MyPageData;
 import com.tourism.common.core.object.ResponseResult;
 import com.tourism.common.core.object.TokenData;
-import com.tourism.common.core.util.MyPageUtil;
-import com.tourism.common.log.annotation.OperationLog;
-import com.tourism.common.log.model.constant.SysOperationLogType;
 import com.tourism.webadmin.app.website.dto.PageDto;
-import com.tourism.webadmin.app.website.service.BasicToWebService;
 import com.tourism.webadmin.app.website.service.JobRecordService;
-import com.tourism.webadmin.back.model.JobProject;
-import com.tourism.webadmin.back.model.TourBookInfo;
-import com.tourism.webadmin.back.model.TourCountryCode;
 import com.tourism.webadmin.back.model.TourUser;
-import com.tourism.webadmin.back.service.JobProjectService;
-import com.tourism.webadmin.back.service.TourBookInfoService;
 import com.tourism.webadmin.back.service.TourUserService;
-import com.tourism.webadmin.back.vo.BannerInfoVo;
-import com.tourism.webadmin.back.vo.DirectoryInfoVo;
 import com.tourism.webadmin.back.vo.TourBookInfoVo;
 import io.swagger.v3.oas.annotations.tags.Tag;
-import jakarta.validation.constraints.NotNull;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.util.CollectionUtils;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
 @Tag(name = "劳务记录接口")
 @Slf4j
 @RestController

+ 1 - 1
application-webadmin/src/main/java/com/tourism/webadmin/app/website/service/JobRecordService.java

@@ -10,5 +10,5 @@ import com.tourism.webadmin.back.vo.TourBookInfoVo;
  * @author tourism
  */
 public interface JobRecordService {
-    MyPageData<TourBookInfoVo> jobRecordList(String mobile,PageDto pageDto);
+    MyPageData<TourBookInfoVo> jobRecordList(String mobile, PageDto pageDto);
 }

+ 1 - 4
application-webadmin/src/main/java/com/tourism/webadmin/app/website/service/impl/JobRecordServiceImpl.java

@@ -1,7 +1,6 @@
 package com.tourism.webadmin.app.website.service.impl;
 
 import com.github.pagehelper.page.PageMethod;
-import com.tourism.common.additional.utils.MapConvertUtils;
 import com.tourism.common.core.object.MyOrderParam;
 import com.tourism.common.core.object.MyPageData;
 import com.tourism.common.core.util.MyModelUtil;
@@ -12,7 +11,6 @@ import com.tourism.webadmin.back.model.JobProject;
 import com.tourism.webadmin.back.model.TourBookInfo;
 import com.tourism.webadmin.back.service.JobProjectService;
 import com.tourism.webadmin.back.service.TourBookInfoService;
-import com.tourism.webadmin.back.service.TourUserService;
 import com.tourism.webadmin.back.vo.JobProjectVo;
 import com.tourism.webadmin.back.vo.TourBookInfoVo;
 import lombok.extern.slf4j.Slf4j;
@@ -21,7 +19,6 @@ import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
 import java.util.List;
-import java.util.Map;
 
 @Slf4j
 @Service("JobRecordService")
@@ -31,7 +28,7 @@ public class JobRecordServiceImpl implements JobRecordService {
     @Autowired
     private JobProjectService jobProjectService;
 
-    public MyPageData<TourBookInfoVo> jobRecordList(String mobile,PageDto pageDto){
+    public MyPageData<TourBookInfoVo> jobRecordList(String mobile, PageDto pageDto){
 
         TourBookInfo tourBookInfo = new TourBookInfo();
         tourBookInfo.setBookMobile(mobile);

+ 1 - 1
application-webadmin/src/main/java/com/tourism/webadmin/app/website/service/impl/TourismProjectToWebServiceImpl.java

@@ -224,7 +224,7 @@ public class TourismProjectToWebServiceImpl implements TourismProjectToWebServic
         //构建预定的数据进行保存
         TourBookInfo tourBookInfo = new TourBookInfo();
         tourBookInfo.setType(tourBookInfoDto.getType());
-        tourBookInfo.setProjectId(tourBookInfoDto.getProjectId());
+        tourBookInfo.setProjectId(Long.parseLong(tourBookInfoDto.getProjectId()));
         tourBookInfo.setAdultNumber(tourBookInfoDto.getAdultNumber());
         tourBookInfo.setChildrenNumber(tourBookInfoDto.getChildrenNumber());
         tourBookInfo.setAdultPrice(tourismDatePriceOne.getAdultPrice());

+ 27 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/controller/ExtraController.java

@@ -10,14 +10,18 @@ import com.tourism.common.core.util.MyModelUtil;
 import com.tourism.webadmin.app.website.dto.DatePriceSaveDto;
 import com.tourism.webadmin.app.website.vo.DateRangePriceVo;
 import com.tourism.webadmin.app.website.vo.DateRangesPriceVo;
+import com.tourism.webadmin.back.dto.TourBookInfoDto;
 import com.tourism.webadmin.back.dto.TourTourismProjectTravelNotesDto;
 import com.tourism.webadmin.back.dto.TourismProjectDto;
+import com.tourism.webadmin.back.model.TourBookInfo;
 import com.tourism.webadmin.back.model.TourTourismProjectTravelNotes;
 import com.tourism.webadmin.back.model.TourismDatePrice;
 import com.tourism.webadmin.back.model.TourismProject;
+import com.tourism.webadmin.back.service.TourBookInfoService;
 import com.tourism.webadmin.back.service.TourTourismProjectTravelNotesService;
 import com.tourism.webadmin.back.service.TourismDatePriceService;
 import com.tourism.webadmin.back.service.TourismProjectService;
+import com.tourism.webadmin.back.vo.TourBookInfoVo;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
@@ -51,6 +55,8 @@ public class ExtraController {
     private TourismProjectService tourismProjectService;
     @Autowired
     private TourTourismProjectTravelNotesService tourTourismProjectTravelNotesService;
+    @Autowired
+    private TourBookInfoService tourBookInfoService;
     /**
      * 查看指定旅游项目的日历价格。
      *
@@ -292,4 +298,25 @@ public class ExtraController {
         return ResponseResult.success();
     }
 
+
+    /**
+     * 查看指定门户预定管理对象详情。
+     *
+     * @param tourBookInfoDtoFilter 过滤对象。
+     * @return 应答结果对象,包含对象详情。
+     */
+    @SaCheckPermission("tourBookInfo.view")
+    @GetMapping("/isHandleChange")
+    public ResponseResult<Void> isHandleChange(@MyRequestBody TourBookInfoDto tourBookInfoDtoFilter) {
+        TourBookInfo tourBookInfo = tourBookInfoService.getById(tourBookInfoDtoFilter.getId());
+        if(tourBookInfo == null){
+            return ResponseResult.error(ErrorCodeEnum.PROJECT_NOT_EXIST);
+        }
+        TourBookInfo tourBookInfo1 =
+                MyModelUtil.copyTo(tourBookInfo, TourBookInfo.class);
+        tourBookInfo1.setIsHandle(tourBookInfoDtoFilter.getIsHandle());
+        tourBookInfoService.update(tourBookInfo1,tourBookInfo);
+        return ResponseResult.success();
+    }
+
 }

+ 307 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/controller/TourismProjectTravelNotesWriteController.java

@@ -0,0 +1,307 @@
+package com.tourism.webadmin.back.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.annotation.SaIgnore;
+import cn.hutool.core.util.ReflectUtil;
+import com.tourism.common.core.upload.BaseUpDownloader;
+import com.tourism.common.core.upload.UpDownloaderFactory;
+import com.tourism.common.core.upload.UploadResponseInfo;
+import com.tourism.common.core.upload.UploadStoreInfo;
+import com.tourism.common.log.annotation.OperationLog;
+import com.tourism.common.log.model.constant.SysOperationLogType;
+import com.github.pagehelper.page.PageMethod;
+import com.tourism.webadmin.back.vo.*;
+import com.tourism.webadmin.back.dto.*;
+import com.tourism.webadmin.back.model.*;
+import com.tourism.webadmin.back.service.*;
+import com.tourism.common.core.object.*;
+import com.tourism.common.core.util.*;
+import com.tourism.common.core.constant.*;
+import com.tourism.common.core.annotation.MyRequestBody;
+import com.tourism.common.redis.cache.SessionCacheHelper;
+import com.tourism.common.additional.config.ApplicationConfig;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * 发布游记操作控制器类。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+@Tag(name = "发布游记管理接口")
+@Slf4j
+@RestController
+@RequestMapping("/admin/app/tourismProjectTravelNotesWrite")
+public class TourismProjectTravelNotesWriteController {
+
+    @Autowired
+    private ApplicationConfig appConfig;
+    @Autowired
+    private SessionCacheHelper cacheHelper;
+    @Autowired
+    private UpDownloaderFactory upDownloaderFactory;
+    @Autowired
+    private TourismProjectTravelNotesWriteService tourismProjectTravelNotesWriteService;
+
+    /**
+     * 新增发布游记数据。
+     *
+     * @param tourismProjectTravelNotesWriteDto 新增对象。
+     * @return 应答结果对象,包含新增对象主键Id。
+     */
+    @ApiOperationSupport(ignoreParameters = {
+            "tourismProjectTravelNotesWriteDto.id",
+            "tourismProjectTravelNotesWriteDto.searchString",
+            "tourismProjectTravelNotesWriteDto.departureTimeStart",
+            "tourismProjectTravelNotesWriteDto.departureTimeEnd",
+            "tourismProjectTravelNotesWriteDto.createTimeStart",
+            "tourismProjectTravelNotesWriteDto.createTimeEnd"})
+    @SaCheckPermission("tourismProjectTravelNotesWrite.add")
+    @OperationLog(type = SysOperationLogType.ADD)
+    @PostMapping("/add")
+    public ResponseResult<Long> add(@MyRequestBody TourismProjectTravelNotesWriteDto tourismProjectTravelNotesWriteDto) {
+        String errorMessage = MyCommonUtil.getModelValidationError(tourismProjectTravelNotesWriteDto, false);
+        if (errorMessage != null) {
+            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
+        }
+        TourismProjectTravelNotesWrite tourismProjectTravelNotesWrite = MyModelUtil.copyTo(tourismProjectTravelNotesWriteDto, TourismProjectTravelNotesWrite.class);
+        tourismProjectTravelNotesWrite = tourismProjectTravelNotesWriteService.saveNew(tourismProjectTravelNotesWrite);
+        return ResponseResult.success(tourismProjectTravelNotesWrite.getId());
+    }
+
+    /**
+     * 更新发布游记数据。
+     *
+     * @param tourismProjectTravelNotesWriteDto 更新对象。
+     * @return 应答结果对象。
+     */
+    @ApiOperationSupport(ignoreParameters = {
+            "tourismProjectTravelNotesWriteDto.searchString",
+            "tourismProjectTravelNotesWriteDto.departureTimeStart",
+            "tourismProjectTravelNotesWriteDto.departureTimeEnd",
+            "tourismProjectTravelNotesWriteDto.createTimeStart",
+            "tourismProjectTravelNotesWriteDto.createTimeEnd"})
+    @SaCheckPermission("tourismProjectTravelNotesWrite.update")
+    @OperationLog(type = SysOperationLogType.UPDATE)
+    @PostMapping("/update")
+    public ResponseResult<Void> update(@MyRequestBody TourismProjectTravelNotesWriteDto tourismProjectTravelNotesWriteDto) {
+        String errorMessage = MyCommonUtil.getModelValidationError(tourismProjectTravelNotesWriteDto, true);
+        if (errorMessage != null) {
+            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
+        }
+        TourismProjectTravelNotesWrite tourismProjectTravelNotesWrite = MyModelUtil.copyTo(tourismProjectTravelNotesWriteDto, TourismProjectTravelNotesWrite.class);
+        TourismProjectTravelNotesWrite originalTourismProjectTravelNotesWrite = tourismProjectTravelNotesWriteService.getById(tourismProjectTravelNotesWrite.getId());
+        if (originalTourismProjectTravelNotesWrite == null) {
+            // NOTE: 修改下面方括号中的话述
+            errorMessage = "数据验证失败,当前 [数据] 并不存在,请刷新后重试!";
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
+        }
+        if (!tourismProjectTravelNotesWriteService.update(tourismProjectTravelNotesWrite, originalTourismProjectTravelNotesWrite)) {
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
+        }
+        return ResponseResult.success();
+    }
+
+    /**
+     * 删除发布游记数据。
+     *
+     * @param id 删除对象主键Id。
+     * @return 应答结果对象。
+     */
+    @SaCheckPermission("tourismProjectTravelNotesWrite.delete")
+    @OperationLog(type = SysOperationLogType.DELETE)
+    @PostMapping("/delete")
+    public ResponseResult<Void> delete(@MyRequestBody Long id) {
+        if (MyCommonUtil.existBlankArgument(id)) {
+            return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
+        }
+        return this.doDelete(id);
+    }
+
+    /**
+     * 批量删除发布游记数据。
+     *
+     * @param idList 待删除对象的主键Id列表。
+     * @return 应答结果对象。
+     */
+    @SaCheckPermission("tourismProjectTravelNotesWrite.delete")
+    @OperationLog(type = SysOperationLogType.DELETE_BATCH)
+    @PostMapping("/deleteBatch")
+    public ResponseResult<Void> deleteBatch(@MyRequestBody List<Long> idList) {
+        if (MyCommonUtil.existBlankArgument(idList)) {
+            return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
+        }
+        for (Long id : idList) {
+            ResponseResult<Void> responseResult = this.doDelete(id);
+            if (!responseResult.isSuccess()) {
+                return responseResult;
+            }
+        }
+        return ResponseResult.success();
+    }
+
+    /**
+     * 列出符合过滤条件的发布游记列表。
+     *
+     * @param tourismProjectTravelNotesWriteDtoFilter 过滤对象。
+     * @param orderParam 排序参数。
+     * @param pageParam 分页参数。
+     * @return 应答结果对象,包含查询结果集。
+     */
+    @SaCheckPermission("tourismProjectTravelNotesWrite.view")
+    @PostMapping("/list")
+    public ResponseResult<MyPageData<TourismProjectTravelNotesWriteVo>> list(
+            @MyRequestBody TourismProjectTravelNotesWriteDto tourismProjectTravelNotesWriteDtoFilter,
+            @MyRequestBody MyOrderParam orderParam,
+            @MyRequestBody MyPageParam pageParam) {
+        if (pageParam != null) {
+            PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize(), pageParam.getCount());
+        }
+        TourismProjectTravelNotesWrite tourismProjectTravelNotesWriteFilter = MyModelUtil.copyTo(tourismProjectTravelNotesWriteDtoFilter, TourismProjectTravelNotesWrite.class);
+        String orderBy = MyOrderParam.buildOrderBy(orderParam, TourismProjectTravelNotesWrite.class);
+        List<TourismProjectTravelNotesWrite> tourismProjectTravelNotesWriteList =
+                tourismProjectTravelNotesWriteService.getTourismProjectTravelNotesWriteListWithRelation(tourismProjectTravelNotesWriteFilter, orderBy);
+        return ResponseResult.success(MyPageUtil.makeResponseData(tourismProjectTravelNotesWriteList, TourismProjectTravelNotesWriteVo.class));
+    }
+
+    /**
+     * 查看指定发布游记对象详情。
+     *
+     * @param id 指定对象主键Id。
+     * @return 应答结果对象,包含对象详情。
+     */
+    @SaCheckPermission("tourismProjectTravelNotesWrite.view")
+    @GetMapping("/view")
+    public ResponseResult<TourismProjectTravelNotesWriteVo> view(@RequestParam Long id) {
+        TourismProjectTravelNotesWrite tourismProjectTravelNotesWrite = tourismProjectTravelNotesWriteService.getByIdWithRelation(id, MyRelationParam.full());
+        if (tourismProjectTravelNotesWrite == null) {
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
+        }
+        TourismProjectTravelNotesWriteVo tourismProjectTravelNotesWriteVo = MyModelUtil.copyTo(tourismProjectTravelNotesWrite, TourismProjectTravelNotesWriteVo.class);
+        return ResponseResult.success(tourismProjectTravelNotesWriteVo);
+    }
+
+    /**
+     * 附件文件下载。
+     * 这里将图片和其他类型的附件文件放到不同的父目录下,主要为了便于今后图片文件的迁移。
+     *
+     * @param id 附件所在记录的主键Id。
+     * @param fieldName 附件所属的字段名。
+     * @param filename  文件名。如果没有提供该参数,就从当前记录的指定字段中读取。
+     * @param asImage   下载文件是否为图片。
+     * @param response  Http 应答对象。
+     */
+//    @SaCheckPermission("tourismProjectTravelNotesWrite.view")
+    @SaIgnore
+    @OperationLog(type = SysOperationLogType.DOWNLOAD, saveResponse = false)
+    @GetMapping("/download")
+    public void download(
+            @RequestParam(required = false) Long id,
+            @RequestParam String fieldName,
+            @RequestParam String filename,
+            @RequestParam Boolean asImage,
+            HttpServletResponse response) {
+        if (MyCommonUtil.existBlankArgument(fieldName, filename, asImage)) {
+            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+            return;
+        }
+        // 使用try来捕获异常,是为了保证一旦出现异常可以返回500的错误状态,便于调试。
+        // 否则有可能给前端返回的是200的错误码。
+        try {
+            // 如果请求参数中没有包含主键Id,就判断该文件是否为当前session上传的。
+            if (id == null) {
+                if (!cacheHelper.existSessionUploadFile(filename)) {
+                    ResponseResult.output(HttpServletResponse.SC_FORBIDDEN);
+                    return;
+                }
+            } else {
+                TourismProjectTravelNotesWrite tourismProjectTravelNotesWrite = tourismProjectTravelNotesWriteService.getById(id);
+                if (tourismProjectTravelNotesWrite == null) {
+                    ResponseResult.output(HttpServletResponse.SC_NOT_FOUND);
+                    return;
+                }
+                String fieldJsonData = (String) ReflectUtil.getFieldValue(tourismProjectTravelNotesWrite, fieldName);
+                if (fieldJsonData == null && !cacheHelper.existSessionUploadFile(filename)) {
+                    ResponseResult.output(HttpServletResponse.SC_BAD_REQUEST);
+                    return;
+                }
+                if (!BaseUpDownloader.containFile(fieldJsonData, filename)
+                        && !cacheHelper.existSessionUploadFile(filename)) {
+                    ResponseResult.output(HttpServletResponse.SC_FORBIDDEN);
+                    return;
+                }
+            }
+            UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(TourismProjectTravelNotesWrite.class, fieldName);
+            if (!storeInfo.isSupportUpload()) {
+                ResponseResult.output(HttpServletResponse.SC_NOT_IMPLEMENTED,
+                        ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD));
+                return;
+            }
+            BaseUpDownloader upDownloader = upDownloaderFactory.get(storeInfo.getStoreType());
+            upDownloader.doDownload(appConfig.getUploadFileBaseDir(),
+                    TourismProjectTravelNotesWrite.class.getSimpleName(), fieldName, filename, asImage, response);
+        } catch (Exception e) {
+            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            log.error(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 文件上传操作。
+     *
+     * @param fieldName  上传文件名。
+     * @param asImage    是否作为图片上传。如果是图片,今后下载的时候无需权限验证。否则就是附件上传,下载时需要权限验证。
+     * @param uploadFile 上传文件对象。
+     */
+//    @SaCheckPermission("tourismProjectTravelNotesWrite.view")
+    @OperationLog(type = SysOperationLogType.UPLOAD, saveResponse = false)
+    @PostMapping("/upload")
+    public void upload(
+            @RequestParam String fieldName,
+            @RequestParam Boolean asImage,
+            @RequestParam("uploadFile") MultipartFile uploadFile) throws IOException {
+        UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(TourismProjectTravelNotesWrite.class, fieldName);
+        // 这里就会判断参数中指定的字段,是否支持上传操作。
+        if (!storeInfo.isSupportUpload()) {
+            ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
+                    ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD));
+            return;
+        }
+        // 根据字段注解中的存储类型,通过工厂方法获取匹配的上传下载实现类,从而解耦。
+        BaseUpDownloader upDownloader = upDownloaderFactory.get(storeInfo.getStoreType());
+        UploadResponseInfo responseInfo = upDownloader.doUpload(null,
+                appConfig.getUploadFileBaseDir(), TourismProjectTravelNotesWrite.class.getSimpleName(), fieldName, asImage, uploadFile);
+        if (Boolean.TRUE.equals(responseInfo.getUploadFailed())) {
+            ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
+                    ResponseResult.error(ErrorCodeEnum.UPLOAD_FAILED, responseInfo.getErrorMessage()));
+            return;
+        }
+        cacheHelper.putSessionUploadFile(responseInfo.getFilename());
+        ResponseResult.output(ResponseResult.success(responseInfo));
+    }
+
+    private ResponseResult<Void> doDelete(Long id) {
+        String errorMessage;
+        // 验证关联Id的数据合法性
+        TourismProjectTravelNotesWrite originalTourismProjectTravelNotesWrite = tourismProjectTravelNotesWriteService.getById(id);
+        if (originalTourismProjectTravelNotesWrite == null) {
+            // NOTE: 修改下面方括号中的话述
+            errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
+        }
+        if (!tourismProjectTravelNotesWriteService.remove(id)) {
+            errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
+        }
+        return ResponseResult.success();
+    }
+}

+ 179 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/controller/TourismTravelNotesContentWriteController.java

@@ -0,0 +1,179 @@
+package com.tourism.webadmin.back.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.tourism.common.log.annotation.OperationLog;
+import com.tourism.common.log.model.constant.SysOperationLogType;
+import com.github.pagehelper.page.PageMethod;
+import com.tourism.webadmin.back.vo.*;
+import com.tourism.webadmin.back.dto.*;
+import com.tourism.webadmin.back.model.*;
+import com.tourism.webadmin.back.service.*;
+import com.tourism.common.core.object.*;
+import com.tourism.common.core.util.*;
+import com.tourism.common.core.constant.*;
+import com.tourism.common.core.annotation.MyRequestBody;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+
+/**
+ * 发布游记的文本框操作控制器类。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+@Tag(name = "发布游记的文本框管理接口")
+@Slf4j
+@RestController
+@RequestMapping("/admin/app/tourismTravelNotesContentWrite")
+public class TourismTravelNotesContentWriteController {
+
+    @Autowired
+    private TourismTravelNotesContentWriteService tourismTravelNotesContentWriteService;
+
+    /**
+     * 新增发布游记的文本框数据。
+     *
+     * @param tourismTravelNotesContentWriteDto 新增对象。
+     * @return 应答结果对象,包含新增对象主键Id。
+     */
+    @ApiOperationSupport(ignoreParameters = {"tourismTravelNotesContentWriteDto.id"})
+    @SaCheckPermission("tourismTravelNotesContentWrite.add")
+    @OperationLog(type = SysOperationLogType.ADD)
+    @PostMapping("/add")
+    public ResponseResult<Long> add(@MyRequestBody TourismTravelNotesContentWriteDto tourismTravelNotesContentWriteDto) {
+        String errorMessage = MyCommonUtil.getModelValidationError(tourismTravelNotesContentWriteDto, false);
+        if (errorMessage != null) {
+            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
+        }
+        TourismTravelNotesContentWrite tourismTravelNotesContentWrite = MyModelUtil.copyTo(tourismTravelNotesContentWriteDto, TourismTravelNotesContentWrite.class);
+        tourismTravelNotesContentWrite = tourismTravelNotesContentWriteService.saveNew(tourismTravelNotesContentWrite);
+        return ResponseResult.success(tourismTravelNotesContentWrite.getId());
+    }
+
+    /**
+     * 更新发布游记的文本框数据。
+     *
+     * @param tourismTravelNotesContentWriteDto 更新对象。
+     * @return 应答结果对象。
+     */
+    @SaCheckPermission("tourismTravelNotesContentWrite.update")
+    @OperationLog(type = SysOperationLogType.UPDATE)
+    @PostMapping("/update")
+    public ResponseResult<Void> update(@MyRequestBody TourismTravelNotesContentWriteDto tourismTravelNotesContentWriteDto) {
+        String errorMessage = MyCommonUtil.getModelValidationError(tourismTravelNotesContentWriteDto, true);
+        if (errorMessage != null) {
+            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
+        }
+        TourismTravelNotesContentWrite tourismTravelNotesContentWrite = MyModelUtil.copyTo(tourismTravelNotesContentWriteDto, TourismTravelNotesContentWrite.class);
+        TourismTravelNotesContentWrite originalTourismTravelNotesContentWrite = tourismTravelNotesContentWriteService.getById(tourismTravelNotesContentWrite.getId());
+        if (originalTourismTravelNotesContentWrite == null) {
+            // NOTE: 修改下面方括号中的话述
+            errorMessage = "数据验证失败,当前 [数据] 并不存在,请刷新后重试!";
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
+        }
+        if (!tourismTravelNotesContentWriteService.update(tourismTravelNotesContentWrite, originalTourismTravelNotesContentWrite)) {
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
+        }
+        return ResponseResult.success();
+    }
+
+    /**
+     * 删除发布游记的文本框数据。
+     *
+     * @param id 删除对象主键Id。
+     * @return 应答结果对象。
+     */
+    @SaCheckPermission("tourismTravelNotesContentWrite.delete")
+    @OperationLog(type = SysOperationLogType.DELETE)
+    @PostMapping("/delete")
+    public ResponseResult<Void> delete(@MyRequestBody Long id) {
+        if (MyCommonUtil.existBlankArgument(id)) {
+            return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
+        }
+        return this.doDelete(id);
+    }
+
+    /**
+     * 批量删除发布游记的文本框数据。
+     *
+     * @param idList 待删除对象的主键Id列表。
+     * @return 应答结果对象。
+     */
+    @SaCheckPermission("tourismTravelNotesContentWrite.delete")
+    @OperationLog(type = SysOperationLogType.DELETE_BATCH)
+    @PostMapping("/deleteBatch")
+    public ResponseResult<Void> deleteBatch(@MyRequestBody List<Long> idList) {
+        if (MyCommonUtil.existBlankArgument(idList)) {
+            return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
+        }
+        for (Long id : idList) {
+            ResponseResult<Void> responseResult = this.doDelete(id);
+            if (!responseResult.isSuccess()) {
+                return responseResult;
+            }
+        }
+        return ResponseResult.success();
+    }
+
+    /**
+     * 列出符合过滤条件的发布游记的文本框列表。
+     *
+     * @param tourismTravelNotesContentWriteDtoFilter 过滤对象。
+     * @param orderParam 排序参数。
+     * @param pageParam 分页参数。
+     * @return 应答结果对象,包含查询结果集。
+     */
+    @SaCheckPermission("tourismTravelNotesContentWrite.view")
+    @PostMapping("/list")
+    public ResponseResult<MyPageData<TourismTravelNotesContentWriteVo>> list(
+            @MyRequestBody TourismTravelNotesContentWriteDto tourismTravelNotesContentWriteDtoFilter,
+            @MyRequestBody MyOrderParam orderParam,
+            @MyRequestBody MyPageParam pageParam) {
+        if (pageParam != null) {
+            PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize(), pageParam.getCount());
+        }
+        TourismTravelNotesContentWrite tourismTravelNotesContentWriteFilter = MyModelUtil.copyTo(tourismTravelNotesContentWriteDtoFilter, TourismTravelNotesContentWrite.class);
+        String orderBy = MyOrderParam.buildOrderBy(orderParam, TourismTravelNotesContentWrite.class);
+        List<TourismTravelNotesContentWrite> tourismTravelNotesContentWriteList =
+                tourismTravelNotesContentWriteService.getTourismTravelNotesContentWriteListWithRelation(tourismTravelNotesContentWriteFilter, orderBy);
+        return ResponseResult.success(MyPageUtil.makeResponseData(tourismTravelNotesContentWriteList, TourismTravelNotesContentWriteVo.class));
+    }
+
+    /**
+     * 查看指定发布游记的文本框对象详情。
+     *
+     * @param id 指定对象主键Id。
+     * @return 应答结果对象,包含对象详情。
+     */
+    @SaCheckPermission("tourismTravelNotesContentWrite.view")
+    @GetMapping("/view")
+    public ResponseResult<TourismTravelNotesContentWriteVo> view(@RequestParam Long id) {
+        TourismTravelNotesContentWrite tourismTravelNotesContentWrite = tourismTravelNotesContentWriteService.getByIdWithRelation(id, MyRelationParam.full());
+        if (tourismTravelNotesContentWrite == null) {
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
+        }
+        TourismTravelNotesContentWriteVo tourismTravelNotesContentWriteVo = MyModelUtil.copyTo(tourismTravelNotesContentWrite, TourismTravelNotesContentWriteVo.class);
+        return ResponseResult.success(tourismTravelNotesContentWriteVo);
+    }
+
+    private ResponseResult<Void> doDelete(Long id) {
+        String errorMessage;
+        // 验证关联Id的数据合法性
+        TourismTravelNotesContentWrite originalTourismTravelNotesContentWrite = tourismTravelNotesContentWriteService.getById(id);
+        if (originalTourismTravelNotesContentWrite == null) {
+            // NOTE: 修改下面方括号中的话述
+            errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
+        }
+        if (!tourismTravelNotesContentWriteService.remove(id)) {
+            errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
+        }
+        return ResponseResult.success();
+    }
+}

+ 33 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/dao/TourismProjectTravelNotesWriteMapper.java

@@ -0,0 +1,33 @@
+package com.tourism.webadmin.back.dao;
+
+import com.tourism.common.core.base.dao.BaseDaoMapper;
+import com.tourism.webadmin.back.model.TourismProjectTravelNotesWrite;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.*;
+
+/**
+ * 发布游记数据操作访问接口。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+public interface TourismProjectTravelNotesWriteMapper extends BaseDaoMapper<TourismProjectTravelNotesWrite> {
+
+    /**
+     * 批量插入对象列表。
+     *
+     * @param tourismProjectTravelNotesWriteList 新增对象列表。
+     */
+    void insertList(List<TourismProjectTravelNotesWrite> tourismProjectTravelNotesWriteList);
+
+    /**
+     * 获取过滤后的对象列表。
+     *
+     * @param tourismProjectTravelNotesWriteFilter 主表过滤对象。
+     * @param orderBy 排序字符串,order by从句的参数。
+     * @return 对象列表。
+     */
+    List<TourismProjectTravelNotesWrite> getTourismProjectTravelNotesWriteList(
+            @Param("tourismProjectTravelNotesWriteFilter") TourismProjectTravelNotesWrite tourismProjectTravelNotesWriteFilter, @Param("orderBy") String orderBy);
+}

+ 127 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/dao/mapper/TourismProjectTravelNotesWriteMapper.xml

@@ -0,0 +1,127 @@
+<?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.tourism.webadmin.back.dao.TourismProjectTravelNotesWriteMapper">
+    <resultMap id="BaseResultMap" type="com.tourism.webadmin.back.model.TourismProjectTravelNotesWrite">
+        <id column="id" jdbcType="BIGINT" property="id"/>
+        <result column="project_title" jdbcType="VARCHAR" property="projectTitle"/>
+        <result column="departure_time" jdbcType="DATE" property="departureTime"/>
+        <result column="count_times" jdbcType="VARCHAR" property="countTimes"/>
+        <result column="role" jdbcType="VARCHAR" property="role"/>
+        <result column="recommendation_rate" jdbcType="TINYINT" property="recommendationRate"/>
+        <result column="average_cost" jdbcType="VARCHAR" property="averageCost"/>
+        <result column="state" jdbcType="TINYINT" property="state"/>
+        <result column="reason" jdbcType="VARCHAR" property="reason"/>
+        <result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
+        <result column="tourism_url" jdbcType="VARCHAR" property="tourismUrl"/>
+        <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
+        <result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
+        <result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
+        <result column="data_state" jdbcType="TINYINT" property="dataState"/>
+        <result column="tourism_tavel_notes_url" jdbcType="VARCHAR" property="tourismTavelNotesUrl"/>
+<!--        <result column="is_complete" jdbcType="TINYINT" property="isComplete"/>-->
+    </resultMap>
+
+    <insert id="insertList">
+        INSERT INTO tour_tourism_project_travel_notes_writer
+            (id,
+            project_title,
+            departure_time,
+            count_times,
+            role,
+            recommendation_rate,
+            average_cost,
+            state,
+            reason,
+            create_user_id,
+            tourism_url,
+            create_time,
+            update_user_id,
+            update_time,
+            data_state,
+            tourism_tavel_notes_url)
+        VALUES
+        <foreach collection="list" index="index" item="item" separator="," >
+            (#{item.id},
+            #{item.projectTitle},
+            #{item.departureTime},
+            #{item.countTimes},
+            #{item.role},
+            #{item.recommendationRate},
+            #{item.averageCost},
+            #{item.state},
+            #{item.reason},
+            #{item.createUserId},
+            #{item.tourismUrl},
+            #{item.createTime},
+            #{item.updateUserId},
+            #{item.updateTime},
+            #{item.dataState},
+            #{item.tourismTavelNotesUrl})
+        </foreach>
+    </insert>
+
+    <!-- 如果有逻辑删除字段过滤,请写到这里 -->
+    <sql id="filterRef">
+        <!-- 这里必须加上全包名,否则当filterRef被其他Mapper.xml包含引用的时候,就会调用Mapper.xml中的该SQL片段 -->
+        <include refid="com.tourism.webadmin.back.dao.TourismProjectTravelNotesWriteMapper.inputFilterRef"/>
+        AND tour_tourism_project_travel_notes_writer.data_state = ${@com.tourism.common.core.constant.GlobalDeletedFlag@NORMAL}
+    </sql>
+
+    <!-- 这里仅包含调用接口输入的主表过滤条件 -->
+    <sql id="inputFilterRef">
+        <if test="tourismProjectTravelNotesWriteFilter != null">
+            <if test="tourismProjectTravelNotesWriteFilter.projectTitle != null and tourismProjectTravelNotesWriteFilter.projectTitle != ''">
+                <bind name = "safeTourismProjectTravelNotesWriteProjectTitle" value = "'%' + tourismProjectTravelNotesWriteFilter.projectTitle + '%'" />
+                AND tour_tourism_project_travel_notes_writer.project_title LIKE #{safeTourismProjectTravelNotesWriteProjectTitle}
+            </if>
+            <if test="tourismProjectTravelNotesWriteFilter.departureTimeStart != null and tourismProjectTravelNotesWriteFilter.departureTimeStart != ''">
+                AND tour_tourism_project_travel_notes_writer.departure_time &gt;= #{tourismProjectTravelNotesWriteFilter.departureTimeStart}
+            </if>
+            <if test="tourismProjectTravelNotesWriteFilter.departureTimeEnd != null and tourismProjectTravelNotesWriteFilter.departureTimeEnd != ''">
+                AND tour_tourism_project_travel_notes_writer.departure_time &lt;= #{tourismProjectTravelNotesWriteFilter.departureTimeEnd}
+            </if>
+            <if test="tourismProjectTravelNotesWriteFilter.countTimes != null and tourismProjectTravelNotesWriteFilter.countTimes != ''">
+                <bind name = "safeTourismProjectTravelNotesWriteCountTimes" value = "'%' + tourismProjectTravelNotesWriteFilter.countTimes + '%'" />
+                AND tour_tourism_project_travel_notes_writer.count_times LIKE #{safeTourismProjectTravelNotesWriteCountTimes}
+            </if>
+            <if test="tourismProjectTravelNotesWriteFilter.role != null and tourismProjectTravelNotesWriteFilter.role != ''">
+                <bind name = "safeTourismProjectTravelNotesWriteRole" value = "'%' + tourismProjectTravelNotesWriteFilter.role + '%'" />
+                AND tour_tourism_project_travel_notes_writer.role LIKE #{safeTourismProjectTravelNotesWriteRole}
+            </if>
+            <if test="tourismProjectTravelNotesWriteFilter.recommendationRate != null">
+                AND tour_tourism_project_travel_notes_writer.recommendation_rate = #{tourismProjectTravelNotesWriteFilter.recommendationRate}
+            </if>
+            <if test="tourismProjectTravelNotesWriteFilter.averageCost != null and tourismProjectTravelNotesWriteFilter.averageCost != ''">
+                <bind name = "safeTourismProjectTravelNotesWriteAverageCost" value = "'%' + tourismProjectTravelNotesWriteFilter.averageCost + '%'" />
+                AND tour_tourism_project_travel_notes_writer.average_cost LIKE #{safeTourismProjectTravelNotesWriteAverageCost}
+            </if>
+            <if test="tourismProjectTravelNotesWriteFilter.state != null">
+                AND tour_tourism_project_travel_notes_writer.state = #{tourismProjectTravelNotesWriteFilter.state}
+            </if>
+            <if test="tourismProjectTravelNotesWriteFilter.reason != null and tourismProjectTravelNotesWriteFilter.reason != ''">
+                <bind name = "safeTourismProjectTravelNotesWriteReason" value = "'%' + tourismProjectTravelNotesWriteFilter.reason + '%'" />
+                AND tour_tourism_project_travel_notes_writer.reason LIKE #{safeTourismProjectTravelNotesWriteReason}
+            </if>
+            <if test="tourismProjectTravelNotesWriteFilter.createTimeStart != null and tourismProjectTravelNotesWriteFilter.createTimeStart != ''">
+                AND tour_tourism_project_travel_notes_writer.create_time &gt;= #{tourismProjectTravelNotesWriteFilter.createTimeStart}
+            </if>
+            <if test="tourismProjectTravelNotesWriteFilter.createTimeEnd != null and tourismProjectTravelNotesWriteFilter.createTimeEnd != ''">
+                AND tour_tourism_project_travel_notes_writer.create_time &lt;= #{tourismProjectTravelNotesWriteFilter.createTimeEnd}
+            </if>
+            <if test="tourismProjectTravelNotesWriteFilter.searchString != null and tourismProjectTravelNotesWriteFilter.searchString != ''">
+                <bind name = "safeTourismProjectTravelNotesWriteSearchString" value = "'%' + tourismProjectTravelNotesWriteFilter.searchString + '%'" />
+                AND CONCAT(IFNULL(tour_tourism_project_travel_notes_writer.project_title,''), IFNULL(tour_tourism_project_travel_notes_writer.count_times,''), IFNULL(tour_tourism_project_travel_notes_writer.role,''), IFNULL(tour_tourism_project_travel_notes_writer.average_cost,''), IFNULL(tour_tourism_project_travel_notes_writer.reason,'')) LIKE #{safeTourismProjectTravelNotesWriteSearchString}
+            </if>
+        </if>
+    </sql>
+
+    <select id="getTourismProjectTravelNotesWriteList" resultMap="BaseResultMap" parameterType="com.tourism.webadmin.back.model.TourismProjectTravelNotesWrite">
+        SELECT * FROM tour_tourism_project_travel_notes_writer
+        <where>
+            <include refid="filterRef"/>
+        </where>
+        <if test="orderBy != null and orderBy != ''">
+            ORDER BY ${orderBy}
+        </if>
+    </select>
+</mapper>

+ 60 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/dao/mapper/TourismTravelNotesContentWriteMapper.xml

@@ -0,0 +1,60 @@
+<?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.tourism.webadmin.back.dao.TourismTravelNotesContentWriteMapper">
+    <resultMap id="BaseResultMap" type="com.tourism.webadmin.back.model.TourismTravelNotesContentWrite">
+        <id column="id" jdbcType="BIGINT" property="id"/>
+        <result column="content" jdbcType="LONGVARCHAR" property="content"/>
+        <result column="association_id" jdbcType="BIGINT" property="associationId"/>
+        <result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
+        <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
+        <result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
+        <result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
+        <result column="data_state" jdbcType="TINYINT" property="dataState"/>
+    </resultMap>
+
+    <insert id="insertList">
+        INSERT INTO tour_tourism_travel_notes_content_writer
+            (id,
+            content,
+            association_id,
+            create_user_id,
+            create_time,
+            update_user_id,
+            update_time,
+            data_state)
+        VALUES
+        <foreach collection="list" index="index" item="item" separator="," >
+            (#{item.id},
+            #{item.content},
+            #{item.associationId},
+            #{item.createUserId},
+            #{item.createTime},
+            #{item.updateUserId},
+            #{item.updateTime},
+            #{item.dataState})
+        </foreach>
+    </insert>
+
+    <!-- 如果有逻辑删除字段过滤,请写到这里 -->
+    <sql id="filterRef">
+        <!-- 这里必须加上全包名,否则当filterRef被其他Mapper.xml包含引用的时候,就会调用Mapper.xml中的该SQL片段 -->
+        <include refid="com.tourism.webadmin.back.dao.TourismTravelNotesContentWriteMapper.inputFilterRef"/>
+        AND tour_tourism_travel_notes_content_writer.data_state = ${@com.tourism.common.core.constant.GlobalDeletedFlag@NORMAL}
+    </sql>
+
+    <!-- 这里仅包含调用接口输入的主表过滤条件 -->
+    <sql id="inputFilterRef">
+        <if test="tourismTravelNotesContentWriteFilter != null">
+        </if>
+    </sql>
+
+    <select id="getTourismTravelNotesContentWriteList" resultMap="BaseResultMap" parameterType="com.tourism.webadmin.back.model.TourismTravelNotesContentWrite">
+        SELECT * FROM tour_tourism_travel_notes_content_writer
+        <where>
+            <include refid="filterRef"/>
+        </where>
+        <if test="orderBy != null and orderBy != ''">
+            ORDER BY ${orderBy}
+        </if>
+    </select>
+</mapper>

+ 4 - 1
application-webadmin/src/main/java/com/tourism/webadmin/back/dto/TourBookInfoDto.java

@@ -1,7 +1,9 @@
 package com.tourism.webadmin.back.dto;
 
+import com.tourism.common.core.validator.ConstDictRef;
 import com.tourism.common.core.validator.UpdateGroup;
 
+import com.tourism.webadmin.back.model.constant.ProjectType;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
@@ -68,6 +70,7 @@ public class TourBookInfoDto {
      * NOTE: 可支持等于操作符的列表数据过滤。
      */
     @Schema(description = "预定的种类(1:旅游 2:劳务)。可支持等于操作符的列表数据过滤。")
+    @ConstDictRef(constDictClass = ProjectType.class, message = "数据验证失败,预定的种类(1:旅游 2:劳务)为无效值!")
     private Integer type;
 
     /**
@@ -75,7 +78,7 @@ public class TourBookInfoDto {
      * NOTE: 可支持等于操作符的列表数据过滤。
      */
     @Schema(description = "预定种类的id。可支持等于操作符的列表数据过滤。")
-    private String projectId;
+    private Long projectId;
 
     /**
      * 成人价格。

+ 142 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/dto/TourismProjectTravelNotesWriteDto.java

@@ -0,0 +1,142 @@
+package com.tourism.webadmin.back.dto;
+
+import com.tourism.common.core.validator.UpdateGroup;
+import com.tourism.common.core.validator.ConstDictRef;
+import com.tourism.webadmin.back.model.constant.AuditState;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import jakarta.validation.constraints.*;
+
+import java.util.Date;
+
+/**
+ * 发布游记Dto对象。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+@Schema(description = "发布游记Dto对象")
+@Data
+public class TourismProjectTravelNotesWriteDto {
+
+    /**
+     * 主键id。
+     */
+    @Schema(description = "主键id。", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "数据验证失败,主键id不能为空!", groups = {UpdateGroup.class})
+    private Long id;
+
+    /**
+     * 项目标题。
+     * NOTE: 可支持等于操作符的列表数据过滤。
+     */
+    @Schema(description = "项目标题。可支持等于操作符的列表数据过滤。")
+    private String projectTitle;
+
+    /**
+     * 出发时间。
+     * NOTE: 可支持等于操作符的列表数据过滤。
+     */
+    @Schema(description = "出发时间。可支持等于操作符的列表数据过滤。")
+    private Date departureTime;
+
+    /**
+     * 总天数。
+     * NOTE: 可支持等于操作符的列表数据过滤。
+     */
+    @Schema(description = "总天数。可支持等于操作符的列表数据过滤。")
+    private String countTimes;
+
+    /**
+     * 人物关系。
+     * NOTE: 可支持等于操作符的列表数据过滤。
+     */
+    @Schema(description = "人物关系。可支持等于操作符的列表数据过滤。")
+    private String role;
+
+    /**
+     * 推荐指数。
+     * NOTE: 可支持等于操作符的列表数据过滤。
+     */
+    @Schema(description = "推荐指数。可支持等于操作符的列表数据过滤。")
+    private Integer recommendationRate;
+
+    /**
+     * 人均费用。
+     * NOTE: 可支持等于操作符的列表数据过滤。
+     */
+    @Schema(description = "人均费用。可支持等于操作符的列表数据过滤。")
+    private String averageCost;
+
+    /**
+     * 审核状态(0,未审核;1,审核通过;2、审核不通过)。
+     * NOTE: 可支持等于操作符的列表数据过滤。
+     */
+    @Schema(description = "审核状态(0,未审核;1,审核通过;2、审核不通过)。可支持等于操作符的列表数据过滤。")
+    @ConstDictRef(constDictClass = AuditState.class, message = "数据验证失败,审核状态(0,未审核;1,审核通过;2、审核不通过)为无效值!")
+    private Integer state;
+
+    /**
+     * 审核不通过的原因。
+     * NOTE: 可支持等于操作符的列表数据过滤。
+     */
+    @Schema(description = "审核不通过的原因。可支持等于操作符的列表数据过滤。")
+    private String reason;
+
+    /**
+     * 项目展示图片。
+     */
+    @Schema(description = "项目展示图片。")
+    private String tourismUrl;
+
+    /**
+     * 游记内容中的图片。
+     */
+    @Schema(description = "游记内容中的图片。")
+    private String tourismTavelNotesUrl;
+
+//    /**
+//     * 是否完成(0,草稿;1,成稿)。
+//     * NOTE: 可支持等于操作符的列表数据过滤。
+//     */
+//    @Schema(description = "是否完成(0,草稿;1,成稿)。可支持等于操作符的列表数据过滤。")
+//    @ConstDictRef(constDictClass = IsComplete.class, message = "数据验证失败,是否完成(0,草稿;1,成稿)为无效值!")
+//    private Integer isComplete;
+
+    /**
+     * departureTime 范围过滤起始值(>=)。
+     * NOTE: 可支持范围操作符的列表数据过滤。
+     */
+    @Schema(description = "departureTime 范围过滤起始值(>=)。可支持范围操作符的列表数据过滤。")
+    private String departureTimeStart;
+
+    /**
+     * departureTime 范围过滤结束值(<=)。
+     * NOTE: 可支持范围操作符的列表数据过滤。
+     */
+    @Schema(description = "departureTime 范围过滤结束值(<=)。可支持范围操作符的列表数据过滤。")
+    private String departureTimeEnd;
+
+    /**
+     * createTime 范围过滤起始值(>=)。
+     * NOTE: 可支持范围操作符的列表数据过滤。
+     */
+    @Schema(description = "createTime 范围过滤起始值(>=)。可支持范围操作符的列表数据过滤。")
+    private String createTimeStart;
+
+    /**
+     * createTime 范围过滤结束值(<=)。
+     * NOTE: 可支持范围操作符的列表数据过滤。
+     */
+    @Schema(description = "createTime 范围过滤结束值(<=)。可支持范围操作符的列表数据过滤。")
+    private String createTimeEnd;
+
+    /**
+     * project_title / count_times / role / average_cost / reason LIKE搜索字符串。
+     * NOTE: 可支持LIKE操作符的列表数据过滤。
+     */
+    @Schema(description = "LIKE模糊搜索字符串")
+    private String searchString;
+}

+ 39 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/dto/TourismTravelNotesContentWriteDto.java

@@ -0,0 +1,39 @@
+package com.tourism.webadmin.back.dto;
+
+import com.tourism.common.core.validator.UpdateGroup;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import jakarta.validation.constraints.*;
+
+/**
+ * 发布游记的文本框Dto对象。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+@Schema(description = "发布游记的文本框Dto对象")
+@Data
+public class TourismTravelNotesContentWriteDto {
+
+    /**
+     * 主键id。
+     */
+    @Schema(description = "主键id。", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "数据验证失败,主键id不能为空!", groups = {UpdateGroup.class})
+    private Long id;
+
+    /**
+     * 富文本内容。
+     */
+    @Schema(description = "富文本内容。")
+    private String content;
+
+    /**
+     * 关联表id。
+     */
+    @Schema(description = "关联表id。", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "数据验证失败,关联表id不能为空!", groups = {UpdateGroup.class})
+    private Long associationId;
+}

+ 14 - 7
application-webadmin/src/main/java/com/tourism/webadmin/back/model/TourBookInfo.java

@@ -70,7 +70,7 @@ public class TourBookInfo extends BaseModel {
      * 预定种类的id。
      */
     @TableField(value = "project_id")
-    private String projectId;
+    private Long projectId;
 
     /**
      * 逻辑删除标记字段(1: 正常 -1: 已删除)。
@@ -115,16 +115,17 @@ public class TourBookInfo extends BaseModel {
     @TableField(exist = false)
     private String searchString;
 
-    @TableField(exist = false)
-    private Date startTime;
-
-    @TableField(exist = false)
-    private Date endTime;
-
     public void setSearchString(String searchString) {
         this.searchString = MyCommonUtil.replaceSqlWildcard(searchString);
     }
 
+    @RelationOneToOne(
+            masterIdField = "projectId",
+            slaveModelClass = TourismProject.class,
+            slaveIdField = "id")
+    @TableField(exist = false)
+    private TourismProject tourismProject;
+
     @RelationConstDict(
             masterIdField = "type",
             constantDictClass = ProjectType.class)
@@ -137,6 +138,12 @@ public class TourBookInfo extends BaseModel {
     @TableField(exist = false)
     private Map<String, Object> isHandleDictMap;
 
+    @TableField(exist = false)
+    private Date startTime;
+
+    @TableField(exist = false)
+    private Date endTime;
+
 
     public String getString() {
         return type + "_" + projectId + "_" + adultNumber + "_" + childrenNumber + "_" + startTime;

+ 159 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/model/TourismProjectTravelNotesWrite.java

@@ -0,0 +1,159 @@
+package com.tourism.webadmin.back.model;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.tourism.webadmin.back.model.constant.AuditState;
+import com.tourism.common.core.util.MyCommonUtil;
+import com.tourism.common.core.upload.UploadStoreTypeEnum;
+import com.tourism.common.core.annotation.*;
+import com.tourism.common.core.base.model.BaseModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * 发布游记实体对象。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName(value = "tour_tourism_project_travel_notes_writer")
+public class TourismProjectTravelNotesWrite extends BaseModel {
+
+    /**
+     * 主键id。
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 项目标题。
+     */
+    @TableField(value = "project_title")
+    private String projectTitle;
+
+    /**
+     * 出发时间。
+     */
+    @TableField(value = "departure_time")
+    private Date departureTime;
+
+    /**
+     * 总天数。
+     */
+    @TableField(value = "count_times")
+    private String countTimes;
+
+    /**
+     * 人物关系。
+     */
+    @TableField(value = "role")
+    private String role;
+
+    /**
+     * 推荐指数。
+     */
+    @TableField(value = "recommendation_rate")
+    private Integer recommendationRate;
+
+    /**
+     * 人均费用。
+     */
+    @TableField(value = "average_cost")
+    private String averageCost;
+
+    /**
+     * 审核状态(0,未审核;1,审核通过;2、审核不通过)。
+     */
+    @TableField(value = "state")
+    private Integer state;
+
+    /**
+     * 审核不通过的原因。
+     */
+    @TableField(value = "reason")
+    private String reason;
+
+    /**
+     * 项目展示图片。
+     */
+    @UploadFlagColumn(storeType = UploadStoreTypeEnum.HUAWEI_OBS_SYSTEM)
+    @TableField(value = "tourism_url")
+    private String tourismUrl;
+
+    /**
+     * 逻辑删除标记字段(1: 正常 -1: 已删除)。
+     */
+    @TableLogic
+    @TableField(value = "data_state")
+    private Integer dataState;
+
+    /**
+     * 游记内容中的图片。
+     */
+    @UploadFlagColumn(storeType = UploadStoreTypeEnum.HUAWEI_OBS_SYSTEM)
+    @TableField(value = "tourism_tavel_notes_url")
+    private String tourismTavelNotesUrl;
+
+//    /**
+//     * 是否完成(0,草稿;1,成稿)。
+//     */
+//    @TableField(value = "is_complete")
+//    private Integer isComplete;
+
+    /**
+     * departureTime 范围过滤起始值(>=)。
+     */
+    @TableField(exist = false)
+    private String departureTimeStart;
+
+    /**
+     * departureTime 范围过滤结束值(<=)。
+     */
+    @TableField(exist = false)
+    private String departureTimeEnd;
+
+    /**
+     * createTime 范围过滤起始值(>=)。
+     */
+    @TableField(exist = false)
+    private String createTimeStart;
+
+    /**
+     * createTime 范围过滤结束值(<=)。
+     */
+    @TableField(exist = false)
+    private String createTimeEnd;
+
+    /**
+     * project_title / count_times / role / average_cost / reason LIKE搜索字符串。
+     */
+    @TableField(exist = false)
+    private String searchString;
+
+    public void setSearchString(String searchString) {
+        this.searchString = MyCommonUtil.replaceSqlWildcard(searchString);
+    }
+
+    @RelationOneToOne(
+            masterIdField = "id",
+            slaveModelClass = TourismTravelNotesContentWrite.class,
+            slaveIdField = "associationId")
+    @TableField(exist = false)
+    private TourismTravelNotesContentWrite tourismTravelNotesContentWrite;
+
+    @RelationConstDict(
+            masterIdField = "state",
+            constantDictClass = AuditState.class)
+    @TableField(exist = false)
+    private Map<String, Object> stateDictMap;
+
+//    @RelationConstDict(
+//            masterIdField = "isComplete",
+//            constantDictClass = IsComplete.class)
+//    @TableField(exist = false)
+//    private Map<String, Object> isCompleteDictMap;
+}

+ 43 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/model/TourismTravelNotesContentWrite.java

@@ -0,0 +1,43 @@
+package com.tourism.webadmin.back.model;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.tourism.common.core.base.model.BaseModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 发布游记的文本框实体对象。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName(value = "tour_tourism_travel_notes_content_writer")
+public class TourismTravelNotesContentWrite extends BaseModel {
+
+    /**
+     * 主键id。
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 富文本内容。
+     */
+    @TableField(value = "content")
+    private String content;
+
+    /**
+     * 关联表id。
+     */
+    @TableField(value = "association_id")
+    private Long associationId;
+
+    /**
+     * 逻辑删除标记字段(1: 正常 -1: 已删除)。
+     */
+    @TableLogic
+    @TableField(value = "data_state")
+    private Integer dataState;
+}

+ 49 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/model/constant/AuditState.java

@@ -0,0 +1,49 @@
+package com.tourism.webadmin.back.model.constant;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 审核状态常量字典对象。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+public final class AuditState {
+
+    /**
+     * 未审核。
+     */
+    public static final int UNAUDITSTATE = 0;
+    /**
+     * 审核未通过。
+     */
+    public static final int FAILAUDIT = 1;
+    /**
+     * 审核通过。
+     */
+    public static final int SUCCEEDAUDIT = 2;
+
+    private static final Map<Object, String> DICT_MAP = new HashMap<>(3);
+    static {
+        DICT_MAP.put(UNAUDITSTATE, "未审核");
+        DICT_MAP.put(FAILAUDIT, "审核未通过");
+        DICT_MAP.put(SUCCEEDAUDIT, "审核通过");
+    }
+
+    /**
+     * 判断参数是否为当前常量字典的合法值。
+     *
+     * @param value 待验证的参数值。
+     * @return 合法返回true,否则false。
+     */
+    public static boolean isValid(Integer value) {
+        return value != null && DICT_MAP.containsKey(value);
+    }
+
+    /**
+     * 私有构造函数,明确标识该常量类的作用。
+     */
+    private AuditState() {
+    }
+}

+ 44 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/model/constant/IsComplete.java

@@ -0,0 +1,44 @@
+package com.tourism.webadmin.back.model.constant;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 是否完成写作常量字典对象。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+public final class IsComplete {
+
+    /**
+     * 未完成。
+     */
+    public static final int UNCOMPLETED = 0;
+    /**
+     * 完成。
+     */
+    public static final int COMPLETED = 1;
+
+    private static final Map<Object, String> DICT_MAP = new HashMap<>(2);
+    static {
+        DICT_MAP.put(UNCOMPLETED, "未完成");
+        DICT_MAP.put(COMPLETED, "完成");
+    }
+
+    /**
+     * 判断参数是否为当前常量字典的合法值。
+     *
+     * @param value 待验证的参数值。
+     * @return 合法返回true,否则false。
+     */
+    public static boolean isValid(Integer value) {
+        return value != null && DICT_MAP.containsKey(value);
+    }
+
+    /**
+     * 私有构造函数,明确标识该常量类的作用。
+     */
+    private IsComplete() {
+    }
+}

+ 68 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/service/TourismProjectTravelNotesWriteService.java

@@ -0,0 +1,68 @@
+package com.tourism.webadmin.back.service;
+
+import com.tourism.webadmin.back.model.*;
+import com.tourism.common.core.base.service.IBaseService;
+
+import java.util.*;
+
+/**
+ * 发布游记数据操作服务接口。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+public interface TourismProjectTravelNotesWriteService extends IBaseService<TourismProjectTravelNotesWrite, Long> {
+
+    /**
+     * 保存新增对象。
+     *
+     * @param tourismProjectTravelNotesWrite 新增对象。
+     * @return 返回新增对象。
+     */
+    TourismProjectTravelNotesWrite saveNew(TourismProjectTravelNotesWrite tourismProjectTravelNotesWrite);
+
+    /**
+     * 利用数据库的insertList语法,批量插入对象列表。
+     *
+     * @param tourismProjectTravelNotesWriteList 新增对象列表。
+     */
+    void saveNewBatch(List<TourismProjectTravelNotesWrite> tourismProjectTravelNotesWriteList);
+
+    /**
+     * 更新数据对象。
+     *
+     * @param tourismProjectTravelNotesWrite         更新的对象。
+     * @param originalTourismProjectTravelNotesWrite 原有数据对象。
+     * @return 成功返回true,否则false。
+     */
+    boolean update(TourismProjectTravelNotesWrite tourismProjectTravelNotesWrite, TourismProjectTravelNotesWrite originalTourismProjectTravelNotesWrite);
+
+    /**
+     * 删除指定数据。
+     *
+     * @param id 主键Id。
+     * @return 成功返回true,否则false。
+     */
+    boolean remove(Long id);
+
+    /**
+     * 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
+     * 如果需要同时获取关联数据,请移步(getTourismProjectTravelNotesWriteListWithRelation)方法。
+     *
+     * @param filter  过滤对象。
+     * @param orderBy 排序参数。
+     * @return 查询结果集。
+     */
+    List<TourismProjectTravelNotesWrite> getTourismProjectTravelNotesWriteList(TourismProjectTravelNotesWrite filter, String orderBy);
+
+    /**
+     * 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
+     * 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
+     * 如果仅仅需要获取主表数据,请移步(getTourismProjectTravelNotesWriteList),以便获取更好的查询性能。
+     *
+     * @param filter 主表过滤对象。
+     * @param orderBy 排序参数。
+     * @return 查询结果集。
+     */
+    List<TourismProjectTravelNotesWrite> getTourismProjectTravelNotesWriteListWithRelation(TourismProjectTravelNotesWrite filter, String orderBy);
+}

+ 76 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/service/TourismTravelNotesContentWriteService.java

@@ -0,0 +1,76 @@
+package com.tourism.webadmin.back.service;
+
+import com.tourism.webadmin.back.model.*;
+import com.tourism.common.core.base.service.IBaseService;
+
+import java.util.*;
+
+/**
+ * 发布游记的文本框数据操作服务接口。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+public interface TourismTravelNotesContentWriteService extends IBaseService<TourismTravelNotesContentWrite, Long> {
+
+    /**
+     * 保存新增对象。
+     *
+     * @param tourismTravelNotesContentWrite 新增对象。
+     * @return 返回新增对象。
+     */
+    TourismTravelNotesContentWrite saveNew(TourismTravelNotesContentWrite tourismTravelNotesContentWrite);
+
+    /**
+     * 利用数据库的insertList语法,批量插入对象列表。
+     *
+     * @param tourismTravelNotesContentWriteList 新增对象列表。
+     */
+    void saveNewBatch(List<TourismTravelNotesContentWrite> tourismTravelNotesContentWriteList);
+
+    /**
+     * 更新数据对象。
+     *
+     * @param tourismTravelNotesContentWrite         更新的对象。
+     * @param originalTourismTravelNotesContentWrite 原有数据对象。
+     * @return 成功返回true,否则false。
+     */
+    boolean update(TourismTravelNotesContentWrite tourismTravelNotesContentWrite, TourismTravelNotesContentWrite originalTourismTravelNotesContentWrite);
+
+    /**
+     * 删除指定数据。
+     *
+     * @param id 主键Id。
+     * @return 成功返回true,否则false。
+     */
+    boolean remove(Long id);
+
+    /**
+     * 当前服务的支持表为从表,根据主表的关联Id,删除一对多的从表数据。
+     *
+     * @param associationId 从表关联字段。
+     * @return 删除数量。
+     */
+    int removeByAssociationId(Long associationId);
+
+    /**
+     * 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
+     * 如果需要同时获取关联数据,请移步(getTourismTravelNotesContentWriteListWithRelation)方法。
+     *
+     * @param filter  过滤对象。
+     * @param orderBy 排序参数。
+     * @return 查询结果集。
+     */
+    List<TourismTravelNotesContentWrite> getTourismTravelNotesContentWriteList(TourismTravelNotesContentWrite filter, String orderBy);
+
+    /**
+     * 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
+     * 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
+     * 如果仅仅需要获取主表数据,请移步(getTourismTravelNotesContentWriteList),以便获取更好的查询性能。
+     *
+     * @param filter 主表过滤对象。
+     * @param orderBy 排序参数。
+     * @return 查询结果集。
+     */
+    List<TourismTravelNotesContentWrite> getTourismTravelNotesContentWriteListWithRelation(TourismTravelNotesContentWrite filter, String orderBy);
+}

+ 114 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/service/impl/TourismProjectTravelNotesWriteServiceImpl.java

@@ -0,0 +1,114 @@
+package com.tourism.webadmin.back.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.tourism.webadmin.back.model.constant.AuditState;
+import com.tourism.webadmin.back.service.*;
+import com.tourism.webadmin.back.dao.*;
+import com.tourism.webadmin.back.model.*;
+import com.tourism.webadmin.config.DataSourceType;
+import com.tourism.common.core.annotation.MyDataSource;
+import com.tourism.common.core.base.dao.BaseDaoMapper;
+import com.tourism.common.core.constant.GlobalDeletedFlag;
+import com.tourism.common.core.object.MyRelationParam;
+import com.tourism.common.core.base.service.BaseService;
+import com.tourism.common.core.util.MyModelUtil;
+import com.tourism.common.sequence.wrapper.IdGeneratorWrapper;
+import com.github.pagehelper.Page;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * 发布游记数据操作服务类。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+@Slf4j
+@Service("tourismProjectTravelNotesWriteService")
+public class TourismProjectTravelNotesWriteServiceImpl extends BaseService<TourismProjectTravelNotesWrite, Long> implements TourismProjectTravelNotesWriteService {
+
+    @Autowired
+    private IdGeneratorWrapper idGenerator;
+    @Autowired
+    private TourismProjectTravelNotesWriteMapper tourismProjectTravelNotesWriteMapper;
+    @Autowired
+    private TourismTravelNotesContentWriteService tourismTravelNotesContentWriteService;
+
+    /**
+     * 返回当前Service的主表Mapper对象。
+     *
+     * @return 主表Mapper对象。
+     */
+    @Override
+    protected BaseDaoMapper<TourismProjectTravelNotesWrite> mapper() {
+        return tourismProjectTravelNotesWriteMapper;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public TourismProjectTravelNotesWrite saveNew(TourismProjectTravelNotesWrite tourismProjectTravelNotesWrite) {
+        tourismProjectTravelNotesWriteMapper.insert(this.buildDefaultValue(tourismProjectTravelNotesWrite));
+        return tourismProjectTravelNotesWrite;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void saveNewBatch(List<TourismProjectTravelNotesWrite> tourismProjectTravelNotesWriteList) {
+        if (CollUtil.isNotEmpty(tourismProjectTravelNotesWriteList)) {
+            tourismProjectTravelNotesWriteList.forEach(this::buildDefaultValue);
+            tourismProjectTravelNotesWriteMapper.insertList(tourismProjectTravelNotesWriteList);
+        }
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean update(TourismProjectTravelNotesWrite tourismProjectTravelNotesWrite, TourismProjectTravelNotesWrite originalTourismProjectTravelNotesWrite) {
+        MyModelUtil.fillCommonsForUpdate(tourismProjectTravelNotesWrite, originalTourismProjectTravelNotesWrite);
+        // 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。
+        UpdateWrapper<TourismProjectTravelNotesWrite> uw = this.createUpdateQueryForNullValue(tourismProjectTravelNotesWrite, tourismProjectTravelNotesWrite.getId());
+        return tourismProjectTravelNotesWriteMapper.update(tourismProjectTravelNotesWrite, uw) == 1;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean remove(Long id) {
+        if (tourismProjectTravelNotesWriteMapper.deleteById(id) == 0) {
+            return false;
+        }
+        tourismTravelNotesContentWriteService.removeByAssociationId(id);
+        return true;
+    }
+
+    @Override
+    public List<TourismProjectTravelNotesWrite> getTourismProjectTravelNotesWriteList(TourismProjectTravelNotesWrite filter, String orderBy) {
+        return tourismProjectTravelNotesWriteMapper.getTourismProjectTravelNotesWriteList(filter, orderBy);
+    }
+
+    @Override
+    public List<TourismProjectTravelNotesWrite> getTourismProjectTravelNotesWriteListWithRelation(TourismProjectTravelNotesWrite filter, String orderBy) {
+        List<TourismProjectTravelNotesWrite> resultList = tourismProjectTravelNotesWriteMapper.getTourismProjectTravelNotesWriteList(filter, orderBy);
+        // 在缺省生成的代码中,如果查询结果resultList不是Page对象,说明没有分页,那么就很可能是数据导出接口调用了当前方法。
+        // 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
+        int batchSize = resultList instanceof Page ? 0 : 1000;
+        this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
+        return resultList;
+    }
+
+    private TourismProjectTravelNotesWrite buildDefaultValue(TourismProjectTravelNotesWrite tourismProjectTravelNotesWrite) {
+        if (tourismProjectTravelNotesWrite.getId() == null) {
+            tourismProjectTravelNotesWrite.setId(idGenerator.nextLongId());
+        }
+        MyModelUtil.fillCommonsForInsert(tourismProjectTravelNotesWrite);
+        tourismProjectTravelNotesWrite.setDataState(GlobalDeletedFlag.NORMAL);
+        MyModelUtil.setDefaultValue(tourismProjectTravelNotesWrite, "reason", "");
+        MyModelUtil.setDefaultValue(tourismProjectTravelNotesWrite, "tourismUrl", "");
+        MyModelUtil.setDefaultValue(tourismProjectTravelNotesWrite, "tourismTavelNotesUrl", "");
+        MyModelUtil.setDefaultValue(tourismProjectTravelNotesWrite, "state", AuditState.UNAUDITSTATE);
+        return tourismProjectTravelNotesWrite;
+    }
+}

+ 106 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/service/impl/TourismTravelNotesContentWriteServiceImpl.java

@@ -0,0 +1,106 @@
+package com.tourism.webadmin.back.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.*;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.tourism.webadmin.back.service.*;
+import com.tourism.webadmin.back.dao.*;
+import com.tourism.webadmin.back.model.*;
+import com.tourism.webadmin.config.DataSourceType;
+import com.tourism.common.core.annotation.MyDataSource;
+import com.tourism.common.core.base.dao.BaseDaoMapper;
+import com.tourism.common.core.constant.GlobalDeletedFlag;
+import com.tourism.common.core.object.MyRelationParam;
+import com.tourism.common.core.base.service.BaseService;
+import com.tourism.common.core.util.MyModelUtil;
+import com.github.pagehelper.Page;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * 发布游记的文本框数据操作服务类。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+@Slf4j
+@Service("tourismTravelNotesContentWriteService")
+public class TourismTravelNotesContentWriteServiceImpl extends BaseService<TourismTravelNotesContentWrite, Long> implements TourismTravelNotesContentWriteService {
+
+    @Autowired
+    private TourismTravelNotesContentWriteMapper tourismTravelNotesContentWriteMapper;
+
+    /**
+     * 返回当前Service的主表Mapper对象。
+     *
+     * @return 主表Mapper对象。
+     */
+    @Override
+    protected BaseDaoMapper<TourismTravelNotesContentWrite> mapper() {
+        return tourismTravelNotesContentWriteMapper;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public TourismTravelNotesContentWrite saveNew(TourismTravelNotesContentWrite tourismTravelNotesContentWrite) {
+        tourismTravelNotesContentWriteMapper.insert(this.buildDefaultValue(tourismTravelNotesContentWrite));
+        return tourismTravelNotesContentWrite;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void saveNewBatch(List<TourismTravelNotesContentWrite> tourismTravelNotesContentWriteList) {
+        if (CollUtil.isNotEmpty(tourismTravelNotesContentWriteList)) {
+            tourismTravelNotesContentWriteList.forEach(this::buildDefaultValue);
+            tourismTravelNotesContentWriteMapper.insertList(tourismTravelNotesContentWriteList);
+        }
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean update(TourismTravelNotesContentWrite tourismTravelNotesContentWrite, TourismTravelNotesContentWrite originalTourismTravelNotesContentWrite) {
+        MyModelUtil.fillCommonsForUpdate(tourismTravelNotesContentWrite, originalTourismTravelNotesContentWrite);
+        // 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。
+        UpdateWrapper<TourismTravelNotesContentWrite> uw = this.createUpdateQueryForNullValue(tourismTravelNotesContentWrite, tourismTravelNotesContentWrite.getId());
+        return tourismTravelNotesContentWriteMapper.update(tourismTravelNotesContentWrite, uw) == 1;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean remove(Long id) {
+        return tourismTravelNotesContentWriteMapper.deleteById(id) == 1;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public int removeByAssociationId(Long associationId) {
+        TourismTravelNotesContentWrite deletedObject = new TourismTravelNotesContentWrite();
+        deletedObject.setAssociationId(associationId);
+        return tourismTravelNotesContentWriteMapper.delete(new QueryWrapper<>(deletedObject));
+    }
+
+    @Override
+    public List<TourismTravelNotesContentWrite> getTourismTravelNotesContentWriteList(TourismTravelNotesContentWrite filter, String orderBy) {
+        return tourismTravelNotesContentWriteMapper.getTourismTravelNotesContentWriteList(filter, orderBy);
+    }
+
+    @Override
+    public List<TourismTravelNotesContentWrite> getTourismTravelNotesContentWriteListWithRelation(TourismTravelNotesContentWrite filter, String orderBy) {
+        List<TourismTravelNotesContentWrite> resultList = tourismTravelNotesContentWriteMapper.getTourismTravelNotesContentWriteList(filter, orderBy);
+        // 在缺省生成的代码中,如果查询结果resultList不是Page对象,说明没有分页,那么就很可能是数据导出接口调用了当前方法。
+        // 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
+        int batchSize = resultList instanceof Page ? 0 : 1000;
+        this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
+        return resultList;
+    }
+
+    private TourismTravelNotesContentWrite buildDefaultValue(TourismTravelNotesContentWrite tourismTravelNotesContentWrite) {
+        MyModelUtil.fillCommonsForInsert(tourismTravelNotesContentWrite);
+        tourismTravelNotesContentWrite.setDataState(GlobalDeletedFlag.NORMAL);
+        return tourismTravelNotesContentWrite;
+    }
+}

+ 13 - 7
application-webadmin/src/main/java/com/tourism/webadmin/back/vo/TourBookInfoVo.java

@@ -27,7 +27,7 @@ public class TourBookInfoVo extends BaseVo {
      * 主键id。
      */
     @Schema(description = "主键id")
-    private String id;
+    private Long id;
 
     /**
      * 预定电话。
@@ -102,17 +102,23 @@ public class TourBookInfoVo extends BaseVo {
     private BigDecimal totalPrice;
 
     /**
+     * projectId 的一对一关联数据对象,数据对应类型为TourismProjectVo。
+     */
+    @Schema(description = "projectId 的一对一关联数据对象,数据对应类型为TourismProjectVo")
+    private Map<String, Object> tourismProject;
+
+    /**
+     * type 常量字典关联数据。
+     */
+    @Schema(description = "type 常量字典关联数据")
+    private Map<String, Object> typeDictMap;
+
+    /**
      * isHandle 全局字典关联数据。
      */
     @Schema(description = "isHandle 全局字典关联数据")
     private Map<String, Object> isHandleDictMap;
 
-    @RelationConstDict(
-            masterIdField = "type",
-            constantDictClass = ProjectType.class)
-    @TableField(exist = false)
-    private Map<String, Object> typeDictMap;
-
     /**
      * projectMap 项目关联的数据。
      */

+ 111 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/vo/TourismProjectTravelNotesWriteVo.java

@@ -0,0 +1,111 @@
+package com.tourism.webadmin.back.vo;
+
+import com.tourism.common.core.base.vo.BaseVo;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * 发布游记VO视图对象。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+@Schema(description = "发布游记VO视图对象")
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TourismProjectTravelNotesWriteVo extends BaseVo {
+
+    /**
+     * 主键id。
+     */
+    @Schema(description = "主键id")
+    private Long id;
+
+    /**
+     * 项目标题。
+     */
+    @Schema(description = "项目标题")
+    private String projectTitle;
+
+    /**
+     * 出发时间。
+     */
+    @Schema(description = "出发时间")
+    private Date departureTime;
+
+    /**
+     * 总天数。
+     */
+    @Schema(description = "总天数")
+    private String countTimes;
+
+    /**
+     * 人物关系。
+     */
+    @Schema(description = "人物关系")
+    private String role;
+
+    /**
+     * 推荐指数。
+     */
+    @Schema(description = "推荐指数")
+    private Integer recommendationRate;
+
+    /**
+     * 人均费用。
+     */
+    @Schema(description = "人均费用")
+    private String averageCost;
+
+    /**
+     * 审核状态(0,未审核;1,审核通过;2、审核不通过)。
+     */
+    @Schema(description = "审核状态(0,未审核;1,审核通过;2、审核不通过)")
+    private Integer state;
+
+    /**
+     * 审核不通过的原因。
+     */
+    @Schema(description = "审核不通过的原因")
+    private String reason;
+
+    /**
+     * 项目展示图片。
+     */
+    @Schema(description = "项目展示图片")
+    private String tourismUrl;
+
+    /**
+     * 游记内容中的图片。
+     */
+    @Schema(description = "游记内容中的图片")
+    private String tourismTavelNotesUrl;
+
+//    /**
+//     * 是否完成(0,草稿;1,成稿)。
+//     */
+//    @Schema(description = "是否完成(0,草稿;1,成稿)")
+//    private Integer isComplete;
+
+    /**
+     * id 的一对一关联数据对象,数据对应类型为TourismTravelNotesContentWriteVo。
+     */
+    @Schema(description = "id 的一对一关联数据对象,数据对应类型为TourismTravelNotesContentWriteVo")
+    private Map<String, Object> tourismTravelNotesContentWrite;
+
+    /**
+     * state 常量字典关联数据。
+     */
+    @Schema(description = "state 常量字典关联数据")
+    private Map<String, Object> stateDictMap;
+
+//    /**
+//     * isComplete 常量字典关联数据。
+//     */
+//    @Schema(description = "isComplete 常量字典关联数据")
+//    private Map<String, Object> isCompleteDictMap;
+}

+ 36 - 0
application-webadmin/src/main/java/com/tourism/webadmin/back/vo/TourismTravelNotesContentWriteVo.java

@@ -0,0 +1,36 @@
+package com.tourism.webadmin.back.vo;
+
+import com.tourism.common.core.base.vo.BaseVo;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 发布游记的文本框VO视图对象。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+@Schema(description = "发布游记的文本框VO视图对象")
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TourismTravelNotesContentWriteVo extends BaseVo {
+
+    /**
+     * 主键id。
+     */
+    @Schema(description = "主键id")
+    private Long id;
+
+    /**
+     * 富文本内容。
+     */
+    @Schema(description = "富文本内容")
+    private String content;
+
+    /**
+     * 关联表id。
+     */
+    @Schema(description = "关联表id")
+    private Long associationId;
+}