瀏覽代碼

公司信息管理

mgz12 6 月之前
父節點
當前提交
6d5d3bba0e
共有 16 個文件被更改,包括 899 次插入272 次删除
  1. 182 27
      application-webadmin/src/main/java/com/tourism/webadmin/app/controller/CompanyInfoController.java
  2. 179 0
      application-webadmin/src/main/java/com/tourism/webadmin/app/controller/ContentCompanyController.java
  3. 33 0
      application-webadmin/src/main/java/com/tourism/webadmin/app/dao/ContentCompanyMapper.java
  4. 3 0
      application-webadmin/src/main/java/com/tourism/webadmin/app/dao/mapper/CompanyInfoMapper.xml
  5. 60 0
      application-webadmin/src/main/java/com/tourism/webadmin/app/dao/mapper/ContentCompanyMapper.xml
  6. 9 0
      application-webadmin/src/main/java/com/tourism/webadmin/app/dto/CompanyInfoDto.java
  7. 40 0
      application-webadmin/src/main/java/com/tourism/webadmin/app/dto/ContentCompanyDto.java
  8. 24 0
      application-webadmin/src/main/java/com/tourism/webadmin/app/model/CompanyInfo.java
  9. 43 0
      application-webadmin/src/main/java/com/tourism/webadmin/app/model/ContentCompany.java
  10. 32 0
      application-webadmin/src/main/java/com/tourism/webadmin/app/service/CompanyInfoService.java
  11. 76 0
      application-webadmin/src/main/java/com/tourism/webadmin/app/service/ContentCompanyService.java
  12. 57 1
      application-webadmin/src/main/java/com/tourism/webadmin/app/service/impl/CompanyInfoServiceImpl.java
  13. 104 0
      application-webadmin/src/main/java/com/tourism/webadmin/app/service/impl/ContentCompanyServiceImpl.java
  14. 0 244
      application-webadmin/src/main/java/com/tourism/webadmin/app/util/FlowIdentityExtHelper.java
  15. 19 0
      application-webadmin/src/main/java/com/tourism/webadmin/app/vo/CompanyInfoVo.java
  16. 38 0
      application-webadmin/src/main/java/com/tourism/webadmin/app/vo/ContentCompanyVo.java

+ 182 - 27
application-webadmin/src/main/java/com/tourism/webadmin/app/controller/CompanyInfoController.java

@@ -1,6 +1,12 @@
 package com.tourism.webadmin.app.controller;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.alibaba.fastjson.JSONObject;
+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;
@@ -12,6 +18,7 @@ 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.webadmin.config.ApplicationConfig;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -20,6 +27,7 @@ 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.*;
 
