无关风月
8 小时以前 02bb94e413f6950b9786c5ee86c0937bc20f8ae8
Merge remote-tracking branch 'origin/master'

# Conflicts:
# ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TUserController.java
1个文件已删除
6个文件已添加
11个文件已修改
564 ■■■■ 已修改文件
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TLocationController.java 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/WorkbenchesController.java 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-test.yml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TUserController.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/WxAppletTools.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/importExcel/TLocationImportExcel.java 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/utils/JsonUtils.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/utils/TemplateMessageSendUtil.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/config/JacksonConfig.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/model/WeixinProperties.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletUserEncrypteData.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/template/Template.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/template/wxTemplateTaskReturn/WxTemplateTaskResultRequest.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/template/wxTemplateTaskReturn/WxTemplateTaskResultRequestData.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxAppletTools.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TLocationController.java
@@ -5,6 +5,8 @@
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.annotation.Log;
@@ -341,7 +343,7 @@
    @PostMapping("/importLocation")
    public R<String> importLocation(@RequestPart("file") MultipartFile file) {
        ImportParams params = new ImportParams();
        params.setTitleRows(2); // 标题行数
//        params.setTitleRows(1); // 标题行数
        params.setHeadRows(1); //表头行数
        InputStream inputStream = null;
//        List<CustomerImportFailedData> failedData = new ArrayList<>();
@@ -371,9 +373,11 @@
        // 查询所有用户
        List<SysUser> users = sysUserService.selectAllList();
        // 查询所有部门
        List<TDept> deptList = deptService.list();
        List<TProjectDept> deptList = projectDeptService.list();
        // 查询所有保洁员
        List<TCleaner> cleaners = cleanerService.list();
        JSONObject result = new JSONObject();
        for (TLocationImportExcel locationExcel : locationExcelList) {
            System.err.println(locationExcel);
@@ -385,28 +389,43 @@
                location.setLocationType(tLocationType.getId());
            }
            location.setLocationAddress(locationExcel.getLocationAddress());
            String[] addressLonLat = locationExcel.getLocationAddressLonLat().split("/");
            String[] addressLonLat = locationExcel.getLocationAddressLonLat().split(",");
            location.setLocationLon(addressLonLat[0]);
            location.setLocationLat(addressLonLat[1]);
            location.setLocationAddressEnd(locationExcel.getLocationAddressEnd());
            String[] addressEndLonLat = locationExcel.getLocationAddressEndLonLat().split("/");
            String[] addressEndLonLat = locationExcel.getLocationAddressEndLonLat().split(",");
            location.setLocationLonEnd(addressEndLonLat[0]);
            location.setLocationLatEnd(addressEndLonLat[1]);
            TDept tDept = deptList.stream().filter(dept -> dept.getCode().equals(locationExcel.getDeptCode())).findFirst().orElse(null);
            if(Objects.nonNull(tDept)){
                location.setProjectId(tDept.getId());
            TProjectDept projectDept = deptList.stream().filter(dept -> dept.getCode().equals(locationExcel.getDeptCode())).findFirst().orElse(null);
            if(Objects.nonNull(projectDept)){
                location.setProjectId(projectDept.getId());
            }else {
                result.append("路段名:[", locationExcel.getLocationName()+"]未查询到部门");
                continue;
            }
            SysUser sysUser = users.stream().filter(user -> user.getNickName().equals(locationExcel.getNickName())).findFirst().orElse(null);
            if(Objects.nonNull(sysUser)){
                location.setLocationLeader(String.valueOf(sysUser.getUserId()));
            }else {
                result.append("路段名:[", locationExcel.getLocationName()+"]未查询到点位负责人");
                continue;
            }
            cleaners.stream().filter(cleaner -> cleaner.getCleanerCode().equals(locationExcel.getCleanerCodeClear())
            TCleaner tCleaner = cleaners.stream().filter(cleaner -> cleaner.getCleanerCode().equals(locationExcel.getCleanerCodeClear())
                    && cleaner.getDeptCode().equals(locationExcel.getDeptCodeClear())
                    && cleaner.getProjectCode().equals(locationExcel.getProjectCodeClear())).findFirst().orElse(null);
            location.setLocationCleaner(locationExcel.getProjectCodeClear());
                    && cleaner.getProjectCode().equals(locationExcel.getProjectCodeClear())
                    && cleaner.getCleanerName().equals(locationExcel.getCleanerName())).findFirst().orElse(null);
            if(Objects.nonNull(tCleaner)){
                location.setLocationCleaner(tCleaner.getId());
            }else {
                result.append("路段名:[", locationExcel.getLocationName()+"]未查询到保洁员");
                continue;
            }
            locationService.save(location);
        }
        if(!result.isEmpty()){
            return R.ok(result.toString());
        }
        return R.ok();
    }
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/WorkbenchesController.java
@@ -204,6 +204,10 @@
                    }
                    query.setProjectId(projectIds);
                }
                // 巡检员数
                Integer totalEmployeeNum = sysUserService.selectUserCount(query.getProjectId(),deptType);
                map.put("totalEmployeeNum", totalEmployeeNum);
            }else {
                // 公司人员
                // 查询自己的任务列表
@@ -218,6 +222,9 @@
                        query.setProjectId(projectIds);
                    }
                }
                // 巡检员数
                Integer totalEmployeeNum = sysUserService.selectUserCount(query.getProjectId(),1);
                map.put("totalEmployeeNum", totalEmployeeNum+1);
            }
            // 查询片区
