Browse Source

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderMapper.java
ct 1 week ago
parent
commit
6fdf1a01b2
32 changed files with 1970 additions and 1 deletions
  1. 54 0
      fs-admin/src/main/java/com/fs/crm/controller/ReportController.java
  2. 62 0
      fs-admin/src/main/java/com/fs/stats/FsStatsMemberController.java
  3. 3 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyUserMapper.java
  4. 38 0
      fs-service/src/main/java/com/fs/crm/domain/CrmCustomerAssist.java
  5. 43 0
      fs-service/src/main/java/com/fs/crm/domain/Report.java
  6. 87 0
      fs-service/src/main/java/com/fs/crm/mapper/CrmCustomerAssistMapper.java
  7. 7 0
      fs-service/src/main/java/com/fs/crm/mapper/CrmCustomerMapper.java
  8. 11 0
      fs-service/src/main/java/com/fs/crm/param/CrmCustomerAssistDeLParam.java
  9. 21 0
      fs-service/src/main/java/com/fs/crm/param/ReportParam.java
  10. 11 0
      fs-service/src/main/java/com/fs/crm/service/ReportService.java
  11. 70 0
      fs-service/src/main/java/com/fs/crm/service/impl/ReportServiceImpl.java
  12. 42 0
      fs-service/src/main/java/com/fs/his/domain/FsComplaintTemplate.java
  13. 63 0
      fs-service/src/main/java/com/fs/his/domain/FsUserComplaint.java
  14. 62 0
      fs-service/src/main/java/com/fs/his/mapper/FsComplaintTemplateMapper.java
  15. 3 0
      fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderMapper.java
  16. 63 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserComplaintMapper.java
  17. 62 0
      fs-service/src/main/java/com/fs/his/service/IFsComplaintTemplateService.java
  18. 63 0
      fs-service/src/main/java/com/fs/his/service/IFsUserComplaintService.java
  19. 94 0
      fs-service/src/main/java/com/fs/his/service/impl/FsComplaintTemplateServiceImpl.java
  20. 94 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserComplaintServiceImpl.java
  21. 88 0
      fs-service/src/main/java/com/fs/his/utils/ComplaintTreeUtil.java
  22. 16 0
      fs-service/src/main/java/com/fs/his/vo/FsComplaintTemplateVO.java
  23. 52 0
      fs-service/src/main/java/com/fs/his/vo/FsUserComplaintVo.java
  24. 138 0
      fs-service/src/main/resources/application-config-bly.yml
  25. 144 0
      fs-service/src/main/resources/application-druid-bly-test.yml
  26. 144 0
      fs-service/src/main/resources/application-druid-bly.yml
  27. 8 0
      fs-service/src/main/resources/mapper/company/CompanyUserMapper.xml
  28. 108 0
      fs-service/src/main/resources/mapper/crm/CrmCustomerAssistMapper.xml
  29. 3 1
      fs-service/src/main/resources/mapper/crm/CrmCustomerMapper.xml
  30. 86 0
      fs-service/src/main/resources/mapper/his/FsComplaintTemplateMapper.xml
  31. 108 0
      fs-service/src/main/resources/mapper/his/FsUserComplaintMapper.xml
  32. 122 0
      fs-user-app/src/main/java/com/fs/app/controller/FsUserComplaintController.java

+ 54 - 0
fs-admin/src/main/java/com/fs/crm/controller/ReportController.java

@@ -0,0 +1,54 @@
+package com.fs.crm.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.model.LoginUser;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.crm.domain.Report;
+import com.fs.framework.web.service.TokenService;
+import com.fs.crm.param.ReportParam;
+import com.fs.crm.service.ReportService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+@RestController
+@RequestMapping("/crm/report")
+public class ReportController extends BaseController {
+    @Autowired
+    private ReportService reportService;
+    @Autowired
+    private TokenService tokenService;
+    @GetMapping("/reportList")
+    public TableDataInfo getReport(ReportParam param, HttpServletRequest request)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+
+        Long userId = loginUser.getUser().getUserId();
+        param.setCompanyUserId(userId);
+        List<Report> list = reportService.getReport(param);
+        return getDataTable(list);
+    }
+    @GetMapping("/export")
+    public AjaxResult export(ReportParam param,HttpServletRequest request)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(request);
+
+        Long userId = loginUser.getUser().getUserId();
+        param.setCompanyUserId(userId);
+        List<Report> list = reportService.getReport(param);
+        if (CollectionUtils.isEmpty(list)){
+            return AjaxResult.error("请选择导出数据");
+        }
+        ExcelUtil<Report> util = new ExcelUtil<Report>(Report.class);
+        return util.exportExcel(list, "report");
+    }
+
+}

+ 62 - 0
fs-admin/src/main/java/com/fs/stats/FsStatsMemberController.java

@@ -0,0 +1,62 @@
+package com.fs.stats;
+
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.statis.service.IFsStatsMemberDailyService;
+import com.fs.statis.vo.FsStatsMemberDailyVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import lombok.AllArgsConstructor;
+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.time.LocalDate;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/stats/member")
+@AllArgsConstructor
+public class FsStatsMemberController {
+
+    private final IFsStatsMemberDailyService statsMemberDailyService;
+
+    @GetMapping("/dailyData")
+    public AjaxResult dailyData(@RequestParam String startDate,
+                                @RequestParam String endDate,
+                                @RequestParam Integer type,
+                                @RequestParam(required = false) Long companyId,
+                                @RequestParam(required = false) Long companyUserId,
+                                @RequestParam(required = false) Long userId,
+                                @RequestParam(required = false) String phone,
+                                @RequestParam(required = false) Long trainCampId,
+                                @RequestParam(required = false) Long periodId,
+                                @RequestParam(required = false) Long courseId,
+                                @RequestParam(required = false) Long videoId,
+                                @RequestParam(required = false, defaultValue = "1") Integer pageNum,
+                                @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
+        Map<String, Object> params = new HashMap<>();
+        params.put("companyId", companyId);
+        params.put("companyUserId", companyUserId);
+        params.put("userId", userId);
+        params.put("phone", phone);
+        params.put("trainCampId", trainCampId);
+        params.put("periodId", periodId);
+        params.put("courseId", courseId);
+        params.put("videoId", videoId);
+
+        if (type == 1) {
+            params.put("startDate", LocalDate.parse(startDate));
+            params.put("endDate", LocalDate.parse(endDate).plusDays(1));
+        } else {
+            params.put("startDate", LocalDate.parse(startDate).withDayOfMonth(1));
+            params.put("endDate", LocalDate.parse(endDate).withDayOfMonth(1).plusMonths(1));
+        }
+
+        PageHelper.startPage(pageNum, pageSize);
+        List<FsStatsMemberDailyVO> list = statsMemberDailyService.selectDailyData(params);
+        return AjaxResult.success(new PageInfo<>(list));
+    }
+}

+ 3 - 0
fs-service/src/main/java/com/fs/company/mapper/CompanyUserMapper.java

@@ -315,4 +315,7 @@ public interface CompanyUserMapper
 
     @Update("update company_user set doctor_id = null where user_id = #{userId}")
     public int unBindDoctorId(@Param("userId")Long userId);
+
+
+    List<String> selectCompanyUserNameByIdsList(@Param("companyUserIDs")List<Long> companyUserID);
 }

+ 38 - 0
fs-service/src/main/java/com/fs/crm/domain/CrmCustomerAssist.java