@@ -38,54 +46,65 @@ public class CompanyInfoController {
     @Autowired
     private ApplicationConfig appConfig;
     @Autowired
+    private SessionCacheHelper cacheHelper;
+    @Autowired
+    private UpDownloaderFactory upDownloaderFactory;
+    @Autowired
     private CompanyInfoService companyInfoService;
 
     /**
-     * 新增公司信息管理数据。
+     * 新增公司信息管理数据,及其关联的从表数据
      *
-     * @param companyInfoDto 新增对象。
+     * @param companyInfoDto 新增主表对象。
+     * @param contentCompanyDto 一对一公司富文本管理从表Dto。
      * @return 应答结果对象,包含新增对象主键Id。
      */
     @ApiOperationSupport(ignoreParameters = {"companyInfoDto.id", "companyInfoDto.searchString"})
     @SaCheckPermission("companyInfo.add")
     @OperationLog(type = SysOperationLogType.ADD)
     @PostMapping("/add")
-    public ResponseResult<Long> add(@MyRequestBody CompanyInfoDto companyInfoDto) {
-        String errorMessage = MyCommonUtil.getModelValidationError(companyInfoDto, false);
-        if (errorMessage != null) {
-            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
+    public ResponseResult<Long> add(
+            @MyRequestBody CompanyInfoDto companyInfoDto,
+            @MyRequestBody ContentCompanyDto contentCompanyDto) {
+        ResponseResult<Tuple2<CompanyInfo, JSONObject>> verifyResult =
+                this.doBusinessDataVerifyAndConvert(companyInfoDto, false, contentCompanyDto);
+        if (!verifyResult.isSuccess()) {
+            return ResponseResult.errorFrom(verifyResult);
         }
-        CompanyInfo companyInfo = MyModelUtil.copyTo(companyInfoDto, CompanyInfo.class);
-        companyInfo = companyInfoService.saveNew(companyInfo);
+        Tuple2<CompanyInfo, JSONObject> bizData = verifyResult.getData();
+        CompanyInfo companyInfo = bizData.getFirst();
+        companyInfo = companyInfoService.saveNewWithRelation(companyInfo, bizData.getSecond());
         return ResponseResult.success(companyInfo.getId());
     }
 
     /**
-     * 更新公司信息管理数据。
+     * 修改公司信息管理数据,及其关联的从表数据。
      *
-     * @param companyInfoDto 更新对象。
-     * @return 应答结果对象。
+     * @param companyInfoDto 修改后的对象。
+     * @param contentCompanyDto 一对一公司富文本管理从表Dto。
+     * @return 应答结果对象,包含新增对象主键Id。
      */
-    @ApiOperationSupport(ignoreParameters = {"companyInfoDto.searchString"})
+    @ApiOperationSupport(ignoreParameters = {"companyInfoDto.id", "companyInfoDto.searchString"})
     @SaCheckPermission("companyInfo.update")
     @OperationLog(type = SysOperationLogType.UPDATE)
     @PostMapping("/update")
-    public ResponseResult<Void> update(@MyRequestBody CompanyInfoDto companyInfoDto) {
-        String errorMessage = MyCommonUtil.getModelValidationError(companyInfoDto, true);
-        if (errorMessage != null) {
-            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
+    public ResponseResult<Long> update(
+            @MyRequestBody CompanyInfoDto companyInfoDto,
+            @MyRequestBody ContentCompanyDto contentCompanyDto) {
+        String errorMessage;
+        ResponseResult<Tuple2<CompanyInfo, JSONObject>> verifyResult =
+                this.doBusinessDataVerifyAndConvert(companyInfoDto, true, contentCompanyDto);
+        if (!verifyResult.isSuccess()) {
+            return ResponseResult.errorFrom(verifyResult);
         }
-        CompanyInfo companyInfo = MyModelUtil.copyTo(companyInfoDto, CompanyInfo.class);
-        CompanyInfo originalCompanyInfo = companyInfoService.getById(companyInfo.getId());
-        if (originalCompanyInfo == null) {
-            // NOTE: 修改下面方括号中的话述
-            errorMessage = "数据验证失败,当前 [数据] 并不存在,请刷新后重试!";
+        Tuple2<CompanyInfo, JSONObject> bizData = verifyResult.getData();
+        CompanyInfo originalCompanyInfo = bizData.getSecond().getObject("originalData", CompanyInfo.class);
+        CompanyInfo companyInfo = bizData.getFirst();
+        if (!companyInfoService.updateWithRelation(companyInfo, originalCompanyInfo, bizData.getSecond())) {
+            errorMessage = "数据验证失败,[CompanyInfo] 数据不存在!";
             return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
         }
-        if (!companyInfoService.update(companyInfo, originalCompanyInfo)) {
-            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
-        }
-        return ResponseResult.success();
+        return ResponseResult.success(companyInfo.getId());
     }
 
     /**
@@ -179,6 +198,11 @@ public class CompanyInfoController {
         Set<String> translatedDictFieldSet = new HashSet<>();
         List<CompanyInfo> dataList =
                 ImportUtil.doImport(headerInfos, skipHeader, filename, CompanyInfo.class, translatedDictFieldSet);
+        CallResult result = companyInfoService.verifyImportList(dataList, translatedDictFieldSet);
+        if (!result.isSuccess()) {
+            // result中返回了具体的验证失败对象,如果需要返回更加详细的错误,可根据实际情况手动修改。
+            return ResponseResult.errorFrom(result);
+        }
         companyInfoService.saveNewBatch(dataList, -1);
         return ResponseResult.success();
     }
@@ -203,15 +227,16 @@ public class CompanyInfoController {
         // 导出文件的标题数组
         // NOTE: 下面的代码中仅仅导出了主表数据,主表聚合计算数据和主表关联字典的数据。
         // 一对一从表数据的导出,可根据需要自行添加。如:headerMap.put("slaveFieldName.xxxField", "标题名称")
-        Map<String, String> headerMap = new LinkedHashMap<>(13);
+        Map<String, String> headerMap = new LinkedHashMap<>(14);
         headerMap.put("id", "主键id");
         headerMap.put("companyName", "公司名称");
         headerMap.put("address", "公司地址");
         headerMap.put("establishDate", "成立日期");
         headerMap.put("telephone", "联系电话");
         headerMap.put("website", "公司网站链接");
-        headerMap.put("companyType", "公司类型");
+        headerMap.put("companyTypeDictMap.name", "公司类型");
         headerMap.put("email", "公司邮箱");
+        headerMap.put("companyUrl", "公司图片");
         headerMap.put("createUserId", "创建用户");
         headerMap.put("createTime", "创建时间");
         headerMap.put("updateUserId", "更新用户");
@@ -237,6 +262,136 @@ public class CompanyInfoController {
         return ResponseResult.success(companyInfoVo);
     }
 
+    /**
+     * 附件文件下载。
+     * 这里将图片和其他类型的附件文件放到不同的父目录下,主要为了便于今后图片文件的迁移。
+     *
+     * @param id 附件所在记录的主键Id。
+     * @param fieldName 附件所属的字段名。
+     * @param filename  文件名。如果没有提供该参数,就从当前记录的指定字段中读取。
+     * @param asImage   下载文件是否为图片。
+     * @param response  Http 应答对象。
+     */
+    @SaCheckPermission("companyInfo.view")
+    @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 {
+                CompanyInfo companyInfo = companyInfoService.getById(id);
+                if (companyInfo == null) {
+                    ResponseResult.output(HttpServletResponse.SC_NOT_FOUND);
+                    return;
+                }
+                String fieldJsonData = (String) ReflectUtil.getFieldValue(companyInfo, 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(CompanyInfo.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(),
+                    CompanyInfo.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("companyInfo.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(CompanyInfo.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(), CompanyInfo.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<Tuple2<CompanyInfo, JSONObject>> doBusinessDataVerifyAndConvert(
+            CompanyInfoDto companyInfoDto,
+            boolean forUpdate,
+            ContentCompanyDto contentCompanyDto) {
+        ErrorCodeEnum errorCode = ErrorCodeEnum.DATA_VALIDATED_FAILED;
+        String errorMessage = MyCommonUtil.getModelValidationError(companyInfoDto, false);
+        if (errorMessage != null) {
+            return ResponseResult.error(errorCode, errorMessage);
+        }
+        errorMessage = MyCommonUtil.getModelValidationError(contentCompanyDto);
+        if (errorMessage != null) {
+            return ResponseResult.error(errorCode, "参数 [contentCompanyDto] " + errorMessage);
+        }
+        // 全部关联从表数据的验证和转换
+        JSONObject relationData = new JSONObject();
+        CallResult verifyResult;
+        // 下面是输入参数中,主表关联数据的验证。
+        CompanyInfo companyInfo = MyModelUtil.copyTo(companyInfoDto, CompanyInfo.class);
+        CompanyInfo originalData;
+        if (forUpdate && companyInfo != null) {
+            originalData = companyInfoService.getById(companyInfo.getId());
+            if (originalData == null) {
+                return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
+            }
+            relationData.put("originalData", originalData);
+        }
+        // 处理主表的一对一关联 [ContentCompany]
+        ContentCompany contentCompany = MyModelUtil.copyTo(contentCompanyDto, ContentCompany.class);
+        relationData.put("contentCompany", contentCompany);
+        return ResponseResult.success(new Tuple2<>(companyInfo, relationData));
+    }
+
     private ResponseResult<Void> doDelete(Long id) {
         String errorMessage;
         // 验证关联Id的数据合法性

+ 179 - 0
application-webadmin/src/main/java/com/tourism/webadmin/app/controller/ContentCompanyController.java

@@ -0,0 +1,179 @@
+package com.tourism.webadmin.app.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.app.vo.*;
+import com.tourism.webadmin.app.dto.*;
+import com.tourism.webadmin.app.model.*;
+import com.tourism.webadmin.app.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/contentCompany")
+public class ContentCompanyController {
+
+    @Autowired
+    private ContentCompanyService contentCompanyService;
+
+    /**
+     * 新增公司富文本管理数据。
+     *
+     * @param contentCompanyDto 新增对象。
+     * @return 应答结果对象,包含新增对象主键Id。
+     */
+    @ApiOperationSupport(ignoreParameters = {"contentCompanyDto.id"})
+    @SaCheckPermission("contentCompany.add")
+    @OperationLog(type = SysOperationLogType.ADD)
+    @PostMapping("/add")
+    public ResponseResult<Long> add(@MyRequestBody ContentCompanyDto contentCompanyDto) {
+        String errorMessage = MyCommonUtil.getModelValidationError(contentCompanyDto, false);
+        if (errorMessage != null) {
+            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
+        }
+        ContentCompany contentCompany = MyModelUtil.copyTo(contentCompanyDto, ContentCompany.class);
+        contentCompany = contentCompanyService.saveNew(contentCompany);
+        return ResponseResult.success(contentCompany.getId());
+    }
+
+    /**
+     * 更新公司富文本管理数据。
+     *
+     * @param contentCompanyDto 更新对象。
+     * @return 应答结果对象。
+     */
+    @SaCheckPermission("contentCompany.update")
+    @OperationLog(type = SysOperationLogType.UPDATE)
+    @PostMapping("/update")
+    public ResponseResult<Void> update(@MyRequestBody ContentCompanyDto contentCompanyDto) {
+        String errorMessage = MyCommonUtil.getModelValidationError(contentCompanyDto, true);
+        if (errorMessage != null) {
+            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
+        }
+        ContentCompany contentCompany = MyModelUtil.copyTo(contentCompanyDto, ContentCompany.class);
+        ContentCompany originalContentCompany = contentCompanyService.getById(contentCompany.getId());
+        if (originalContentCompany == null) {
+            // NOTE: 修改下面方括号中的话述
+            errorMessage = "数据验证失败,当前 [数据] 并不存在,请刷新后重试!";
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
+        }
+        if (!contentCompanyService.update(contentCompany, originalContentCompany)) {
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
+        }
+        return ResponseResult.success();
+    }
+
+    /**
+     * 删除公司富文本管理数据。
+     *
+     * @param id 删除对象主键Id。
+     * @return 应答结果对象。
+     */
+    @SaCheckPermission("contentCompany.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("contentCompany.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 contentCompanyDtoFilter 过滤对象。
+     * @param orderParam 排序参数。
+     * @param pageParam 分页参数。
+     * @return 应答结果对象,包含查询结果集。
+     */
+    @SaCheckPermission("contentCompany.view")
+    @PostMapping("/list")
+    public ResponseResult<MyPageData<ContentCompanyVo>> list(
+            @MyRequestBody ContentCompanyDto contentCompanyDtoFilter,
+            @MyRequestBody MyOrderParam orderParam,
+            @MyRequestBody MyPageParam pageParam) {
+        if (pageParam != null) {
+            PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize(), pageParam.getCount());
+        }
+        ContentCompany contentCompanyFilter = MyModelUtil.copyTo(contentCompanyDtoFilter, ContentCompany.class);
+        String orderBy = MyOrderParam.buildOrderBy(orderParam, ContentCompany.class);
+        List<ContentCompany> contentCompanyList =
+                contentCompanyService.getContentCompanyListWithRelation(contentCompanyFilter, orderBy);
+        return ResponseResult.success(MyPageUtil.makeResponseData(contentCompanyList, ContentCompanyVo.class));
+    }
+
+    /**
+     * 查看指定公司富文本管理对象详情。
+     *
+     * @param id 指定对象主键Id。
+     * @return 应答结果对象,包含对象详情。
+     */
+    @SaCheckPermission("contentCompany.view")
+    @GetMapping("/view")
+    public ResponseResult<ContentCompanyVo> view(@RequestParam Long id) {
+        ContentCompany contentCompany = contentCompanyService.getByIdWithRelation(id, MyRelationParam.full());
+        if (contentCompany == null) {
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
+        }
+        ContentCompanyVo contentCompanyVo = MyModelUtil.copyTo(contentCompany, ContentCompanyVo.class);
+        return ResponseResult.success(contentCompanyVo);
+    }
+
+    private ResponseResult<Void> doDelete(Long id) {
+        String errorMessage;
+        // 验证关联Id的数据合法性
+        ContentCompany originalContentCompany = contentCompanyService.getById(id);
+        if (originalContentCompany == null) {
+            // NOTE: 修改下面方括号中的话述
+            errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
+        }
+        if (!contentCompanyService.remove(id)) {
+            errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
+            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
+        }
+        return ResponseResult.success();
+    }
+}

+ 33 - 0
application-webadmin/src/main/java/com/tourism/webadmin/app/dao/ContentCompanyMapper.java

@@ -0,0 +1,33 @@
+package com.tourism.webadmin.app.dao;
+
+import com.tourism.common.core.base.dao.BaseDaoMapper;
+import com.tourism.webadmin.app.model.ContentCompany;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.*;
+
+/**
+ * 公司富文本管理数据操作访问接口。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+public interface ContentCompanyMapper extends BaseDaoMapper<ContentCompany> {
+
+    /**
+     * 批量插入对象列表。
+     *
+     * @param contentCompanyList 新增对象列表。
+     */
+    void insertList(List<ContentCompany> contentCompanyList);
+
+    /**
+     * 获取过滤后的对象列表。
+     *
+     * @param contentCompanyFilter 主表过滤对象。
+     * @param orderBy 排序字符串,order by从句的参数。
+     * @return 对象列表。
+     */
+    List<ContentCompany> getContentCompanyList(
+            @Param("contentCompanyFilter") ContentCompany contentCompanyFilter, @Param("orderBy") String orderBy);
+}

+ 3 - 0
application-webadmin/src/main/java/com/tourism/webadmin/app/dao/mapper/CompanyInfoMapper.xml

@@ -10,6 +10,7 @@
         <result column="website" jdbcType="VARCHAR" property="website"/>
         <result column="company_type" jdbcType="TINYINT" property="companyType"/>
         <result column="email" jdbcType="VARCHAR" property="email"/>
+        <result column="company_url" jdbcType="VARCHAR" property="companyUrl"/>
         <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"/>
@@ -27,6 +28,7 @@
             website,
             company_type,
             email,
+            company_url,
             create_user_id,
             create_time,
             update_user_Id,
@@ -42,6 +44,7 @@
             #{item.website},
             #{item.companyType},
             #{item.email},
+            #{item.companyUrl},
             #{item.createUserId},
             #{item.createTime},
             #{item.updateUserId},

+ 60 - 0
application-webadmin/src/main/java/com/tourism/webadmin/app/dao/mapper/ContentCompanyMapper.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.app.dao.ContentCompanyMapper">
+    <resultMap id="BaseResultMap" type="com.tourism.webadmin.app.model.ContentCompany">
+        <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_content_company
+            (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.app.dao.ContentCompanyMapper.inputFilterRef"/>
+        AND tour_content_company.data_state = ${@com.tourism.common.core.constant.GlobalDeletedFlag@NORMAL}
+    </sql>
+
+    <!-- 这里仅包含调用接口输入的主表过滤条件 -->
+    <sql id="inputFilterRef">
+        <if test="contentCompanyFilter != null">
+        </if>
+    </sql>
+
+    <select id="getContentCompanyList" resultMap="BaseResultMap" parameterType="com.tourism.webadmin.app.model.ContentCompany">
+        SELECT * FROM tour_content_company
+        <where>
+            <include refid="filterRef"/>
+        </where>
+        <if test="orderBy != null and orderBy != ''">
+            ORDER BY ${orderBy}
+        </if>
+    </select>
+</mapper>

+ 9 - 0
application-webadmin/src/main/java/com/tourism/webadmin/app/dto/CompanyInfoDto.java

@@ -1,6 +1,8 @@
 package com.tourism.webadmin.app.dto;
 
 import com.tourism.common.core.validator.UpdateGroup;
+import com.tourism.common.core.validator.ConstDictRef;
+import com.tourism.webadmin.app.model.constant.CompanyType;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
@@ -65,6 +67,7 @@ public class CompanyInfoDto {
      */
     @Schema(description = "公司类型。", requiredMode = Schema.RequiredMode.REQUIRED)
     @NotNull(message = "数据验证失败,公司类型不能为空!")
+    @ConstDictRef(constDictClass = CompanyType.class, message = "数据验证失败,公司类型为无效值!")
     private Integer companyType;
 
     /**
@@ -75,6 +78,12 @@ public class CompanyInfoDto {
     private String email;
 
     /**
+     * 公司图片。
+     */
+    @Schema(description = "公司图片上传地址。")
+    private String companyUrl;
+
+    /**
      * 更新用户。
      */
     @Schema(description = "更新用户。")

+ 40 - 0
application-webadmin/src/main/java/com/tourism/webadmin/app/dto/ContentCompanyDto.java

@@ -0,0 +1,40 @@
+package com.tourism.webadmin.app.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 = "ContentCompanyDto对象")
+@Data
+public class ContentCompanyDto {
+
+    /**
+     * 主键id。
+     */
+    @Schema(description = "主键id。", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "数据验证失败,主键id不能为空!", groups = {UpdateGroup.class})
+    private Long id;
+
+    /**
+     * 富文本内容。
+     */
+    @Schema(description = "富文本内容。", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotBlank(message = "数据验证失败,富文本内容不能为空!")
+    private String content;
+
+    /**
+     * 关联表id。
+     */
+    @Schema(description = "关联表id。", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "数据验证失败,关联表id不能为空!", groups = {UpdateGroup.class})
+    private Long associationId;
+}

+ 24 - 0
application-webadmin/src/main/java/com/tourism/webadmin/app/model/CompanyInfo.java

@@ -1,10 +1,14 @@
 package com.tourism.webadmin.app.model;
 
 import com.baomidou.mybatisplus.annotation.*;
+import com.tourism.webadmin.app.model.constant.CompanyType;
 import com.tourism.common.core.util.MyCommonUtil;
+import com.tourism.common.core.upload.UploadStoreTypeEnum;
+import com.tourism.common.core.annotation.*;
 import lombok.Data;
 
 import java.util.Date;
+import java.util.Map;
 
 /**
  * 公司信息管理实体对象。
@@ -65,6 +69,13 @@ public class CompanyInfo {
     private String email;
 
     /**
+     * 公司图片。
+     */
+    @UploadFlagColumn(storeType = UploadStoreTypeEnum.LOCAL_SYSTEM)
+    @TableField(value = "company_url")
+    private String companyUrl;
+
+    /**
      * 创建用户。
      */
     @TableField(value = "create_user_id")
@@ -104,4 +115,17 @@ public class CompanyInfo {
     public void setSearchString(String searchString) {
         this.searchString = MyCommonUtil.replaceSqlWildcard(searchString);
     }
+
+    @RelationOneToOne(
+            masterIdField = "id",
+            slaveModelClass = ContentCompany.class,
+            slaveIdField = "associationId")
+    @TableField(exist = false)
+    private ContentCompany contentCompany;
+
+    @RelationConstDict(
+            masterIdField = "companyType",
+            constantDictClass = CompanyType.class)
+    @TableField(exist = false)
+    private Map<String, Object> companyTypeDictMap;
 }

+ 43 - 0
application-webadmin/src/main/java/com/tourism/webadmin/app/model/ContentCompany.java

@@ -0,0 +1,43 @@
+package com.tourism.webadmin.app.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_content_company")
+public class ContentCompany 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;
+}

+ 32 - 0
application-webadmin/src/main/java/com/tourism/webadmin/app/service/CompanyInfoService.java

@@ -1,6 +1,8 @@
 package com.tourism.webadmin.app.service;
 
+import com.alibaba.fastjson.JSONObject;
 import com.tourism.webadmin.app.model.*;
+import com.tourism.common.core.object.CallResult;
 import com.tourism.common.core.base.service.IBaseService;
 
 import java.util.*;
@@ -37,6 +39,15 @@ public interface CompanyInfoService extends IBaseService<CompanyInfo, Long> {
     void saveNewBatch(List<CompanyInfo> companyInfoList, int batchSize);
 
     /**
+     * 保存新增主表对象及关联对象。
+     *
+     * @param companyInfo 新增主表对象。
+     * @param relationData 全部关联从表数据。
+     * @return 返回新增主表对象。
+     */
+    CompanyInfo saveNewWithRelation(CompanyInfo companyInfo, JSONObject relationData);
+
+    /**
      * 更新数据对象。
      *
      * @param companyInfo         更新的对象。
@@ -46,6 +57,16 @@ public interface CompanyInfoService extends IBaseService<CompanyInfo, Long> {
     boolean update(CompanyInfo companyInfo, CompanyInfo originalCompanyInfo);
 
     /**
+     * 更新主表对象及关联对象。
+     *
+     * @param companyInfo 主表对象新数据。
+     * @param originalCompanyInfo 主表对象源数据。
+     * @param relationData 全部关联从表数据。
+     * @return 修改成功返回true,否则false。
+     */
+    boolean updateWithRelation(CompanyInfo companyInfo, CompanyInfo originalCompanyInfo, JSONObject relationData);
+
+    /**
      * 删除指定数据。
      *
      * @param id 主键Id。
@@ -73,4 +94,15 @@ public interface CompanyInfoService extends IBaseService<CompanyInfo, Long> {
      * @return 查询结果集。
      */
     List<CompanyInfo> getCompanyInfoListWithRelation(CompanyInfo filter, String orderBy);
+
+    /**
+     * 对批量导入数据列表进行数据合法性验证。
+     * 验证逻辑主要覆盖主表的常量字典字段、字典表字典字段、数据源字段和一对一关联数据是否存在。
+     *
+     * @param dataList 主表的数据列表。
+     * @param ignoreFieldSet 需要忽略校验的字典字段集合。通常对于字典反向翻译过来的字段适用,
+     *                       避免了二次验证,以提升效率。
+     * @return 验证结果。如果失败,包含具体的错误信息和导致错误的数据对象。
+     */
+    CallResult verifyImportList(List<CompanyInfo> dataList, Set<String> ignoreFieldSet);
 }

+ 76 - 0
application-webadmin/src/main/java/com/tourism/webadmin/app/service/ContentCompanyService.java

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

+ 57 - 1
application-webadmin/src/main/java/com/tourism/webadmin/app/service/impl/CompanyInfoServiceImpl.java

@@ -1,6 +1,7 @@
 package com.tourism.webadmin.app.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.tourism.webadmin.app.service.*;
 import com.tourism.webadmin.app.dao.*;
@@ -9,6 +10,7 @@ import com.tourism.common.core.base.dao.BaseDaoMapper;
 import com.tourism.common.core.constant.GlobalDeletedFlag;
 import com.tourism.common.core.object.TokenData;
 import com.tourism.common.core.object.MyRelationParam;
+import com.tourism.common.core.object.CallResult;
 import com.tourism.common.core.base.service.BaseService;
 import com.tourism.common.sequence.wrapper.IdGeneratorWrapper;
 import com.github.pagehelper.Page;
@@ -33,6 +35,8 @@ public class CompanyInfoServiceImpl extends BaseService<CompanyInfo, Long> imple
     private IdGeneratorWrapper idGenerator;
     @Autowired
     private CompanyInfoMapper companyInfoMapper;
+    @Autowired
+    private ContentCompanyService contentCompanyService;
 
     /**
      * 返回当前Service的主表Mapper对象。
@@ -87,6 +91,14 @@ public class CompanyInfoServiceImpl extends BaseService<CompanyInfo, Long> imple
 
     @Transactional(rollbackFor = Exception.class)
     @Override
+    public CompanyInfo saveNewWithRelation(CompanyInfo companyInfo, JSONObject relationData) {
+        this.saveNew(companyInfo);
+        this.saveOrUpdateOneToOneRelationData(companyInfo, relationData);
+        return companyInfo;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
     public boolean update(CompanyInfo companyInfo, CompanyInfo originalCompanyInfo) {
         companyInfo.setCreateUserId(originalCompanyInfo.getCreateUserId());
         companyInfo.setCreateTime(originalCompanyInfo.getCreateTime());
@@ -98,8 +110,34 @@ public class CompanyInfoServiceImpl extends BaseService<CompanyInfo, Long> imple
 
     @Transactional(rollbackFor = Exception.class)
     @Override
+    public boolean updateWithRelation(
+            CompanyInfo companyInfo, CompanyInfo originalCompanyInfo, JSONObject relationData) {
+        // companyInfo 为空的时候,无需修改主表数据。
+        if (companyInfo != null && !this.update(companyInfo, originalCompanyInfo)) {
+            return false;
+        }
+        this.saveOrUpdateOneToOneRelationData(originalCompanyInfo, relationData);
+        return true;
+    }
+
+    private void saveOrUpdateOneToOneRelationData(CompanyInfo companyInfo, JSONObject relationData) {
+        // 对于一对一新增或更新,如果主键值为空就新增,否则就更新,同时更新updateTime和updateUserId。
+        ContentCompany contentCompany = relationData.getObject("contentCompany", ContentCompany.class);
+        if (contentCompany != null) {
+            contentCompany.setAssociationId(companyInfo.getId());
+            contentCompanyService.saveNewOrUpdate(contentCompany,
+                    contentCompanyService::saveNew, contentCompanyService::update);
+        }
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
     public boolean remove(Long id) {
-        return companyInfoMapper.deleteById(id) == 1;
+        if (companyInfoMapper.deleteById(id) == 0) {
+            return false;
+        }
+        contentCompanyService.removeByAssociationId(id);
+        return true;
     }
 
     @Override
@@ -117,6 +155,24 @@ public class CompanyInfoServiceImpl extends BaseService<CompanyInfo, Long> imple
         return resultList;
     }
 
+    @Override
+    public CallResult verifyImportList(List<CompanyInfo> dataList, Set<String> ignoreFieldSet) {
+        CallResult callResult;
+        if (!CollUtil.contains(ignoreFieldSet, "companyType")) {
+            callResult = verifyImportForConstDict(dataList, "companyTypeDictMap", CompanyInfo::getCompanyType);
+            if (!callResult.isSuccess()) {
+                return callResult;
+            }
+        }
+        if (!CollUtil.contains(ignoreFieldSet, "id")) {
+            callResult = verifyImportForOneToOneRelation(dataList, "ContentCompany", CompanyInfo::getId);
+            if (!callResult.isSuccess()) {
+                return callResult;
+            }
+        }
+        return CallResult.ok();
+    }
+
     private CompanyInfo buildDefaultValue(CompanyInfo companyInfo) {
         if (companyInfo.getId() == null) {
             companyInfo.setId(idGenerator.nextLongId());

+ 104 - 0
application-webadmin/src/main/java/com/tourism/webadmin/app/service/impl/ContentCompanyServiceImpl.java

@@ -0,0 +1,104 @@
+package com.tourism.webadmin.app.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.app.service.*;
+import com.tourism.webadmin.app.dao.*;
+import com.tourism.webadmin.app.model.*;
+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("contentCompanyService")
+public class ContentCompanyServiceImpl extends BaseService<ContentCompany, Long> implements ContentCompanyService {
+
+    @Autowired
+    private ContentCompanyMapper contentCompanyMapper;
+
+    /**
+     * 返回当前Service的主表Mapper对象。
+     *
+     * @return 主表Mapper对象。
+     */
+    @Override
+    protected BaseDaoMapper<ContentCompany> mapper() {
+        return contentCompanyMapper;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public ContentCompany saveNew(ContentCompany contentCompany) {
+        contentCompanyMapper.insert(this.buildDefaultValue(contentCompany));
+        return contentCompany;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void saveNewBatch(List<ContentCompany> contentCompanyList) {
+        if (CollUtil.isNotEmpty(contentCompanyList)) {
+            contentCompanyList.forEach(this::buildDefaultValue);
+            contentCompanyMapper.insertList(contentCompanyList);
+        }
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean update(ContentCompany contentCompany, ContentCompany originalContentCompany) {
+        MyModelUtil.fillCommonsForUpdate(contentCompany, originalContentCompany);
+        // 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。
+        UpdateWrapper<ContentCompany> uw = this.createUpdateQueryForNullValue(contentCompany, contentCompany.getId());
+        return contentCompanyMapper.update(contentCompany, uw) == 1;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean remove(Long id) {
+        return contentCompanyMapper.deleteById(id) == 1;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public int removeByAssociationId(Long associationId) {
+        ContentCompany deletedObject = new ContentCompany();
+        deletedObject.setAssociationId(associationId);
+        return contentCompanyMapper.delete(new QueryWrapper<>(deletedObject));
+    }
+
+    @Override
+    public List<ContentCompany> getContentCompanyList(ContentCompany filter, String orderBy) {
+        return contentCompanyMapper.getContentCompanyList(filter, orderBy);
+    }
+
+    @Override
+    public List<ContentCompany> getContentCompanyListWithRelation(ContentCompany filter, String orderBy) {
+        List<ContentCompany> resultList = contentCompanyMapper.getContentCompanyList(filter, orderBy);
+        // 在缺省生成的代码中,如果查询结果resultList不是Page对象,说明没有分页,那么就很可能是数据导出接口调用了当前方法。
+        // 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
+        int batchSize = resultList instanceof Page ? 0 : 1000;
+        this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
+        return resultList;
+    }
+
+    private ContentCompany buildDefaultValue(ContentCompany contentCompany) {
+        MyModelUtil.fillCommonsForInsert(contentCompany);
+        contentCompany.setDataState(GlobalDeletedFlag.NORMAL);
+        return contentCompany;
+    }
+}

+ 0 - 244
application-webadmin/src/main/java/com/tourism/webadmin/app/util/FlowIdentityExtHelper.java

@@ -1,244 +0,0 @@
-package com.tourism.webadmin.app.util;
-
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.collection.CollUtil;
-import com.tourism.common.flow.util.BaseFlowIdentityExtHelper;
-import com.tourism.common.flow.util.FlowCustomExtFactory;
-import com.tourism.common.flow.vo.FlowUserInfoVo;
-import com.tourism.webadmin.upms.model.SysDept;
-import com.tourism.webadmin.upms.model.SysUser;
-import com.tourism.webadmin.upms.model.constant.SysUserStatus;
-import com.tourism.webadmin.upms.model.SysDeptPost;
-import com.tourism.webadmin.upms.service.SysDeptService;
-import com.tourism.webadmin.upms.service.SysUserService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import jakarta.annotation.PostConstruct;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * 为流程提供所需的用户身份相关的等扩展信息的帮助类。
- *
- * @author 吃饭睡觉
- * @date 2024-09-06
- */
-@Slf4j
-@Component
-public class FlowIdentityExtHelper implements BaseFlowIdentityExtHelper {
-
-    @Autowired
-    private SysDeptService sysDeptService;
-    @Autowired
-    private SysUserService sysUserService;
-    @Autowired
-    private FlowCustomExtFactory flowCustomExtFactory;
-
-    @PostConstruct
-    public void doRegister() {
-        flowCustomExtFactory.registerFlowIdentityExtHelper(this);
-    }
-
-    @Override
-    public Long getLeaderDeptPostId(Long deptId) {
-        List<Long> deptPostIdList = sysDeptService.getLeaderDeptPostIdList(deptId);
-        return CollUtil.isEmpty(deptPostIdList) ? null : deptPostIdList.get(0);
-    }
-
-    @Override
-    public Long getUpLeaderDeptPostId(Long deptId) {
-        List<Long> deptPostIdList = sysDeptService.getUpLeaderDeptPostIdList(deptId);
-        return CollUtil.isEmpty(deptPostIdList) ? null : deptPostIdList.get(0);
-    }
-
-    @Override
-    public Map<String, String> getDeptPostIdMap(Long deptId, Set<String> postIdSet) {
-        Set<Long> postIdSet2 = postIdSet.stream().map(Long::valueOf).collect(Collectors.toSet());
-        List<SysDeptPost> deptPostList = sysDeptService.getSysDeptPostList(deptId, postIdSet2);
-        if (CollUtil.isEmpty(deptPostList)) {
-            return null;
-        }
-        Map<String, String> resultMap = new HashMap<>(deptPostList.size());
-        deptPostList.forEach(sysDeptPost ->
-                resultMap.put(sysDeptPost.getPostId().toString(), sysDeptPost.getDeptPostId().toString()));
-        return resultMap;
-    }
-
-    @Override
-    public Map<String, String> getSiblingDeptPostIdMap(Long deptId, Set<String> postIdSet) {
-        Set<Long> postIdSet2 = postIdSet.stream().map(Long::valueOf).collect(Collectors.toSet());
-        List<SysDeptPost> deptPostList = sysDeptService.getSiblingSysDeptPostList(deptId, postIdSet2);
-        if (CollUtil.isEmpty(deptPostList)) {
-            return null;
-        }
-        Map<String, String> resultMap = new HashMap<>(deptPostList.size());
-        for (SysDeptPost deptPost : deptPostList) {
-            String deptPostId = resultMap.get(deptPost.getPostId().toString());
-            if (deptPostId != null) {
-                deptPostId = deptPostId + "," + deptPost.getDeptPostId();
-            } else {
-                deptPostId = deptPost.getDeptPostId().toString();
-            }
-            resultMap.put(deptPost.getPostId().toString(), deptPostId);
-        }
-        return resultMap;
-    }
-
-    @Override
-    public Map<String, String> getUpDeptPostIdMap(Long deptId, Set<String> postIdSet) {
-        SysDept sysDept = sysDeptService.getById(deptId);
-        if (sysDept == null || sysDept.getParentId() == null) {
-            return null;
-        }
-        return getDeptPostIdMap(sysDept.getParentId(), postIdSet);
-    }
-
-    @Override
-    public Set<String> getUsernameListByRoleIds(Set<String> roleIdSet) {
-        Set<String> usernameSet = new HashSet<>();
-        Set<Long> roleIdSet2 = roleIdSet.stream().map(Long::valueOf).collect(Collectors.toSet());
-        SysUser filter = new SysUser();
-        filter.setUserStatus(SysUserStatus.STATUS_NORMAL);
-        for (Long roleId : roleIdSet2) {
-            List<SysUser> userList = sysUserService.getSysUserListByRoleId(roleId, filter, null);
-            this.extractAndAppendUsernameList(usernameSet, userList);
-        }
-        return usernameSet;
-    }
-
-    @Override
-    public List<FlowUserInfoVo> getUserInfoListByRoleIds(Set<String> roleIdSet) {
-        List<FlowUserInfoVo> resultList = new LinkedList<>();
-        Set<Long> roleIdSet2 = roleIdSet.stream().map(Long::valueOf).collect(Collectors.toSet());
-        SysUser filter = new SysUser();
-        filter.setUserStatus(SysUserStatus.STATUS_NORMAL);
-        for (Long roleId : roleIdSet2) {
-            List<SysUser> userList = sysUserService.getSysUserListByRoleId(roleId, filter, null);
-            if (CollUtil.isNotEmpty(userList)) {
-                resultList.addAll(BeanUtil.copyToList(userList, FlowUserInfoVo.class));
-            }
-        }
-        return resultList;
-    }
-
-    @Override
-    public Set<String> getUsernameListByDeptIds(Set<String> deptIdSet) {
-        Set<String> usernameSet = new HashSet<>();
-        Set<Long> deptIdSet2 = deptIdSet.stream().map(Long::valueOf).collect(Collectors.toSet());
-        for (Long deptId : deptIdSet2) {
-            SysUser filter = new SysUser();
-            filter.setDeptId(deptId);
-            filter.setUserStatus(SysUserStatus.STATUS_NORMAL);
-            List<SysUser> userList = sysUserService.getSysUserList(filter, null);
-            this.extractAndAppendUsernameList(usernameSet, userList);
-        }
-        return usernameSet;
-    }
-
-    @Override
-    public List<FlowUserInfoVo> getUserInfoListByDeptIds(Set<String> deptIdSet) {
-        List<FlowUserInfoVo> resultList = new LinkedList<>();
-        Set<Long> deptIdSet2 = deptIdSet.stream().map(Long::valueOf).collect(Collectors.toSet());
-        for (Long deptId : deptIdSet2) {
-            SysUser filter = new SysUser();
-            filter.setDeptId(deptId);
-            filter.setUserStatus(SysUserStatus.STATUS_NORMAL);
-            List<SysUser> userList = sysUserService.getSysUserList(filter, null);
-            if (CollUtil.isNotEmpty(userList)) {
-                resultList.addAll(BeanUtil.copyToList(userList, FlowUserInfoVo.class));
-            }
-        }
-        return resultList;
-    }
-
-    @Override
-    public Set<String> getUsernameListByPostIds(Set<String> postIdSet) {
-        Set<String> usernameSet = new HashSet<>();
-        Set<Long> postIdSet2 = postIdSet.stream().map(Long::valueOf).collect(Collectors.toSet());
-        SysUser filter = new SysUser();
-        filter.setUserStatus(SysUserStatus.STATUS_NORMAL);
-        for (Long postId : postIdSet2) {
-            List<SysUser> userList = sysUserService.getSysUserListByPostId(postId, filter, null);
-            this.extractAndAppendUsernameList(usernameSet, userList);
-        }
-        return usernameSet;
-    }
-
-    @Override
-    public List<FlowUserInfoVo> getUserInfoListByPostIds(Set<String> postIdSet) {
-        List<FlowUserInfoVo> resultList = new LinkedList<>();
-        Set<Long> postIdSet2 = postIdSet.stream().map(Long::valueOf).collect(Collectors.toSet());
-        SysUser filter = new SysUser();
-        filter.setUserStatus(SysUserStatus.STATUS_NORMAL);
-        for (Long postId : postIdSet2) {
-            List<SysUser> userList = sysUserService.getSysUserListByPostId(postId, filter, null);
-            if (CollUtil.isNotEmpty(userList)) {
-                resultList.addAll(BeanUtil.copyToList(userList, FlowUserInfoVo.class));
-            }
-        }
-        return resultList;
-    }
-
-    @Override
-    public Set<String> getUsernameListByDeptPostIds(Set<String> deptPostIdSet) {
-        Set<String> usernameSet = new HashSet<>();
-        Set<Long> deptPostIdSet2 = deptPostIdSet.stream().map(Long::valueOf).collect(Collectors.toSet());
-        SysUser filter = new SysUser();
-        filter.setUserStatus(SysUserStatus.STATUS_NORMAL);
-        for (Long deptPostId : deptPostIdSet2) {
-            List<SysUser> userList = sysUserService.getSysUserListByDeptPostId(deptPostId, filter, null);
-            this.extractAndAppendUsernameList(usernameSet, userList);
-        }
-        return usernameSet;
-    }
-
-    @Override
-    public List<FlowUserInfoVo> getUserInfoListByDeptPostIds(Set<String> deptPostIdSet) {
-        List<FlowUserInfoVo> resultList = new LinkedList<>();
-        Set<Long> deptPostIdSet2 = deptPostIdSet.stream().map(Long::valueOf).collect(Collectors.toSet());
-        SysUser filter = new SysUser();
-        filter.setUserStatus(SysUserStatus.STATUS_NORMAL);
-        for (Long deptPostId : deptPostIdSet2) {
-            List<SysUser> userList = sysUserService.getSysUserListByDeptPostId(deptPostId, filter, null);
-            if (CollUtil.isNotEmpty(userList)) {
-                resultList.addAll(BeanUtil.copyToList(userList, FlowUserInfoVo.class));
-            }
-        }
-        return resultList;
-    }
-
-    @Override
-    public List<FlowUserInfoVo> getUserInfoListByUsernameSet(Set<String> usernameSet) {
-        List<FlowUserInfoVo> resultList = null;
-        List<SysUser> userList = sysUserService.getInList("loginName", usernameSet);
-        if (CollUtil.isNotEmpty(userList)) {
-            resultList = BeanUtil.copyToList(userList, FlowUserInfoVo.class);
-        }
-        return resultList;
-    }
-
-    @Override
-    public Boolean supprtDataPerm() {
-        return true;
-    }
-
-    @Override
-    public Map<String, String> mapUserShowNameByLoginName(Set<String> loginNameSet) {
-        if (CollUtil.isEmpty(loginNameSet)) {
-            return new HashMap<>(1);
-        }
-        Map<String, String> resultMap = new HashMap<>(loginNameSet.size());
-        List<SysUser> userList = sysUserService.getInList("loginName", loginNameSet);
-        userList.forEach(user -> resultMap.put(user.getLoginName(), user.getShowName()));
-        return resultMap;
-    }
-
-    private void extractAndAppendUsernameList(Set<String> resultUsernameList, List<SysUser> userList) {
-        List<String> usernameList = userList.stream().map(SysUser::getLoginName).collect(Collectors.toList());
-        if (CollUtil.isNotEmpty(usernameList)) {
-            resultUsernameList.addAll(usernameList);
-        }
-    }
-}

+ 19 - 0
application-webadmin/src/main/java/com/tourism/webadmin/app/vo/CompanyInfoVo.java

@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.util.Date;
+import java.util.Map;
 
 /**
  * 公司信息管理VO视图对象。
@@ -64,6 +65,12 @@ public class CompanyInfoVo {
     private String email;
 
     /**
+     * 公司图片。
+     */
+    @Schema(description = "公司图片上传地址")
+    private String companyUrl;
+
+    /**
      * 创建用户。
      */
     @Schema(description = "创建用户")
@@ -86,4 +93,16 @@ public class CompanyInfoVo {
      */
     @Schema(description = "更新时间")
     private Date updateTime;
+
+    /**
+     * id 的一对一关联数据对象,数据对应类型为ContentCompanyVo。
+     */
+    @Schema(description = "id 的一对一关联数据对象,数据对应类型为ContentCompanyVo")
+    private Map<String, Object> contentCompany;
+
+    /**
+     * companyType 常量字典关联数据。
+     */
+    @Schema(description = "companyType 常量字典关联数据")
+    private Map<String, Object> companyTypeDictMap;
 }

+ 38 - 0
application-webadmin/src/main/java/com/tourism/webadmin/app/vo/ContentCompanyVo.java

@@ -0,0 +1,38 @@
+package com.tourism.webadmin.app.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;
+
+/**
+ * 公司富文本管理VO视图对象。
+ *
+ * @author 吃饭睡觉
+ * @date 2024-09-06
+ */
+@Schema(description = "ContentCompanyVO视图对象")
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ContentCompanyVo extends BaseVo {
+
+    /**
+     * 主键id。
+     */
+    @Schema(description = "主键id")
+    private Long id;
+
+    /**
+     * 富文本内容。
+     */
+    @Schema(description = "富文本内容")
+    private String content;
+
+    /**
+     * 关联表id。
+     */
+    @Schema(description = "关联表id")
+    private Long associationId;
+}