@@ -283,6 +290,16 @@
                list.addAll(taskList);
            }
            list = list.stream().distinct().collect(Collectors.toList());
            // 巡检员数
            if(CollectionUtils.isEmpty(query.getProjectId())){
                Integer totalEmployeeNum = sysUserService.selectUserCount(query.getProjectId(),deptType);
                Integer totalEmployeeNum1 = sysUserService.selectUserCount(query.getProjectId(),1);
                map.put("totalEmployeeNum", totalEmployeeNum+totalEmployeeNum1);
            }else {
                Integer totalEmployeeNum = sysUserService.selectUserCount(query.getProjectId(),1);
                map.put("totalEmployeeNum", totalEmployeeNum);
            }
        }
        // 查询任务相关数据
@@ -294,11 +311,11 @@
        map.put("waitTaskNum", list.stream().filter(tTask -> tTask.getStatus() == 1).count());
        // 总计员工数
        Integer totalEmployeeNum = sysUserService.selectUserCount(null,deptType);
        if (deptType != 1) {
            totalEmployeeNum = totalEmployeeNum + 1;
        }
        map.put("totalEmployeeNum", totalEmployeeNum);
//        Integer totalEmployeeNum = sysUserService.selectUserCount(null,deptType);
//        if (deptType != 1) {
//            totalEmployeeNum = totalEmployeeNum + 1;
//        }
//        map.put("totalEmployeeNum", totalEmployeeNum);
        // 今日请假员工数量
        List<TLeave> leaves = leaveService.list(Wrappers.lambdaQuery(TLeave.class)
@@ -499,6 +516,22 @@
                && task.getStatus() != 3 && task.getStatus() != 4).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(tasks)){
            taskSituationVO.setPassRate(BigDecimal.ZERO);
            for (long i = 0; i <= daysBetween; i++) {
                TaskSituationDayVO taskSituationDayVO = new TaskSituationDayVO();
                if(i == 0){
                    format = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                }else {
                    format = DateUtils.stringToLocalDate(format).plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                }
                taskSituationDayVO.setTaskTime(format);
                // 任务数
                taskSituationDayVO.setTaskNum(0);
                // 完成数
                taskSituationDayVO.setCompletedNum(0);
                taskSituationDayVO.setCompleteRate(BigDecimal.ZERO);
                taskSituationDayVOList.add(taskSituationDayVO);
            }
            taskSituationVO.setTaskSituationDayVO(taskSituationDayVOList);
            return R.ok(taskSituationVO);
        }
        List<String> taskIds = tasks.stream().map(TTask::getId).collect(Collectors.toList());
@@ -541,7 +574,7 @@
            if(tTasks.isEmpty()){
                taskSituationDayVO.setCompleteRate(BigDecimal.ZERO);
            }else {
                taskSituationDayVO.setCompleteRate(new BigDecimal(qualifiedWarnChild).divide(new BigDecimal(tTasks.size()), 2, RoundingMode.HALF_DOWN));
                taskSituationDayVO.setCompleteRate(new BigDecimal(qualifiedWarnChild).divide(new BigDecimal(taskSituationDayVO.getCompletedNum()), 2, RoundingMode.HALF_DOWN));
            }
            taskSituationDayVOList.add(taskSituationDayVO);
        }