@@ -0,0 +1,38 @@
+package com.fs.crm.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+/**
+ * 客户员工协作对象 crm_customer_assist
+ *
+ * @author fs
+ * @date 2025-05-27
+ */
+@Data
+public class CrmCustomerAssist extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private Long companyId;
+
+    /** 销售ID */
+    @Excel(name = "销售ID")
+    private Long companyUserId;
+
+    /** 销售名字 */
+    @Excel(name = "销售名字")
+    private String companyUserName;
+
+    /** 销售公司ID */
+    @Excel(name = "销售公司ID")
+    private Long customerId;
+
+    private Integer Rate;
+}

+ 43 - 0
fs-service/src/main/java/com/fs/crm/domain/Report.java

@@ -0,0 +1,43 @@
+package com.fs.crm.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+public class Report {
+    //订单编号
+    @Excel(name = "订单编号")
+    private String orderSn;
+    //成单金额
+    @Excel(name = "成单金额")
+    private BigDecimal money;
+    //支付时间
+    @Excel(name = "支付时间" ,width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date payTime;
+    //订单状态
+    @Excel(name = "订单状态")
+    private String orderStatus;
+    //客户名称
+    @Excel(name = "客户名称")
+    private String userName;
+    //是否共享客户1是0否
+    @Excel(name = "是否共享客户")
+    private String status;
+    //共享销售
+    @Excel(name = "共享销售")
+    private String companyUserNames;
+    //分成比例
+    @Excel(name = "分成比例")
+    private BigDecimal proportion;
+    //我的业绩
+    @Excel(name = "我的业绩")
+    private BigDecimal myPerformance;
+    //客户id
+    @Excel(name = "客户id")
+    private Long customerId;
+}

+ 87 - 0
fs-service/src/main/java/com/fs/crm/mapper/CrmCustomerAssistMapper.java

@@ -0,0 +1,87 @@
+package com.fs.crm.mapper;
+
+import com.fs.crm.domain.CrmCustomerAssist;
+import com.fs.crm.param.CrmCustomerAssistDeLParam;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 客户员工协作Mapper接口
+ *
+ * @author fs
+ * @date 2025-05-27
+ */
+public interface CrmCustomerAssistMapper
+{
+    /**
+     * 查询客户员工协作
+     *
+     * @param id 客户员工协作ID
+     * @return 客户员工协作
+     */
+    public CrmCustomerAssist selectCrmCustomerAssistById(Long id);
+
+    /**
+     * 查询客户员工协作列表
+     *
+     * @param crmCustomerAssist 客户员工协作
+     * @return 客户员工协作集合
+     */
+    public List<CrmCustomerAssist> selectCrmCustomerAssistList(CrmCustomerAssist crmCustomerAssist);
+
+    /**
+     * 新增客户员工协作
+     *
+     * @param crmCustomerAssist 客户员工协作
+     * @return 结果
+     */
+    public int insertCrmCustomerAssist(CrmCustomerAssist crmCustomerAssist);
+
+    /**
+     * 修改客户员工协作
+     *
+     * @param crmCustomerAssist 客户员工协作
+     * @return 结果
+     */
+    public int updateCrmCustomerAssist(CrmCustomerAssist crmCustomerAssist);
+
+    /**
+     * 删除客户员工协作
+     *
+     * @param id 客户员工协作ID
+     * @return 结果
+     */
+    public int deleteCrmCustomerAssistById(Long id);
+
+    /**
+     * 批量删除客户员工协作
+     *
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteCrmCustomerAssistByIds(Long[] ids);
+
+    List<String> selectCompanyUserNameByCustomerId(@Param("customerId") Long customerId);
+
+    int removeByCustomer(@Param("maps") CrmCustomerAssistDeLParam param);
+
+    int deleteCrmCustomerAssistByCustomerId(Long customerId);
+
+    /**
+     * 查询当前销售协作的客户
+     * @param companyUserId
+     * @return
+     */
+    List<Long> selectCustomerIdByCompanyUserId(@Param("companyUserId") Long companyUserId);
+
+    /**
+     * 根据客户id查询销售
+     * @param customerId
+     * @return
+     */
+    List<Long> selectCompanyUserIdByCustomerId(@Param("customerId") Long customerId,@Param("createTime") Date createTime);
+
+    List<CrmCustomerAssist> selectByCustomerId(Long customerId);
+}

+ 7 - 0
fs-service/src/main/java/com/fs/crm/mapper/CrmCustomerMapper.java

@@ -959,4 +959,11 @@ public interface CrmCustomerMapper extends BaseMapper<CrmCustomer> {
 
     List<CrmMyCustomerListQueryVO> selectCrmMyAssistListQuery(@Param("maps") CrmMyCustomerListQueryParam param);
 
+    /**
+     * 查询当前销售的客户
+     * @param companyUserId
+     * @return
+     */
+    List<Long> selectCustomerIdByCompanyUserId(@Param("companyUserId") Long companyUserId);
+
 }

+ 11 - 0
fs-service/src/main/java/com/fs/crm/param/CrmCustomerAssistDeLParam.java

@@ -0,0 +1,11 @@
+package com.fs.crm.param;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class CrmCustomerAssistDeLParam {
+    private List<Long> customerIds;
+    private Long companyUserId;
+}

+ 21 - 0
fs-service/src/main/java/com/fs/crm/param/ReportParam.java

@@ -0,0 +1,21 @@
+package com.fs.crm.param;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.param.BaseQueryParam;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class ReportParam extends BaseQueryParam {
+    private Long companyId;
+    private Long companyUserId;
+    private Double money;
+    private String rechargeNo;
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date payTime;
+    private String status;
+    private String orderStatus;
+    private List<Long> customerIds;
+}

+ 11 - 0
fs-service/src/main/java/com/fs/crm/service/ReportService.java

@@ -0,0 +1,11 @@
+package com.fs.crm.service;
+
+
+import com.fs.crm.domain.Report;
+import com.fs.crm.param.ReportParam;
+
+import java.util.List;
+
+public interface ReportService {
+    List<Report> getReport(ReportParam param);
+}

+ 70 - 0
fs-service/src/main/java/com/fs/crm/service/impl/ReportServiceImpl.java

@@ -0,0 +1,70 @@
+package com.fs.crm.service.impl;
+
+import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.crm.domain.Report;
+import com.fs.crm.mapper.CrmCustomerAssistMapper;
+import com.fs.crm.mapper.CrmCustomerMapper;
+import com.fs.crm.service.ReportService;
+import com.fs.his.mapper.FsStoreOrderMapper;
+import com.fs.crm.param.ReportParam;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Service
+public class ReportServiceImpl implements ReportService {
+    @Autowired
+    private CrmCustomerMapper crmCustomerMapper;
+    @Autowired
+    private CrmCustomerAssistMapper crmCustomerAssistMapper;
+    @Autowired
+    private FsStoreOrderMapper storeOrderMapper;
+    @Autowired
+    private CompanyUserMapper companyUserMapper;
+    @Override
+    public List<Report> getReport(ReportParam param) {
+        Set<Long> mergedSet = new HashSet<>();
+
+        if (param.getCompanyUserId()!=null){
+            //查询当前销售的客户以及协作客户
+            List<Long> customerIds = Optional.ofNullable(crmCustomerMapper.selectCustomerIdByCompanyUserId(param.getCompanyUserId()))
+                    .orElse(Collections.emptyList());
+            List<Long> assistCustomerIds = Optional.ofNullable(crmCustomerAssistMapper.selectCustomerIdByCompanyUserId(param.getCompanyUserId()))
+                    .orElse(Collections.emptyList());
+            mergedSet = Stream.concat(customerIds.stream(), assistCustomerIds.stream())
+                    .collect(Collectors.toSet());
+            mergedSet.addAll(customerIds);
+            mergedSet.addAll(assistCustomerIds);
+            if (mergedSet.isEmpty()){
+                return Collections.emptyList();
+            }
+            param.setCustomerIds(new ArrayList<>(mergedSet));
+        }
+        //查询客户的订单记录
+        List<Report> reports = storeOrderMapper.selectOrderByCustomerIds(param);
+        for (Report report : reports) {
+            //查询用户下单时是否共享客户,有哪些销售共享
+            List<Long> companyUserIds = crmCustomerAssistMapper.selectCompanyUserIdByCustomerId(report.getCustomerId(), report.getPayTime());
+            if (companyUserIds.size()>0){
+                report.setStatus("1");
+                String s = companyUserMapper.selectCompanyUserNameByIdsList(companyUserIds).toString();
+                String replace = s.replace("[", "");
+                String replace1 = replace.replace("]", "");
+                report.setCompanyUserNames(replace1);
+            }
+            //计算销售的业绩
+            //分成比例
+            BigDecimal bigDecimal = new BigDecimal("100.00");
+            BigDecimal ratio = bigDecimal.divide(new BigDecimal(companyUserIds.size()), 2, RoundingMode.HALF_UP);
+            report.setProportion(ratio);
+            report.setMyPerformance(ratio.multiply(report.getMoney()).divide(bigDecimal));
+            //修改对象
+        }
+        return reports;
+    }
+}

+ 42 - 0
fs-service/src/main/java/com/fs/his/domain/FsComplaintTemplate.java

@@ -0,0 +1,42 @@
+package com.fs.his.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 投诉模板对象 fs_complaint_template
+ *
+ * @author fs
+ * @date 2025-06-09
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsComplaintTemplate extends BaseEntity{
+
+    @TableId
+    private Long id;
+
+    /** 上级编码 */
+    @Excel(name = "上级编码")
+    private Long parentId;
+
+    /** 同级下排序 */
+    @Excel(name = "同级下排序")
+    private Long sort;
+
+    /** 投诉分类 */
+    @Excel(name = "投诉分类")
+    private String name;
+
+
+    @Excel(name = "投诉分类")
+    private Long isDel;
+
+
+    private String description;
+
+
+}

+ 63 - 0
fs-service/src/main/java/com/fs/his/domain/FsUserComplaint.java

@@ -0,0 +1,63 @@
+package com.fs.his.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 用户投诉对象 fs_user_complaint
+ *
+ * @author fs
+ * @date 2025-06-09
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsUserComplaint extends BaseEntity{
+
+    @TableId
+    private Long id;
+
+    /** 用户id */
+//    @Excel(name = "用户id")
+    private Long userId;
+
+    @Excel(name = "用户")
+    private String userName;
+
+    /** 投诉模板id */
+    @Excel(name = "投诉模板id")
+    private Long templateId;
+
+    /** 详细内容 */
+    @Excel(name = "详细内容")
+    private String content;
+
+    /** 联系方式 */
+    @Excel(name = "联系方式")
+    private String phone;
+
+    /** 图片地址 */
+    @Excel(name = "图片地址")
+    private String urls;
+
+    @Excel(name = "交易截图")
+    private String tradeImage;
+
+    /** 被投诉人信息 */
+    @Excel(name = "被投诉人信息")
+    private String account;
+
+    /** 是否处理 */
+    @Excel(name = "是否处理")
+    private Integer isHandle;
+
+    //投诉时间
+    private Date complaintsTime;
+    private Date complainteTime;
+
+    private String remarks;
+}

+ 62 - 0
fs-service/src/main/java/com/fs/his/mapper/FsComplaintTemplateMapper.java

@@ -0,0 +1,62 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsComplaintTemplate;
+
+import java.util.List;
+
+/**
+ * 投诉模板Mapper接口
+ *
+ * @author fs
+ * @date 2025-06-09
+ */
+public interface FsComplaintTemplateMapper extends BaseMapper<FsComplaintTemplate>{
+    /**
+     * 查询投诉模板
+     *
+     * @param id 投诉模板主键
+     * @return 投诉模板
+     */
+    FsComplaintTemplate selectFsComplaintTemplateById(Long id);
+
+    /**
+     * 查询投诉模板列表
+     *
+     * @param fsComplaintTemplate 投诉模板
+     * @return 投诉模板集合
+     */
+    List<FsComplaintTemplate> selectFsComplaintTemplateList(FsComplaintTemplate fsComplaintTemplate);
+
+    /**
+     * 新增投诉模板
+     *
+     * @param fsComplaintTemplate 投诉模板
+     * @return 结果
+     */
+    int insertFsComplaintTemplate(FsComplaintTemplate fsComplaintTemplate);
+
+    /**
+     * 修改投诉模板
+     *
+     * @param fsComplaintTemplate 投诉模板
+     * @return 结果
+     */
+    int updateFsComplaintTemplate(FsComplaintTemplate fsComplaintTemplate);
+
+    /**
+     * 删除投诉模板
+     *
+     * @param id 投诉模板主键
+     * @return 结果
+     */
+    int deleteFsComplaintTemplateById(Long id);
+
+    /**
+     * 批量删除投诉模板
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsComplaintTemplateByIds(Long[] ids);
+}

+ 3 - 0
fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderMapper.java

@@ -1168,4 +1168,7 @@ public interface FsStoreOrderMapper
     Map<String,BigDecimal> selectFsStoreOrderStatistics(@Param("maps") FsStoreOrderParam fsStoreOrder);
 
     String selectFsStoreOrderProductStatistics(@Param("maps")FsStoreOrderParam fsStoreOrder);
+
+
+    List<Report> selectOrderByCustomerIds(@Param("map") ReportParam param);
 }

+ 63 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserComplaintMapper.java

@@ -0,0 +1,63 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsUserComplaint;
+import com.fs.his.vo.FsUserComplaintVo;
+
+import java.util.List;
+
+/**
+ * 用户投诉Mapper接口
+ *
+ * @author fs
+ * @date 2025-06-09
+ */
+public interface FsUserComplaintMapper extends BaseMapper<FsUserComplaint>{
+    /**
+     * 查询用户投诉
+     *
+     * @param id 用户投诉主键
+     * @return 用户投诉
+     */
+    FsUserComplaintVo selectFsUserComplaintById(Long id);
+
+    /**
+     * 查询用户投诉列表
+     *
+     * @param fsUserComplaint 用户投诉
+     * @return 用户投诉集合
+     */
+    List<FsUserComplaintVo> selectFsUserComplaintList(FsUserComplaint fsUserComplaint);
+
+    /**
+     * 新增用户投诉
+     *
+     * @param fsUserComplaint 用户投诉
+     * @return 结果
+     */
+    int insertFsUserComplaint(FsUserComplaint fsUserComplaint);
+
+    /**
+     * 修改用户投诉
+     *
+     * @param fsUserComplaint 用户投诉
+     * @return 结果
+     */
+    int updateFsUserComplaint(FsUserComplaint fsUserComplaint);
+
+    /**
+     * 删除用户投诉
+     *
+     * @param id 用户投诉主键
+     * @return 结果
+     */
+    int deleteFsUserComplaintById(Long id);
+
+    /**
+     * 批量删除用户投诉
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsUserComplaintByIds(Long[] ids);
+}

+ 62 - 0
fs-service/src/main/java/com/fs/his/service/IFsComplaintTemplateService.java

@@ -0,0 +1,62 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.FsComplaintTemplate;
+
+import java.util.List;
+
+/**
+ * 投诉模板Service接口
+ *
+ * @author fs
+ * @date 2025-06-09
+ */
+public interface IFsComplaintTemplateService extends IService<FsComplaintTemplate>{
+    /**
+     * 查询投诉模板
+     *
+     * @param id 投诉模板主键
+     * @return 投诉模板
+     */
+    FsComplaintTemplate selectFsComplaintTemplateById(Long id);
+
+    /**
+     * 查询投诉模板列表
+     *
+     * @param fsComplaintTemplate 投诉模板
+     * @return 投诉模板集合
+     */
+    List<FsComplaintTemplate> selectFsComplaintTemplateList(FsComplaintTemplate fsComplaintTemplate);
+
+    /**
+     * 新增投诉模板
+     *
+     * @param fsComplaintTemplate 投诉模板
+     * @return 结果
+     */
+    int insertFsComplaintTemplate(FsComplaintTemplate fsComplaintTemplate);
+
+    /**
+     * 修改投诉模板
+     *
+     * @param fsComplaintTemplate 投诉模板
+     * @return 结果
+     */
+    int updateFsComplaintTemplate(FsComplaintTemplate fsComplaintTemplate);
+
+    /**
+     * 批量删除投诉模板
+     *
+     * @param ids 需要删除的投诉模板主键集合
+     * @return 结果
+     */
+    int deleteFsComplaintTemplateByIds(Long[] ids);
+
+    /**
+     * 删除投诉模板信息
+     *
+     * @param id 投诉模板主键
+     * @return 结果
+     */
+    int deleteFsComplaintTemplateById(Long id);
+}

+ 63 - 0
fs-service/src/main/java/com/fs/his/service/IFsUserComplaintService.java

@@ -0,0 +1,63 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.FsUserComplaint;
+import com.fs.his.vo.FsUserComplaintVo;
+
+import java.util.List;
+
+/**
+ * 用户投诉Service接口
+ *
+ * @author fs
+ * @date 2025-06-09
+ */
+public interface IFsUserComplaintService extends IService<FsUserComplaint>{
+    /**
+     * 查询用户投诉
+     *
+     * @param id 用户投诉主键
+     * @return 用户投诉
+     */
+    FsUserComplaintVo selectFsUserComplaintById(Long id);
+
+    /**
+     * 查询用户投诉列表
+     *
+     * @param fsUserComplaint 用户投诉
+     * @return 用户投诉集合
+     */
+    List<FsUserComplaintVo> selectFsUserComplaintList(FsUserComplaint fsUserComplaint);
+
+    /**
+     * 新增用户投诉
+     *
+     * @param fsUserComplaint 用户投诉
+     * @return 结果
+     */
+    int insertFsUserComplaint(FsUserComplaint fsUserComplaint);
+
+    /**
+     * 修改用户投诉
+     *
+     * @param fsUserComplaint 用户投诉
+     * @return 结果
+     */
+    int updateFsUserComplaint(FsUserComplaint fsUserComplaint);
+
+    /**
+     * 批量删除用户投诉
+     *
+     * @param ids 需要删除的用户投诉主键集合
+     * @return 结果
+     */
+    int deleteFsUserComplaintByIds(Long[] ids);
+
+    /**
+     * 删除用户投诉信息
+     *
+     * @param id 用户投诉主键
+     * @return 结果
+     */
+    int deleteFsUserComplaintById(Long id);
+}

+ 94 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsComplaintTemplateServiceImpl.java

@@ -0,0 +1,94 @@
+package com.fs.his.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.utils.DateUtils;
+import com.fs.his.domain.FsComplaintTemplate;
+import com.fs.his.mapper.FsComplaintTemplateMapper;
+import com.fs.his.service.IFsComplaintTemplateService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 投诉模板Service业务层处理
+ *
+ * @author fs
+ * @date 2025-06-09
+ */
+@Service
+public class FsComplaintTemplateServiceImpl extends ServiceImpl<FsComplaintTemplateMapper, FsComplaintTemplate> implements IFsComplaintTemplateService {
+
+    /**
+     * 查询投诉模板
+     *
+     * @param id 投诉模板主键
+     * @return 投诉模板
+     */
+    @Override
+    public FsComplaintTemplate selectFsComplaintTemplateById(Long id)
+    {
+        return baseMapper.selectFsComplaintTemplateById(id);
+    }
+
+    /**
+     * 查询投诉模板列表
+     *
+     * @param fsComplaintTemplate 投诉模板
+     * @return 投诉模板
+     */
+    @Override
+    public List<FsComplaintTemplate> selectFsComplaintTemplateList(FsComplaintTemplate fsComplaintTemplate)
+    {
+        return baseMapper.selectFsComplaintTemplateList(fsComplaintTemplate);
+    }
+
+    /**
+     * 新增投诉模板
+     *
+     * @param fsComplaintTemplate 投诉模板
+     * @return 结果
+     */
+    @Override
+    public int insertFsComplaintTemplate(FsComplaintTemplate fsComplaintTemplate)
+    {
+        fsComplaintTemplate.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFsComplaintTemplate(fsComplaintTemplate);
+    }
+
+    /**
+     * 修改投诉模板
+     *
+     * @param fsComplaintTemplate 投诉模板
+     * @return 结果
+     */
+    @Override
+    public int updateFsComplaintTemplate(FsComplaintTemplate fsComplaintTemplate)
+    {
+        fsComplaintTemplate.setUpdateTime(DateUtils.getNowDate());
+        return baseMapper.updateFsComplaintTemplate(fsComplaintTemplate);
+    }
+
+    /**
+     * 批量删除投诉模板
+     *
+     * @param ids 需要删除的投诉模板主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsComplaintTemplateByIds(Long[] ids)
+    {
+        return baseMapper.deleteFsComplaintTemplateByIds(ids);
+    }
+
+    /**
+     * 删除投诉模板信息
+     *
+     * @param id 投诉模板主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsComplaintTemplateById(Long id)
+    {
+        return baseMapper.deleteFsComplaintTemplateById(id);
+    }
+}

+ 94 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserComplaintServiceImpl.java

@@ -0,0 +1,94 @@
+package com.fs.his.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.utils.DateUtils;
+import com.fs.his.domain.FsUserComplaint;
+import com.fs.his.mapper.FsUserComplaintMapper;
+import com.fs.his.service.IFsUserComplaintService;
+import com.fs.his.vo.FsUserComplaintVo;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 用户投诉Service业务层处理
+ *
+ * @author fs
+ * @date 2025-06-09
+ */
+@Service
+public class FsUserComplaintServiceImpl extends ServiceImpl<FsUserComplaintMapper, FsUserComplaint> implements IFsUserComplaintService {
+
+    /**
+     * 查询用户投诉
+     *
+     * @param id 用户投诉主键
+     * @return 用户投诉
+     */
+    @Override
+    public FsUserComplaintVo selectFsUserComplaintById(Long id)
+    {
+        return baseMapper.selectFsUserComplaintById(id);
+    }
+
+    /**
+     * 查询用户投诉列表
+     *
+     * @param fsUserComplaint 用户投诉
+     * @return 用户投诉
+     */
+    @Override
+    public List<FsUserComplaintVo> selectFsUserComplaintList(FsUserComplaint fsUserComplaint)
+    {
+        return baseMapper.selectFsUserComplaintList(fsUserComplaint);
+    }
+
+    /**
+     * 新增用户投诉
+     *
+     * @param fsUserComplaint 用户投诉
+     * @return 结果
+     */
+    @Override
+    public int insertFsUserComplaint(FsUserComplaint fsUserComplaint)
+    {
+        fsUserComplaint.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFsUserComplaint(fsUserComplaint);
+    }
+
+    /**
+     * 修改用户投诉
+     *
+     * @param fsUserComplaint 用户投诉
+     * @return 结果
+     */
+    @Override
+    public int updateFsUserComplaint(FsUserComplaint fsUserComplaint)
+    {
+        return baseMapper.updateFsUserComplaint(fsUserComplaint);
+    }
+
+    /**
+     * 批量删除用户投诉
+     *
+     * @param ids 需要删除的用户投诉主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserComplaintByIds(Long[] ids)
+    {
+        return baseMapper.deleteFsUserComplaintByIds(ids);
+    }
+
+    /**
+     * 删除用户投诉信息
+     *
+     * @param id 用户投诉主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserComplaintById(Long id)
+    {
+        return baseMapper.deleteFsUserComplaintById(id);
+    }
+}

+ 88 - 0
fs-service/src/main/java/com/fs/his/utils/ComplaintTreeUtil.java

@@ -0,0 +1,88 @@
+package com.fs.his.utils;
+
+import com.fs.his.vo.FsComplaintTemplateVO;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @ClassName 树形工具类
+ **/
+public class ComplaintTreeUtil {
+    /**
+     * 获得指定节点下所有归档
+     *
+     * @param list
+     * @param parentId
+     * @return
+     */
+    public static List<FsComplaintTemplateVO> list2TreeConverter(List<FsComplaintTemplateVO> list, int parentId) {
+        List<FsComplaintTemplateVO> returnList = new ArrayList<>();
+
+        for (FsComplaintTemplateVO res : list) {
+            //判断对象是否为根节点
+
+            if (res.getParentId() == parentId) {
+                //该节点为根节点,开始递归
+                //通过递归为节点设置childList
+                recursionFn(list, res);
+                returnList.add(res);
+            }
+        }
+
+        return returnList;
+    }
+
+    /**
+     * 递归列表
+     * 通过递归,给指定t节点设置childList
+     *
+     * @param list
+     * @param t
+     */
+    public static void recursionFn(List<FsComplaintTemplateVO> list, FsComplaintTemplateVO t) {
+        //只能获取当前t节点的子节点集,并不是所有子节点集
+        List<FsComplaintTemplateVO> childsList = getChildList(list, t);
+
+        if(childsList!=null&&childsList.size()>0){
+            //设置他的子集对象集
+            t.setChildren(childsList);
+        }
+
+
+
+        //迭代子集对象集
+
+        //遍历完,则退出递归
+        for (FsComplaintTemplateVO nextChild : childsList) {
+
+            //判断子集对象是否还有子节点
+            if (!CollectionUtils.isEmpty(childsList)) {
+                //有下一个子节点,继续递归
+                recursionFn(list, nextChild);
+            }
+        }
+    }
+
+    /**
+     * 获得指定节点下的所有子节点
+     *
+     * @param list
+     * @param t
+     * @return
+     */
+    public static List<FsComplaintTemplateVO> getChildList(List<FsComplaintTemplateVO> list, FsComplaintTemplateVO t) {
+        List<FsComplaintTemplateVO> childsList = new ArrayList<>();
+        //遍历集合元素,如果元素的Parentid==指定元素的id,则说明是该元素的子节点
+        for (FsComplaintTemplateVO t1 : list) {
+            if (t1.getParentId().equals(t.getId())) {
+                childsList.add(t1);
+            }
+        }
+
+        return childsList;
+    }
+
+
+}

+ 16 - 0
fs-service/src/main/java/com/fs/his/vo/FsComplaintTemplateVO.java

@@ -0,0 +1,16 @@
+package com.fs.his.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class FsComplaintTemplateVO {
+    private static final long serialVersionUID = 1L;
+    private Long id;
+    private String name;
+    private Long parentId;
+    private String description;
+    private Long sort;
+    private List<FsComplaintTemplateVO> children; //子集
+}

+ 52 - 0
fs-service/src/main/java/com/fs/his/vo/FsUserComplaintVo.java

@@ -0,0 +1,52 @@
+package com.fs.his.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class FsUserComplaintVo {
+    private Long id;
+
+    /** 用户id */
+    @Excel(name = "用户")
+    private String userName;
+
+    /** 投诉模板id */
+    @Excel(name = "投诉模板id")
+    private Long templateId;
+
+    private String name;
+
+    /** 详细内容 */
+    @Excel(name = "详细内容")
+    private String content;
+
+    /** 联系方式 */
+//   2025-7-3 新增需求不在导出 @Excel(name = "联系方式")
+    private String phone;
+
+    /** 图片地址 */
+    @Excel(name = "图片地址")
+    private String urls;
+
+    @Excel(name = "交易截图")
+    private String tradeImage;
+
+    /** 被投诉人信息 */
+    @Excel(name = "被投诉人信息")
+    private String account;
+
+    /** 是否处理 */
+    @Excel(name = "是否处理")
+    private Integer isHandle;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "投诉时间",dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    @Excel(name="备注")
+    private String remarks;
+}

+ 138 - 0
fs-service/src/main/resources/application-config-bly.yml

@@ -0,0 +1,138 @@
+#配置
+fsConfig:
+  #快递鸟
+  kdnId: 1886082
+  kdnKeyId: 5a66df03-3d88-469a-ab42-23cb082b57ac
+  kdnUrl: http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx
+  kdnSubscribeUrl: https://api.kdniao.com/api/dist
+  kdnAddressUrl: https://api.kdniao.com/api/dist
+  #ERP配置
+  erpOpen: 1
+  erpAppKey: 108123
+  erpSessionKey: 9caae15474cb443ea22235e7bb86016b
+  erpSecret: 96f774dbd60847b59a16f92fd963a0c8
+  erpUrl: http://v2.api.guanyierp.com/rest/erp_open
+  erpShopCode: test
+  #ERP-hc
+  erpWdAppKey: beiliyou2-gw
+  erpWdAppsecret: 37c7cebf6e5af56c783d865b63553993
+  erpWdSid: beiliyou2
+  erpWdShopCode: ziyou123456
+  erpWdBaseUrl: https://api.wangdian.cn/openapi2/
+  erpWarehouseCode: "02"
+  #第三方支付配置
+  payOpen: 1
+  payPartnerId: 22051909542647100020
+  payKey: f256bd35aa36115d729537e1a1e01b92
+  payGateWayUrl: https://openapi.t2bank.cn/gateway.html
+  payNotifyUrl: https://api.yjf.runtzh.com/app/pay/payNotify
+  refundNotifyUrl: https://api.yjf.runtzh.com/app/pay/refundNotify
+  # 腾讯云IM
+  sdkAppId: 1400693126
+  sdkAppKey: 9afa6e63db943293680e37b3ba032e52cdb238112750806e82e58e9240604b70
+  # 处方接口Test
+  #  prescribeUrl: https://yixian-new-test.yixianmedical.com/platform-shenfang/nethosp/webservice/jsonapi
+  #  actId:  uporder
+  #  appId: 1646204278
+  #  manuId:  3981112bfcc64bf68f7744ffec7e3ca7
+  #  callbackUrl:  https://api.hospital.ifeiyu100.com/app/prescribe/presribeNotify
+  # 处方接口g
+  prescribeUrl: https://app3.nxk520.com/platform-shenfang/nethosp/webservice/jsonapi
+  actId: uporder
+  appId: 1661496555
+  manuId: 0212af1e742b41b09089afeec98f8276
+  callbackUrl: https://api.yjf.runtzh.com/app/prescribe/presribeNotify
+  commonApi: http://192.168.0.224:7011
+logging:
+  level:
+    org.springframework.web: INFO
+    com.github.binarywang.demo.wx.cp: DEBUG
+    me.chanjar.weixin: DEBUG
+wx:
+  cp:
+    corpId: wwb2a1055fb6c9a7c2
+    appConfigs:
+      - agentId: 1000002
+        secret: bhj3402rPCT0YGcosffyTO3eUMs1G2MFHMspXVBNf-c
+        token: PPKOdAlCoMO
+        aesKey: PKvaxtpSv8NGpfTDm7VUHIK8Wok2ESyYX24qpXJAdMP
+  miniapp:
+    configs:
+      - appid: wx11a2ce7c2bbc4521   #倍力优会员商城
+        secret: d680dc8ff20258b158c9355f8b7769ae
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+      - appid: wx301ab2fad04c658a   #倍力优看课小程序
+        secret: 35018f10929b84c8c4a225de253bbcc6
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+
+  pay:
+    appId: wx11a2ce7c2bbc4521 #微信公众号或者小程序等的appid
+    mchId: 1703311381 #微信支付商户号
+    mchKey: FotTIbIzn4AisMW7de712LJQIazSqqAl #微信支付商户密钥
+    v3Key: y5Eo99q93qzdQRAs6E2BDKIF7f3EnS3G
+    subAppId:  #服务商模式下的子商户公众账号ID
+    subMchId:  #服务商模式下的子商户号
+    keyPath: c:\\Tools\\cert\\apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
+    notifyUrl:  https://userapp.bly.ylrztop.com/app/wxpay/wxPayNotify
+  mp:
+    useRedis: false
+    redisConfig:
+      host: 127.0.0.1
+      port: 6379
+      timeout: 2000
+    configs:
+      - appId: wx568ea6b70350c585 # 第一个公众号的appid  倍力优
+        secret: b14343e22871b1c207df5d3321e826b4 # 公众号的appsecret
+        token: PPKOdAlCoMO # 接口配置里的Token值
+        aesKey: Eswa6VjwtVMCcw03qZy6fWllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
+jpush:
+  appKey: cc9a0120a3e4270c9cba340d
+  masterSecret: cfc2575d3cd7470d584c990c
+  liveTime: 1000
+  apnsProduction: true
+aifabu:  #爱链接
+  appKey: 7b471be905ab17e00f3b858c6710dd117601d008
+
+tencent_cloud_config:
+  secret_id: AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT
+  secret_key: u5SuS80342xzx8FRBukza9lVNHKNMSaB
+  bucket: beliyo-1323137866
+  app_id: 1323137866
+  region: ap-chongqing
+  proxy: beliyo
+cloud_host:
+  company_name: 倍力优
+  projectCode: BLY
+headerImg:
+  imgUrl: https://beiliyo-2025.obs.cn-north-4.myhuaweicloud.com/fs/20250115/1736944490230.png
+
+baidu:
+  token: 1231321232
+  back-domain: admin.muyi88.com
+watch:
+  watchUrl: watch.ylrzcloud.com/prod-api
+  #  account: tcloud
+  #  password: mdf-m2h_6yw2$hq
+  account1: ccif #866655060138751
+  password1: cp-t5or_6xw7$mt
+  account2: tcloud #rt500台
+  password2: mdf-m2h_6yw2$hq
+  account3: whr
+  password3: v9xsKuqn_$d2y
+
+fs:
+  commonApi: http://172.21.76.167:8010
+nuonuo:
+  key: 10924508
+  secret: A2EB20764D304D16
+ipad:
+  ipadUrl:
+  aiApi:
+wx_miniapp_temp:
+  pay_order_temp_id: VXEvKaGNPFuJmhWK9O_QPrTZxe9umDCukq-maI8Vdek
+  inquiry_temp_id: 9POPYeqhI48LOPvq-Rfoklze7H-9SlunJKh10Qt4_2I
+

+ 144 - 0
fs-service/src/main/resources/application-druid-bly-test.yml

@@ -0,0 +1,144 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-bly,common
+    # redis 配置
+    redis:
+        # 地址
+        host: 127.0.0.1
+        # 端口,默认为6379
+        port: 6379
+        # 密码
+        password:
+        # 连接超时时间
+        timeout: 30s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 8
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                max-wait: -1ms
+        database: 0
+    datasource:
+        mysql:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://113.44.133.86:3306/bly_store2?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: bly@2025
+                # 从库数据源
+                slave:
+                    # 从数据源开关/默认关闭
+                    enabled: false
+                    url:
+                    username:
+                    password:
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+        sop:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://113.44.133.86:3306/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: bly@2025
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+rocketmq:
+    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
+    producer:
+        group: my-producer-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+    consumer:
+        group: test-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+openIM:
+    secret: openIM123
+    userID: imAdmin
+#是否为新商户,新商户不走mpOpenId
+isNewWxMerchant: false

+ 144 - 0
fs-service/src/main/resources/application-druid-bly.yml

@@ -0,0 +1,144 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-bly,common
+    # redis 配置
+    redis:
+        # 地址
+        host: 192.168.0.224
+        # 端口,默认为6379
+        port: 6379
+        # 密码
+        password:
+        # 连接超时时间
+        timeout: 30s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 8
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                max-wait: -1ms
+        database: 0
+    datasource:
+        mysql:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://192.168.0.224:3306/bly_store?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: bly@2025
+                # 从库数据源
+                slave:
+                    # 从数据源开关/默认关闭
+                    enabled: false
+                    url:
+                    username:
+                    password:
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+        sop:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://192.168.0.224:3306/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: bly@2025
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+rocketmq:
+    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
+    producer:
+        group: my-producer-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+    consumer:
+        group: test-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+openIM:
+    secret: openIM123
+    userID: imAdmin
+#是否为新商户,新商户不走mpOpenId
+isNewWxMerchant: false

+ 8 - 0
fs-service/src/main/resources/mapper/company/CompanyUserMapper.xml

@@ -565,4 +565,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{userId}
         </foreach>
     </update>
+
+    <select id="selectCompanyUserNameByIdsList" resultType="java.lang.String">
+        SELECT nick_name from company_user where user_id in
+        <foreach collection="companyUserIDs" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </select>
+
 </mapper>

+ 108 - 0
fs-service/src/main/resources/mapper/crm/CrmCustomerAssistMapper.xml

@@ -0,0 +1,108 @@
+<?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.fs.crm.mapper.CrmCustomerAssistMapper">
+
+    <resultMap type="CrmCustomerAssist" id="CrmCustomerAssistResult">
+        <result property="id"    column="id"    />
+        <result property="companyId"    column="company_id"    />
+        <result property="companyUserId"    column="company_user_id"    />
+        <result property="companyUserName"    column="company_user_name"    />
+        <result property="customerId"    column="customer_id"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="rate"    column="rate"    />
+    </resultMap>
+
+    <sql id="selectCrmCustomerAssistVo">
+        select id, company_id, company_user_id,company_user_name, customer_id, create_time,rate from crm_customer_assist
+    </sql>
+
+    <select id="selectCrmCustomerAssistList" parameterType="CrmCustomerAssist" resultMap="CrmCustomerAssistResult">
+        <include refid="selectCrmCustomerAssistVo"/>
+        <where>
+            <if test="companyId != null "> and company_id = #{companyId}</if>
+            <if test="companyUserId != null "> and company_user_id = #{companyUserId}</if>
+            <if test="companyUserName != null and companyUserName != ''"> and company_user_name = #{companyUserName}</if>
+            <if test="customerId != null "> and customer_id = #{customerId}</if>
+        </where>
+    </select>
+
+    <select id="selectCrmCustomerAssistById" parameterType="Long" resultMap="CrmCustomerAssistResult">
+        <include refid="selectCrmCustomerAssistVo"/>
+        where id = #{id}
+    </select>
+    <select id="selectCompanyUserNameByCustomerId" resultType="java.lang.String">
+        select  CONCAT(company_user_name, '(', company_user_id, ')','分佣:',rate,'%') AS assistUser
+        from crm_customer_assist
+        where customer_id = #{customerId}
+    </select>
+    <select id="selectCustomerIdByCompanyUserId" resultType="java.lang.Long">
+        SELECT customer_id FROM crm_customer_assist where company_user_id = #{companyUserId}
+    </select>
+    <select id="selectCompanyUserIdByCustomerId" resultType="java.lang.Long">
+        select company_user_id from crm_customer_assist where customer_id = #{customerId} and create_time &lt; #{createTime}
+    </select>
+    <select id="selectByCustomerId" resultType="com.fs.crm.domain.CrmCustomerAssist">
+        <include refid="selectCrmCustomerAssistVo"/>
+        where  customer_id = #{customerId}
+
+    </select>
+
+    <insert id="insertCrmCustomerAssist" parameterType="CrmCustomerAssist" useGeneratedKeys="true" keyProperty="id">
+        insert into crm_customer_assist
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="companyId != null">company_id,</if>
+            <if test="companyUserId != null">company_user_id,</if>
+            <if test="companyUserName != null">company_user_name,</if>
+            <if test="customerId != null">customer_id,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="rate != null">rate,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="companyId != null">#{companyId},</if>
+            <if test="companyUserId != null">#{companyUserId},</if>
+            <if test="companyUserName != null">#{companyUserName},</if>
+            <if test="customerId != null">#{customerId},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="rate != null">#{rate},</if>
+         </trim>
+    </insert>
+
+    <update id="updateCrmCustomerAssist" parameterType="CrmCustomerAssist">
+        update crm_customer_assist
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="companyId != null">company_id = #{companyId},</if>
+            <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+            <if test="companyUserName != null">company_user_name = #{companyUserName},</if>
+            <if test="customerId != null">customer_id = #{customerId},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="rate != null">rate = #{rate},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteCrmCustomerAssistById" parameterType="Long">
+        delete from crm_customer_assist where id = #{id}
+    </delete>
+
+    <delete id="deleteCrmCustomerAssistByIds" parameterType="String">
+        delete from crm_customer_assist where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+    <delete id="removeByCustomer">
+        delete from crm_customer_assist where customer_id in
+        <foreach collection="maps.customerIds" item="customerId" open="(" separator="," close=")">
+            #{customerId}
+        </foreach>
+        <if test="maps.companyUserId != null">
+            and company_user_id = #{maps.companyUserId}
+        </if>
+    </delete>
+    <delete id="deleteCrmCustomerAssistByCustomerId">
+        delete from crm_customer_assist where customer_id = #{customerId}
+    </delete>
+
+</mapper>

+ 3 - 1
fs-service/src/main/resources/mapper/crm/CrmCustomerMapper.xml

@@ -362,7 +362,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         GROUP BY t.type
     </select>
 
-
+    <select id="selectCustomerIdByCompanyUserId" resultType="java.lang.Long">
+        SELECT customer_id FROM crm_customer_assist where company_user_id = #{companyUserId}
+    </select>
 
     <select id="selectCrmMyAssistListQuery" resultType="com.fs.crm.vo.CrmMyCustomerListQueryVO">
         select cu.*,c.create_time as customer_create_time,c.visit_status,c.remark,c.register_desc,c.register_submit_time,

+ 86 - 0
fs-service/src/main/resources/mapper/his/FsComplaintTemplateMapper.xml

@@ -0,0 +1,86 @@
+<?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.fs.his.mapper.FsComplaintTemplateMapper">
+
+    <resultMap type="FsComplaintTemplate" id="FsComplaintTemplateResult">
+        <result property="id"    column="id"    />
+        <result property="parentId"    column="parent_id"    />
+        <result property="sort"    column="sort"    />
+        <result property="name"    column="name"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="isDel"    column="is_del"    />
+        <result property="description"    column="description"    />
+    </resultMap>
+
+    <sql id="selectFsComplaintTemplateVo">
+        select id, parent_id, sort, name, update_time, create_time, is_del,description from fs_complaint_template
+    </sql>
+
+    <select id="selectFsComplaintTemplateList" parameterType="FsComplaintTemplate" resultMap="FsComplaintTemplateResult">
+        <include refid="selectFsComplaintTemplateVo"/>
+        <where>
+            <if test="parentId != null "> and parent_id = #{parentId}</if>
+            <if test="sort != null "> and sort = #{sort}</if>
+            <if test="name != null  and name != ''"> and name like concat('%', #{name}, '%')</if>
+            <if test="isDel != null "> and is_del = #{isDel}</if>
+            <if test="description != null and description !=''"> and description = #{description}</if>
+        </where>
+    </select>
+
+    <select id="selectFsComplaintTemplateById" parameterType="Long" resultMap="FsComplaintTemplateResult">
+        <include refid="selectFsComplaintTemplateVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertFsComplaintTemplate" parameterType="FsComplaintTemplate">
+        insert into fs_complaint_template
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="parentId != null">parent_id,</if>
+            <if test="sort != null">sort,</if>
+            <if test="name != null and name != ''">name,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="isDel != null">is_del,</if>
+            <if test="description != null">description,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="parentId != null">#{parentId},</if>
+            <if test="sort != null">#{sort},</if>
+            <if test="name != null and name != ''">#{name},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="isDel != null">#{isDel},</if>
+            <if test="description != null">#{description},</if>
+         </trim>
+    </insert>
+
+    <update id="updateFsComplaintTemplate" parameterType="FsComplaintTemplate">
+        update fs_complaint_template
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="parentId != null">parent_id = #{parentId},</if>
+            <if test="sort != null">sort = #{sort},</if>
+            <if test="name != null and name != ''">name = #{name},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="isDel != null">is_del = #{isDel},</if>
+            <if test="description != null  and description != ''">description = #{description},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteFsComplaintTemplateById" parameterType="Long">
+        delete from fs_complaint_template where id = #{id}
+    </delete>
+
+    <delete id="deleteFsComplaintTemplateByIds" parameterType="String">
+        delete from fs_complaint_template where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>

+ 108 - 0
fs-service/src/main/resources/mapper/his/FsUserComplaintMapper.xml

@@ -0,0 +1,108 @@
+<?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.fs.his.mapper.FsUserComplaintMapper">
+
+    <resultMap type="FsUserComplaint" id="FsUserComplaintResult">
+        <result property="id"    column="id"    />
+        <result property="userId"    column="user_id"    />
+        <result property="userName"    column="user_name"    />
+        <result property="templateId"    column="template_id"    />
+        <result property="content"    column="content"    />
+        <result property="phone"    column="phone"    />
+        <result property="urls"    column="urls"    />
+        <result property="tradeImage"    column="trade_image"    />
+        <result property="account"    column="account"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="isHandle"    column="is_handle"    />
+    </resultMap>
+
+    <sql id="selectFsUserComplaintVo">
+        select id, user_id,user_name template_id, content, phone, urls,trade_image, account, create_time, is_handle, remarks from fs_user_complaint
+    </sql>
+
+    <select id="selectFsUserComplaintList" parameterType="FsUserComplaint" resultType="com.fs.his.vo.FsUserComplaintVo">
+        select id, user_name, template_id, content, phone, urls,trade_image, account, create_time, is_handle, remarks
+        from fs_user_complaint c
+        <where>
+            <if test="userId != null "> and user_id = #{userId}</if>
+            <if test="userName != null and userName != ''"> and user_name like concat('%',#{userName},'%') </if>
+            <if test="templateId != null "> and template_id = #{templateId}</if>
+            <if test="content != null  and content != ''"> and content = #{content}</if>
+            <if test="phone != null  and phone != ''"> and phone = #{phone}</if>
+            <if test="urls != null  and urls != ''"> and urls = #{urls}</if>
+            <if test="tradeImage != null  and tradeImage != ''"> and trade_image = #{tradeImage}</if>
+            <if test="account != null  and account != ''"> and account = #{account}</if>
+            <if test="isHandle != null "> and is_handle = #{isHandle}</if>
+            <if test="complaintsTime != null ">  and create_time &gt;= #{complaintsTime}</if>
+            <if test="complainteTime != null ">  and create_time &lt; date_add(#{complainteTime}, interval 1 day)</if>
+        </where>
+    </select>
+
+    <select id="selectFsUserComplaintById" parameterType="Long" resultType="com.fs.his.vo.FsUserComplaintVo">
+        select c.id, c.user_name, c.template_id, c.content, c.phone, c.urls,c.trade_image, c.account, c.create_time, c.is_handle,t.name,c.remarks
+        from fs_user_complaint c
+        left join fs_complaint_template t on c.template_id = t.id
+        where c.id = #{id}
+    </select>
+
+    <insert id="insertFsUserComplaint" parameterType="FsUserComplaint" useGeneratedKeys="true" keyProperty="id">
+        insert into fs_user_complaint
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="userId != null">user_id,</if>
+            <if test="userName != null">user_name,</if>
+            <if test="templateId != null">template_id,</if>
+            <if test="content != null">content,</if>
+            <if test="phone != null">phone,</if>
+            <if test="urls != null">urls,</if>
+            <if test="tradeImage != null">trade_image,</if>
+            <if test="account != null">account,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="isHandle != null">is_handle,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="userId != null">#{userId},</if>
+            <if test="userName != null">#{userName},</if>
+            <if test="templateId != null">#{templateId},</if>
+            <if test="content != null">#{content},</if>
+            <if test="phone != null">#{phone},</if>
+            <if test="urls != null">#{urls},</if>
+            <if test="tradeImage != null">#{tradeImage},</if>
+            <if test="account != null">#{account},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="isHandle != null">#{isHandle},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateFsUserComplaint" parameterType="FsUserComplaint">
+        update fs_user_complaint
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="userName != null and userName !=''">user_name = #{userName},</if>
+            <if test="templateId != null">template_id = #{templateId},</if>
+            <if test="content != null">content = #{content},</if>
+            <if test="phone != null">phone = #{phone},</if>
+            <if test="urls != null and urls !=''">urls = #{urls},</if>
+            <if test="tradeImage != null and tradeImage !=''">trade_image = #{tradeImage},</if>
+            <if test="account != null">account = #{account},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="isHandle != null">is_handle = #{isHandle},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteFsUserComplaintById" parameterType="Long">
+        delete from fs_user_complaint where id = #{id}
+    </delete>
+
+    <delete id="deleteFsUserComplaintByIds" parameterType="String">
+        delete from fs_user_complaint where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>

+ 122 - 0
fs-user-app/src/main/java/com/fs/app/controller/FsUserComplaintController.java

@@ -0,0 +1,122 @@
+package com.fs.app.controller;
+
+import com.fs.app.annotation.Login;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.his.domain.FsComplaintTemplate;
+import com.fs.his.domain.FsUserComplaint;
+import com.fs.his.service.IFsComplaintTemplateService;
+import com.fs.his.service.IFsUserComplaintService;
+import com.fs.his.utils.ComplaintTreeUtil;
+import com.fs.his.vo.FsComplaintTemplateVO;
+import com.fs.his.vo.FsUserComplaintVo;
+import com.google.common.collect.Lists;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 用户投诉Controller
+ *
+ * @author fs
+ * @date 2025-06-09
+ */
+@RestController
+@RequestMapping("/app/complaint")
+public class FsUserComplaintController extends AppBaseController
+{
+    @Autowired
+    private IFsUserComplaintService fsUserComplaintService;
+    @Autowired
+    private IFsComplaintTemplateService fsComplaintTemplateService;
+
+    /**
+     * 查询投诉模板列表
+     */
+    @GetMapping("/templateList")
+    public TableDataInfo list(FsComplaintTemplate fsComplaintTemplate)
+    {
+        startPage();
+        fsComplaintTemplate.setIsDel(0L);
+        List<FsComplaintTemplate> list = fsComplaintTemplateService.selectFsComplaintTemplateList(fsComplaintTemplate);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询投诉模板树形结果
+     */
+    @GetMapping("/treeList")
+    public R treeList(FsComplaintTemplate fsComplaintTemplate)
+    {
+        List<FsComplaintTemplate> list = fsComplaintTemplateService.selectFsComplaintTemplateList(fsComplaintTemplate);
+        List<FsComplaintTemplateVO> templateVOS = Lists.newArrayList();
+        for (FsComplaintTemplate template : list){
+            FsComplaintTemplateVO templateVO = new FsComplaintTemplateVO();
+            templateVO.setId(template.getId());
+            templateVO.setName(template.getName());
+            templateVO.setParentId(template.getParentId());
+            templateVO.setDescription(template.getDescription());
+            templateVO.setSort(template.getSort());
+            templateVOS.add(templateVO);
+        }
+        return R.ok().put("data", ComplaintTreeUtil.list2TreeConverter(templateVOS, 0));
+    }
+
+    /**
+     * 查询用户投诉列表
+     */
+//    @PreAuthorize("@ss.hasPermi('his:complaint:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserComplaint fsUserComplaint)
+    {
+        startPage();
+        List<FsUserComplaintVo> list = fsUserComplaintService.selectFsUserComplaintList(fsUserComplaint);
+        return getDataTable(list);
+    }
+
+
+
+    /**
+     * 获取用户投诉详细信息
+     */
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsUserComplaintService.selectFsUserComplaintById(id));
+    }
+
+    /**
+     * 新增用户投诉
+     */
+    @Login
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserComplaint fsUserComplaint)
+    {
+        String userId = getUserId();
+        fsUserComplaint.setUserId(Long.valueOf(userId));
+        return toAjax(fsUserComplaintService.insertFsUserComplaint(fsUserComplaint));
+    }
+
+    /**
+     * 修改用户投诉
+     */
+    @Login
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserComplaint fsUserComplaint)
+    {
+        return toAjax(fsUserComplaintService.updateFsUserComplaint(fsUserComplaint));
+    }
+
+    /**
+     * 删除用户投诉
+     */
+    @Login
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsUserComplaintService.deleteFsUserComplaintByIds(ids));
+    }
+}