ruoyi-admin/src/main/resources/application-test.yml
@@ -198,6 +198,8 @@
  conf:
    appId: wxe91f1af7638aa5dd
    secretId: a787e1a462715604e0c9528b6d8960d1
    templateResultId: C4YA0kRIhoJYwKbhrNhxi8wcRLP4R92QME-lc6eygAo
    templateDateId: fWv6EnWlUNhR5Gu-6b6rv0xbk-yr7pB_kKH_Xnt7ts4
#OSS及短信配置
code:
  config:
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TUserController.java
@@ -5,11 +5,13 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.BaseModel;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.framework.web.service.TokenService;
@@ -25,14 +27,24 @@
import com.ruoyi.system.query.KnowledgeListQuery;
import com.ruoyi.system.query.TaskListQuery;
import com.ruoyi.system.service.*;
import com.ruoyi.system.utils.wx.body.resp.Code2SessionRespBody;
import com.ruoyi.system.utils.wx.body.resq.Code2SessionResqBody;
import com.ruoyi.system.utils.wx.model.WeixinProperties;
import com.ruoyi.system.utils.wx.pojo.AppletUserDecodeData;
import com.ruoyi.system.utils.wx.pojo.AppletUserEncrypteData;
import com.ruoyi.system.utils.wx.tools.WxAppletTools;
import com.ruoyi.system.utils.wx.tools.WxUtils;
import com.ruoyi.system.vo.system.*;
import com.ruoyi.web.controller.tool.EmailUtils;
import com.ruoyi.web.controller.tool.MsgUtils;
import com.sun.jna.platform.win32.LMAccess;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import javax.validation.Valid;
@@ -54,6 +66,7 @@
 * @author xiaochen
 * @since 2025-05-28
 */
@Slf4j
@Api(tags = "个人中心")
@RestController
@RequestMapping("/t-user")
@@ -100,6 +113,31 @@
    private TProblemEscalationService problemEscalationService;
    @Resource
    private TNoticeService noticeService;
    @Autowired
    private RestTemplate wxRestTemplate;
    @Autowired
    private WeixinProperties weixinProperties;
    @Resource
    private RedisService redisService;
    @ApiOperation(value = "通过code获得openid,获取用户信息",tags = {"微信小程序登录"})
    @GetMapping("/openIdByJsCode")
    public R<String> openIdByJsCode(@RequestParam String code) {
        Long userId = tokenService.getLoginUser().getUserId();
        SysUser sysUser = sysUserService.selectUserById(userId);
        if(Objects.isNull(sysUser)){
            return R.fail("未查询到当前登录用户信息");
        }
        if(StringUtils.hasLength(sysUser.getOpenId())){
            return R.ok();
        }
        log.info("<<<<<<<<换取openid开始<<<<<<<<:{}", code);
        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, weixinProperties, redisService);
        Code2SessionRespBody body = appletTools.getOpenIdByJscode2session(new Code2SessionResqBody().build(code));
        String openid = body.getOpenid();
        sysUser.setOpenId(openid);
        sysUserService.updateUser(sysUser);
        return R.ok();
    }
    @Resource
    private MsgUtils msgUtils;
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
@@ -163,4 +163,9 @@
     * 用户类型
     */
    public static final String USER_TYPE = "用户类型";
    /**
     * 模板消息发送地址
     */
    public static final String TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN";
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
@@ -152,6 +152,11 @@
    @ApiModelProperty(value = "营业部id")
    @TableField("business_dept_id")
    private String businessDeptId;
    @ApiModelProperty(value = "openId")
    @TableField("openId")
    private String openId;
    public String getRoleName() {
        return roleName;
ruoyi-common/src/main/java/com/ruoyi/common/utils/WxAppletTools.java
File was deleted
ruoyi-system/src/main/java/com/ruoyi/system/importExcel/TLocationImportExcel.java
@@ -10,39 +10,39 @@
@ApiModel(value = "点位导入excel")
public class TLocationImportExcel implements Serializable {
    @Excel(name = "项目部编号")
    @Excel(name = "项目部编号",width = 20)
    private String deptCode;
    @Excel(name = "项目部名称")
    @Excel(name = "项目部名称",width = 20)
    private String deptName;
    @Excel(name = "基层管理员部门编号")
    @Excel(name = "基层管理员部门编号",width = 20)
    private String deptNumber;
    @Excel(name = "基层管理员项目部编号")
    @Excel(name = "基层管理员项目部编号",width = 20)
    private String projectDeptNumber;
    @Excel(name = "基层管理员姓名  巡检员")
    @Excel(name = "基层管理员姓名  巡检员",width = 20)
    private String nickName;
    @Excel(name = "保洁员部门编号")
    private String projectCodeClear;
    @Excel(name = "保洁员项目部编号")
    @Excel(name = "保洁员部门编号",width = 20)
    private String deptCodeClear;
    @Excel(name = "保洁员片区编号")
    @Excel(name = "保洁员项目部编号",width = 20)
    private String projectCodeClear;
    @Excel(name = "保洁员片区编号",width = 20)
    private String cleanerCodeClear;
    @Excel(name = "保洁员(驾驶员)")
    @Excel(name = "保洁员(驾驶员)",width = 20)
    private String cleanerName;
    @Excel(name = "路段总号")
    @Excel(name = "路段总号",width = 20)
    private String locationCode;
    @Excel(name = "个人编号")
    @Excel(name = "个人编号",width = 20)
    private String cleanerCode;
    @Excel(name = "点位类型")
    @Excel(name = "点位类型",width = 20)
    private String locationType;
    @Excel(name = "路段名(村名)")
    @Excel(name = "路段名(村名)",width = 20)
    private String locationName;
    @Excel(name = "起点")
    @Excel(name = "起点",width = 20)
    private String locationAddress;
    @Excel(name = "终点")
    @Excel(name = "终点",width = 20)
    private String locationAddressEnd;
    @Excel(name = "起点(经纬度)")
    @Excel(name = "起点(经纬度)",width = 20)
    private String locationAddressLonLat;
    @Excel(name = "终点(经纬度)")
    @Excel(name = "终点(经纬度)",width = 20)
    private String locationAddressEndLonLat;
}
ruoyi-system/src/main/java/com/ruoyi/system/utils/JsonUtils.java
New file
@@ -0,0 +1,110 @@
package com.ruoyi.system.utils;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.utils.wx.config.JacksonConfig;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
 * Json转换工具类
 * 参考:https://blog.csdn.net/weixin_38413579/article/details/82562634
 * @author madman
 */
@Slf4j
public final class JsonUtils {
    private static final ObjectMapper OM = new ObjectMapper();
    private static final JavaTimeModule timeModule = new JavaTimeModule();
    /**
     * 转换LocalDateTime
     */
    static class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
        @Override
        public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeString(localDateTime.format(DateTimeFormatter.ofPattern(JacksonConfig.dateTimeFormat)));
        }
    }
    /**
     * 转换LocalDate
     */
    static class LocalDateSerializer extends JsonSerializer<LocalDate> {
        @Override
        public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeString(localDate.format(DateTimeFormatter.ofPattern(JacksonConfig.dateFormat)));
        }
    }
    /**
     * 设置 ObjectMapper
     *
     * @return
     */
    private static ObjectMapper getObjectMapper() {
        // 序列化
        timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
        timeModule.addSerializer(LocalDate.class, new LocalDateSerializer());
        // 反序列化
        timeModule.addDeserializer(LocalDateTime.class,
                new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(JacksonConfig.dateTimeFormat)));
        timeModule.addDeserializer(LocalDate.class,
                new LocalDateDeserializer(DateTimeFormatter.ofPattern(JacksonConfig.dateFormat)));
        // 允许对象忽略json中不存在的属性
        OM.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        OM.registerModule(timeModule);
        return OM;
    }
    /**
     * 将对象序列化
     */
    public static <T> String toJsonString(T obj) {
        try {
            ObjectMapper om = getObjectMapper();
            return om.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("转json字符串失败:{}", obj);
            return null;
        }
    }
    /**
     * 反序列化对象字符串
     */
    public static <T> T parseObject(String json, Class<T> clazz) {
        try {
            ObjectMapper om = getObjectMapper();
            return om.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            throw new ServiceException("反序列化对象字符串失败");
        }
    }
    /**
     * 反序列化字符串成为对象
     */
    public static <T> T parseObject(String json, TypeReference<T> valueTypeRef) {
        try {
            ObjectMapper om = getObjectMapper();
            return om.readValue(json, valueTypeRef);
        } catch (JsonProcessingException e) {
            throw new ServiceException("反序列化字符串成为对象失败");
        }
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/utils/TemplateMessageSendUtil.java
New file
@@ -0,0 +1,82 @@
package com.ruoyi.system.utils;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.utils.HttpUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.system.utils.wx.model.WeixinProperties;
import com.ruoyi.system.utils.wx.template.Template;
import com.ruoyi.system.utils.wx.template.wxTemplateTaskReturn.WxTemplateTaskResultRequest;
import com.ruoyi.system.utils.wx.template.wxTemplateTaskReturn.WxTemplateTaskResultRequestData;
import com.ruoyi.system.utils.wx.tools.WxAppletTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.io.Serializable;
/**
 * 消息模板发送
 */
@Slf4j
@Component
public class TemplateMessageSendUtil implements Serializable {
    private final static String ACCESSTOKEN_CACHE_KEY = "accessToken:";
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private RestTemplate wxRestTemplate;
    @Autowired
    private WeixinProperties weixinProperties;
    @Resource
    private RedisService redisService;
    /**
     * 任务数据提交结果通知
     * @param openId 用户openId
     * @param taskName 任务名称
     * @param auditResult 审核结果
     * @param auditPerson 审核人
     */
    public void wxTemplateTaskResultRequest(String openId,String taskName,String auditResult,String auditPerson) {
        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, weixinProperties, redisService);
        // 1,获取access_token
        String accessToken = redisCache.getCacheObject(ACCESSTOKEN_CACHE_KEY);
        if (!StringUtils.hasLength(accessToken)) {
            accessToken = appletTools.getAccessToken();
        }
        try {
            log.info("任务数据提交结果通知:------------------------");
            // 创建请求实体
            WxTemplateTaskResultRequest wxTemplateTaskResultRequest = new WxTemplateTaskResultRequest();
            wxTemplateTaskResultRequest.setTouser(openId);
            wxTemplateTaskResultRequest.setTemplate_id(weixinProperties.getTaskResultTemplateId());
            // 任务名称
            Template thing1 = new Template();
            thing1.setValue(taskName);
            // 审核结果
            Template phrase4 = new Template();
            phrase4.setValue(auditResult);
            // 审核人
            Template thing3 = new Template();
            thing3.setValue(auditPerson);
            // 发送模板消息参数实体封装
            WxTemplateTaskResultRequestData wxTemplateTaskResultRequestData = new WxTemplateTaskResultRequestData();
            wxTemplateTaskResultRequestData.setThing1(thing1);
            wxTemplateTaskResultRequestData.setPhrase4(phrase4);
            wxTemplateTaskResultRequestData.setThing3(thing3);
            wxTemplateTaskResultRequest.setData(wxTemplateTaskResultRequestData);
            // 4,发送消息给用户
            String url = Constants.TEMPLATE_URL.replace("ACCESS_TOKEN", accessToken);
            String result = HttpUtils.sendPost(url, JsonUtils.toJsonString(wxTemplateTaskResultRequest));
            log.info("任务数据提交结果通知模板消息返回数据:{}", result);
        } catch (Exception e) {
            log.error("任务数据提交结果通知失败;");
        }
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/config/JacksonConfig.java
New file
@@ -0,0 +1,35 @@
package com.ruoyi.system.utils.wx.config;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.format.DateTimeFormatter;
/**
 * @author liheng
 * @ClassName LocalDateTimeSerializerConfig
 * @Description
 * @date 2020-09-22 11:22
 */
@Configuration
public class JacksonConfig {
    public static final String dateFormat = "yyyy-MM-dd";
    public static final String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
        return builder -> {
            // Long型精度丢失问题
            // builder.serializerByType(Long.TYPE, ToStringSerializer.instance);
            builder.serializerByType(Long.class, ToStringSerializer.instance);
            // 时间格式化
            builder.simpleDateFormat(dateTimeFormat);
            builder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat)));
            builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
        };
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/model/WeixinProperties.java
@@ -37,6 +37,20 @@
     * @return secret ID
     */
    private String secretId;
    /**
     * 任务驳回通知 || 任务审核通过通知
     *
     * @return secret ID
     */
    private String taskResultTemplateId;
    public String getTaskResultTemplateId() {
        return taskResultTemplateId;
    }
    public void setTaskResultTemplateId(String taskResultTemplateId) {
        this.taskResultTemplateId = taskResultTemplateId;
    }
    public String getSecretId() {
        return secretId;
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletUserEncrypteData.java
@@ -15,6 +15,4 @@
    private String rawData;
    private String signature;
    private String code;
    @ApiModelProperty(value = "邀请用户id")
    private Long inviteUserId;
}
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/template/Template.java
New file
@@ -0,0 +1,19 @@
package com.ruoyi.system.utils.wx.template;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
 * @Description 微信消息模板参数实体
 * @Author xiaochen
 * @Date 2021/11/8 10:30
 */
@Data
public class Template implements Serializable{
    @ApiModelProperty(value = "消息内容")
    private String value;
}
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/template/wxTemplateTaskReturn/WxTemplateTaskResultRequest.java
New file
@@ -0,0 +1,22 @@
package com.ruoyi.system.utils.wx.template.wxTemplateTaskReturn;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel(value = "任务驳回消息模板配置")
public class WxTemplateTaskResultRequest implements Serializable {
    @ApiModelProperty(value = "用户openid")
    private String touser;
    @ApiModelProperty(value = "消息模板id")
    private String template_id;
    @ApiModelProperty(value = "消息模板data数据")
    private WxTemplateTaskResultRequestData data;
}
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/template/wxTemplateTaskReturn/WxTemplateTaskResultRequestData.java
New file
@@ -0,0 +1,23 @@
package com.ruoyi.system.utils.wx.template.wxTemplateTaskReturn;
import com.ruoyi.system.utils.wx.template.Template;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel(value = "任务驳回消息模板配置数据")
public class WxTemplateTaskResultRequestData implements Serializable {
    @ApiModelProperty(value = "任务名称")
    private Template thing1;
    @ApiModelProperty(value = "审核结果")
    private Template phrase4;
    @ApiModelProperty(value = "审核人")
    private Template thing3;
}
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxAppletTools.java
@@ -21,7 +21,7 @@
 */
@Slf4j
public class WxAppletTools {
    private final static String ACCESSTOKEN_CACHE_KEY = "accessToken";
    private final static String ACCESSTOKEN_CACHE_KEY = "accessToken:";
    /**
     * 请求参数
     * 属性    类型    默认值    必填    说明
@@ -103,8 +103,8 @@
    /**
     * @return
     */
    public String getAccessToken(String version) {
        String accessToken = redisService.getCacheObject(ACCESSTOKEN_CACHE_KEY + version);
    public String getAccessToken() {
        String accessToken = redisService.getCacheObject(ACCESSTOKEN_CACHE_KEY);
        if (StringUtils.hasLength(accessToken)) {
            return accessToken;
        }
@@ -116,7 +116,7 @@
            // 抛出错误
            throw new WxException(accessTokenRespBody.getErrorCode() + ":" + accessTokenRespBody.getErrorMsg());
        }
        redisService.setCacheObject(ACCESSTOKEN_CACHE_KEY + version, accessTokenRespBody.getAccessToken(), 7200L, TimeUnit.SECONDS);
        redisService.setCacheObject(ACCESSTOKEN_CACHE_KEY, accessTokenRespBody.getAccessToken(), 7200L, TimeUnit.SECONDS);
        return accessTokenRespBody.getAccessToken();
    }
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -28,6 +28,7 @@
        <result property="businessDeptId"       column="business_dept_id"       />
        <result property="roleName"       column="role_name"       />
        <result property="code"       column="code"       />
        <result property="openId"       column="openId"       />
        <result property="deptType"       column="deptType"       />
        <association property="dept"    javaType="SysDept"         resultMap="deptResult" />
        <collection  property="roles"   javaType="java.util.List"  resultMap="RoleResult" />
@@ -413,6 +414,7 @@
            <if test="deptType != null">deptType=#{deptType},</if>
            <if test="templateId != null">templateId=#{templateId},</if>
            <if test="code != null and code != ''">code = #{code},</if>
            <if test="openId != null and openId != ''">openId = #{openId},</if>
            update_time = sysdate()
         </set>