| | |
| | | |
| | | <!-- 任务编号单独一行 --> |
| | | <view class="task-code-row"> |
| | | <text class="task-code">{{ task.taskNo }}</text> |
| | | <text class="task-code">{{ task.showTaskCode }}</text> |
| | | </view> |
| | | |
| | | <!-- 任务详细信息 --> |
| | |
| | | |
| | | <!-- 任务编号单独一行 --> |
| | | <view class="task-code-row"> |
| | | <text class="task-code">{{ task.taskCode }}</text> |
| | | <text class="task-code">{{ task.showTaskCode }}</text> |
| | | </view> |
| | | |
| | | <!-- 任务详细信息 --> |
| | |
| | | // 应用任务编号筛选 - 使用taskCode而不是taskNo |
| | | if (this.searchForm.taskNo) { |
| | | filtered = filtered.filter(task => |
| | | task.taskCode && task.taskCode.includes(this.searchForm.taskNo) |
| | | task.showTaskCode && task.showTaskCode.includes(this.searchForm.taskNo) |
| | | ); |
| | | } |
| | | |
| | |
| | | <view class="section-title">基本信息</view> |
| | | <view class="info-item"> |
| | | <view class="label">任务编号</view> |
| | | <view class="value">{{ taskDetail.taskCode }}</view> |
| | | <view class="value">{{ taskDetail.showTaskCode }}</view> |
| | | </view> |
| | | <view class="info-item"> |
| | | <view class="label">任务类型</view> |
| | |
| | | package com.ruoyi.web.controller.sms; |
| | | |
| | | import com.ruoyi.common.annotation.Anonymous; |
| | | import com.ruoyi.common.core.domain.AjaxResult; |
| | | import com.ruoyi.system.service.IQyWechatService; |
| | | import com.ruoyi.system.service.ISysTaskService; |
| | | import com.ruoyi.system.service.IWechatTaskNotifyService; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | |
| | |
| | | |
| | | @Autowired |
| | | private IWechatTaskNotifyService wechatTaskNotifyService; |
| | | |
| | | @Autowired |
| | | private IQyWechatService qyWechatService; |
| | | |
| | | @Autowired |
| | | private ISysTaskService taskService; |
| | | @Anonymous |
| | | @PostMapping("/sendWeiXin") |
| | | public String notify(@RequestBody @Validated SendTaskReq req) { |
| | |
| | | System.out.println(result); |
| | | return "success"; |
| | | } |
| | | |
| | | @Anonymous() |
| | | @GetMapping("/dispatchSyncEvent") |
| | | public Boolean dispatchSyncEvent(@RequestParam Long taskId) { |
| | | return taskService.dispatchSyncEvent(taskId); |
| | | } |
| | | |
| | | @Anonymous() |
| | | @PostMapping("sendQyWeiXin") |
| | | public String sendQyWeiXin(@RequestBody @Validated SendTaskReq req) { |
| | | |
| | | |
| | | String title="医疗运转单派送"; |
| | | String content="您有新的医疗运转单派送,请及时处理"; |
| | | String notifyUrl="https://sys.966120.com.cn/m_DispatchOrder.gds?dispatchId=102311"; |
| | | java.lang.Boolean result =qyWechatService.sendNotifyMessage(req.getUserId(), title,content,notifyUrl); |
| | | System.out.println(result); |
| | | return "success"; |
| | | |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ruoyi.web.controller.system; |
| | | |
| | | import com.ruoyi.common.annotation.Anonymous; |
| | | import com.ruoyi.common.core.controller.BaseController; |
| | | import com.ruoyi.common.core.domain.AjaxResult; |
| | | import com.ruoyi.system.service.IQyWechatAccessTokenService; |
| | | import com.ruoyi.system.service.IQyWechatService; |
| | | import com.ruoyi.system.service.ISysConfigService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | /** |
| | | * 企业微信测试控制器 |
| | | * 用于测试企业微信AccessToken获取和消息发送功能 |
| | | * |
| | | * @author ruoyi |
| | | * @date 2025-12-11 |
| | | */ |
| | | @Anonymous() |
| | | @RestController |
| | | @RequestMapping("/system/qywechat/test") |
| | | public class QyWechatTestController extends BaseController { |
| | | |
| | | @Autowired |
| | | private IQyWechatAccessTokenService qyWechatAccessTokenService; |
| | | |
| | | @Autowired |
| | | private IQyWechatService qyWechatService; |
| | | |
| | | @Autowired |
| | | private ISysConfigService configService; |
| | | |
| | | /** |
| | | * 测试获取企业微信AccessToken |
| | | */ |
| | | @Anonymous() |
| | | @GetMapping("/token") |
| | | public AjaxResult testGetToken() { |
| | | try { |
| | | String corpId = configService.selectConfigByKey("qy_wechat.corp_id"); |
| | | String corpSecret = configService.selectConfigByKey("qy_wechat.corp_secret"); |
| | | |
| | | if (corpId == null || corpSecret == null) { |
| | | return AjaxResult.error("企业微信配置不完整,请检查corp_id和corp_secret配置"); |
| | | } |
| | | |
| | | String accessToken = qyWechatAccessTokenService.getAppAccessToken(corpId, corpSecret); |
| | | |
| | | if (accessToken != null) { |
| | | return AjaxResult.success("获取AccessToken成功", accessToken); |
| | | } else { |
| | | return AjaxResult.error("获取AccessToken失败"); |
| | | } |
| | | } catch (Exception e) { |
| | | return AjaxResult.error("获取AccessToken异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 测试刷新企业微信AccessToken |
| | | */ |
| | | @Anonymous() |
| | | @PostMapping("/refreshToken") |
| | | public AjaxResult testRefreshToken() { |
| | | try { |
| | | String corpId = configService.selectConfigByKey("qy_wechat.corp_id"); |
| | | String corpSecret = configService.selectConfigByKey("qy_wechat.corp_secret"); |
| | | |
| | | if (corpId == null || corpSecret == null) { |
| | | return AjaxResult.error("企业微信配置不完整,请检查corp_id和corp_secret配置"); |
| | | } |
| | | |
| | | String accessToken = qyWechatAccessTokenService.refreshAppAccessToken(corpId, corpSecret); |
| | | |
| | | if (accessToken != null) { |
| | | return AjaxResult.success("刷新AccessToken成功", accessToken); |
| | | } else { |
| | | return AjaxResult.error("刷新AccessToken失败"); |
| | | } |
| | | } catch (Exception e) { |
| | | return AjaxResult.error("刷新AccessToken异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 测试发送企业微信消息 |
| | | */ |
| | | @Anonymous() |
| | | @PostMapping("/sendMessage") |
| | | public AjaxResult testSendMessage(@RequestParam Long userId, |
| | | @RequestParam String title, |
| | | @RequestParam String content,@RequestParam String notifyUrl) { |
| | | try { |
| | | boolean result = qyWechatService.sendNotifyMessage(userId, title, content,notifyUrl); |
| | | |
| | | if (result) { |
| | | return AjaxResult.success("发送企业微信消息成功"); |
| | | } else { |
| | | return AjaxResult.error("发送企业微信消息失败"); |
| | | } |
| | | } catch (Exception e) { |
| | | return AjaxResult.error("发送企业微信消息异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 测试发送企业微信文本消息 |
| | | */ |
| | | @Anonymous() |
| | | @PostMapping("/sendTextMessage") |
| | | public AjaxResult testSendTextMessage(@RequestParam String qyUserId, |
| | | @RequestParam String title, |
| | | @RequestParam String content, |
| | | @RequestParam String notifyUrl) { |
| | | try { |
| | | boolean result = qyWechatService.sendTextMessage(qyUserId, title, content, notifyUrl); |
| | | |
| | | if (result) { |
| | | return AjaxResult.success("发送企业微信文本消息成功"); |
| | | } else { |
| | | return AjaxResult.error("发送企业微信文本消息失败"); |
| | | } |
| | | } catch (Exception e) { |
| | | return AjaxResult.error("发送企业微信文本消息异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 检查企业微信服务是否启用 |
| | | */ |
| | | @Anonymous() |
| | | @GetMapping("/enabled") |
| | | public AjaxResult checkEnabled() { |
| | | try { |
| | | boolean enabled = qyWechatService.isEnabled(); |
| | | return AjaxResult.success("企业微信服务状态:" + (enabled ? "启用" : "禁用"), enabled); |
| | | } catch (Exception e) { |
| | | return AjaxResult.error("检查企业微信服务状态异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | } |
| | |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | import com.ruoyi.common.annotation.Anonymous; |
| | | import com.ruoyi.system.domain.SysTaskEmergency; |
| | | import com.ruoyi.system.service.*; |
| | | import org.springframework.beans.factory.annotation.Qualifier; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | |
| | | |
| | | @Autowired |
| | | private ISysTaskService sysTaskService; |
| | | |
| | | @Autowired |
| | | private ISysTaskEmergencyService sysTaskEmergencyService; |
| | | |
| | | @Autowired |
| | | private IVehicleInfoService vehicleInfoService; |
| | |
| | | @GetMapping("/admin/list") |
| | | public TableDataInfo adminList(TaskQueryVO queryVO) { |
| | | startPage(); |
| | | List<SysTask> list = sysTaskService.selectSysTaskList(queryVO); |
| | | // Handle multi-field task code search |
| | | String searchTaskCode = queryVO.getTaskCode(); |
| | | List<SysTask> list; |
| | | if(searchTaskCode != null && !searchTaskCode.trim().isEmpty()){ |
| | | // Search across task_code, emergency_info.dispatch_code, and emergency_info.service_code |
| | | list = sysTaskService.selectSysTaskListByMultiCode(queryVO, searchTaskCode); |
| | | } else { |
| | | queryVO.setTaskCode(null); |
| | | list = sysTaskService.selectSysTaskList(queryVO); |
| | | } |
| | | |
| | | |
| | | return getDataTable(list); |
| | | } |
| | | |
| | |
| | | return toAjax(sysTaskService.insertSysTask(createVO)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 新增任务(APP端) |
| | | */ |
| | |
| | | appId: wx70f6a7346ee842c0 |
| | | appSecret: 2d6c59de85e876b7eadebeba62e5417a |
| | | redirectUri: http://yourdomain.com/evaluation |
| | | # 企业微信配置 |
| | | qyWeixin: |
| | | appId: wx248505bfbab6d0c1 |
| | | appSecret: 2MCilqWYC0FWjOQ894sbb-s7Lb5sVH4HHuJgOsd9l1k |
| | | # 调度用的weixin配置 |
| | | transferConfigWeixin: |
| | | appId: wx40692cc44953a8cb |
| | |
| | | /** 微信昵称 */ |
| | | private String wechatNickname; |
| | | |
| | | /** 企业微信用户ID */ |
| | | private String qyWechatUserId; |
| | | |
| | | /** 企业微信用户ID更新时间 */ |
| | | private Date qyWechatUpdateTime; |
| | | |
| | | /** 是否可查看所有咨询单(0否 1是) */ |
| | | @Excel(name = "可查看所有咨询单", readConverterExp = "0=否,1=是") |
| | | private String canViewAllConsult; |
| | |
| | | this.wechatNickname = wechatNickname; |
| | | } |
| | | |
| | | public String getQyWechatUserId() |
| | | { |
| | | return qyWechatUserId; |
| | | } |
| | | |
| | | public void setQyWechatUserId(String qyWechatUserId) |
| | | { |
| | | this.qyWechatUserId = qyWechatUserId; |
| | | } |
| | | |
| | | public Date getQyWechatUpdateTime() |
| | | { |
| | | return qyWechatUpdateTime; |
| | | } |
| | | |
| | | public void setQyWechatUpdateTime(Date qyWechatUpdateTime) |
| | | { |
| | | this.qyWechatUpdateTime = qyWechatUpdateTime; |
| | | } |
| | | |
| | | public String getCanViewAllConsult() |
| | | { |
| | | return canViewAllConsult; |
| | |
| | | .append("openId", getOpenId()) |
| | | .append("unionId", getUnionId()) |
| | | .append("wechatNickname", getWechatNickname()) |
| | | .append("qyWechatUserId", getQyWechatUserId()) |
| | | .append("qyWechatUpdateTime", getQyWechatUpdateTime()) |
| | | .append("canViewAllConsult", getCanViewAllConsult()) |
| | | |
| | | .toString(); |
| New file |
| | |
| | | package com.ruoyi.common.utils; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.Date; |
| | | import java.util.Map; |
| | | |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | |
| | | /** |
| | | * Map值转换工具类 |
| | | * 提供从Map中安全获取各种类型值的方法 |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public class MapValueUtils { |
| | | |
| | | /** |
| | | * 从Map中获取字符串值 |
| | | * |
| | | * @param map Map对象 |
| | | * @param key 键 |
| | | * @return 字符串值,如果键不存在或值为null则返回null |
| | | */ |
| | | public static String getStringValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | return value != null ? value.toString() : null; |
| | | } |
| | | |
| | | /** |
| | | * 从Map中获取BigDecimal值 |
| | | * |
| | | * @param map Map对象 |
| | | * @param key 键 |
| | | * @return BigDecimal值,如果键不存在或值为null则返回null,转换失败也返回null |
| | | */ |
| | | public static BigDecimal getBigDecimalValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | if (value instanceof BigDecimal) { |
| | | return (BigDecimal) value; |
| | | } |
| | | try { |
| | | return new BigDecimal(value.toString()); |
| | | } catch (NumberFormatException e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 从Map中获取Long值 |
| | | * |
| | | * @param map Map对象 |
| | | * @param key 键 |
| | | * @return Long值,如果键不存在或值为null则返回null,转换失败也返回null |
| | | */ |
| | | public static Long getLongValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | if (value instanceof Long) { |
| | | return (Long) value; |
| | | } |
| | | try { |
| | | return Long.valueOf(value.toString()); |
| | | } catch (NumberFormatException e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 从Map中获取Integer值 |
| | | * |
| | | * @param map Map对象 |
| | | * @param key 键 |
| | | * @return Integer值,如果键不存在或值为null则返回null,转换失败也返回null |
| | | */ |
| | | public static Integer getIntegerValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | if (value instanceof Integer) { |
| | | return (Integer) value; |
| | | } |
| | | try { |
| | | return Integer.valueOf(value.toString()); |
| | | } catch (NumberFormatException e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 从Map中获取Date值 |
| | | * |
| | | * @param map Map对象 |
| | | * @param key 键 |
| | | * @return Date值,如果键不存在或值为null则返回null,如果是字符串会尝试解析 |
| | | */ |
| | | public static Date getDateValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | if (value instanceof Date) { |
| | | return (Date) value; |
| | | } |
| | | // 如果是字符串,尝试解析 |
| | | if (value instanceof String) { |
| | | try { |
| | | return DateUtils.parseDate(value.toString()); |
| | | } catch (Exception e) { |
| | | return null; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 验证日期字符串格式是否有效 |
| | | * |
| | | * @param dateStr 日期字符串 |
| | | * @param format 日期格式 |
| | | * @return 是否有效 |
| | | */ |
| | | public static boolean isValidDateFormat(String dateStr, String format) { |
| | | if (StringUtils.isEmpty(dateStr)) { |
| | | return false; |
| | | } |
| | | |
| | | try { |
| | | java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(format); |
| | | sdf.setLenient(false); |
| | | sdf.parse(dateStr); |
| | | return true; |
| | | } catch (Exception e) { |
| | | return false; |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ruoyi.quartz.task; |
| | | |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | import com.ruoyi.common.core.domain.AjaxResult; |
| | | import com.ruoyi.system.domain.UserSyncDTO; |
| | | import com.ruoyi.system.service.IUserSyncDataService; |
| | | import com.ruoyi.system.service.IUserSyncService; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 企业微信用户ID同步任务 |
| | | * |
| | | * 定期同步OA系统中的企业微信用户ID到本地系统 |
| | | * |
| | | * @author ruoyi |
| | | * @date 2025-12-11 |
| | | */ |
| | | @Component("qyWechatUserSyncTask") |
| | | public class QyWechatUserSyncTask |
| | | { |
| | | private static final Logger log = LoggerFactory.getLogger(QyWechatUserSyncTask.class); |
| | | |
| | | @Autowired |
| | | private IUserSyncDataService userSyncDataService; |
| | | |
| | | @Autowired |
| | | private IUserSyncService userSyncService; |
| | | |
| | | /** |
| | | * 同步企业微信用户ID |
| | | * |
| | | * 任务执行方法,由Quartz调度器调用 |
| | | * |
| | | * @return 同步结果 |
| | | */ |
| | | public AjaxResult syncQyWechatUserIds() |
| | | { |
| | | try |
| | | { |
| | | log.info("开始同步企业微信用户ID..."); |
| | | |
| | | // 1. 从SQL Server查询OA用户数据(包含企业微信用户ID) |
| | | List<UserSyncDTO> oaUsers = userSyncDataService.getOaUsers(); |
| | | |
| | | if (oaUsers == null || oaUsers.isEmpty()) |
| | | { |
| | | log.warn("未查询到OA用户数据,跳过同步"); |
| | | return AjaxResult.warn("未查询到OA用户数据"); |
| | | } |
| | | |
| | | log.info("从OA系统查询到 {} 条用户数据", oaUsers.size()); |
| | | |
| | | // 2. 同步到MySQL数据库 |
| | | AjaxResult result = userSyncService.syncOaUsers(oaUsers); |
| | | |
| | | log.info("企业微信用户ID同步完成: {}", result.get("msg")); |
| | | return result; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | log.error("同步企业微信用户ID失败", e); |
| | | return AjaxResult.error("同步失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | } |
| | |
| | | public static final String CHANNEL_SITE_MSG = "SITE_MSG"; |
| | | /** 渠道:APP推送 */ |
| | | public static final String CHANNEL_APP_PUSH = "APP_PUSH"; |
| | | /** 渠道:企业微信 */ |
| | | public static final String CHANNEL_QY_WECHAT = "QY_WECHAT"; |
| | | |
| | | // ==================== 启用状态常量 ==================== |
| | | /** 启用 */ |
| | |
| | | @Excel(name = "发送状态") |
| | | private String sendStatus; |
| | | |
| | | /** 发送的内容 */ |
| | | private String sendContent; |
| | | |
| | | /** 发送时间 */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @Excel(name = "发送时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") |
| | |
| | | this.sendResult = sendResult; |
| | | } |
| | | |
| | | public String getSendContent() { |
| | | return sendContent; |
| | | } |
| | | |
| | | public void setSendContent(String sendContent) { |
| | | this.sendContent = sendContent; |
| | | } |
| | | |
| | | public String getResponseMsg() { |
| | | return responseMsg; |
| | | } |
| | |
| | | .append("sendStatus", getSendStatus()) |
| | | .append("sendTime", getSendTime()) |
| | | .append("sendResult", getSendResult()) |
| | | .append("sendContent", getSendContent()) |
| | | .append("retryCount", getRetryCount()) |
| | | .append("createTime", getCreateTime()) |
| | | .append("createBy", getCreateBy()) |
| New file |
| | |
| | | package com.ruoyi.system.domain; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * 企业微信文章实体类 |
| | | * |
| | | * @author ruoyi |
| | | * @date 2025-12-13 |
| | | */ |
| | | public class QyWechatArticle implements Serializable { |
| | | /** 文章标题 */ |
| | | private String title; |
| | | |
| | | /** 文章描述 */ |
| | | private String description; |
| | | |
| | | /** 点击后跳转的链接 */ |
| | | private String url; |
| | | |
| | | /** 图文消息的图片链接 */ |
| | | private String picurl; |
| | | |
| | | /** 小程序appid */ |
| | | private String appid; |
| | | |
| | | /** 小程序页面路径 */ |
| | | private String pagepath; |
| | | |
| | | // Getters and Setters |
| | | public String getTitle() { |
| | | return title; |
| | | } |
| | | |
| | | public void setTitle(String title) { |
| | | this.title = title; |
| | | } |
| | | |
| | | public String getDescription() { |
| | | return description; |
| | | } |
| | | |
| | | public void setDescription(String description) { |
| | | this.description = description; |
| | | } |
| | | |
| | | public String getUrl() { |
| | | return url; |
| | | } |
| | | |
| | | public void setUrl(String url) { |
| | | this.url = url; |
| | | } |
| | | |
| | | public String getPicurl() { |
| | | return picurl; |
| | | } |
| | | |
| | | public void setPicurl(String picurl) { |
| | | this.picurl = picurl; |
| | | } |
| | | |
| | | public String getAppid() { |
| | | return appid; |
| | | } |
| | | |
| | | public void setAppid(String appid) { |
| | | this.appid = appid; |
| | | } |
| | | |
| | | public String getPagepath() { |
| | | return pagepath; |
| | | } |
| | | |
| | | public void setPagepath(String pagepath) { |
| | | this.pagepath = pagepath; |
| | | } |
| | | } |
| | |
| | | /** 福祉车扩展信息 */ |
| | | private SysTaskWelfare welfareInfo; |
| | | |
| | | private String showTaskCode; |
| | | public void setShowTaskCode(String showTaskCode) { |
| | | showTaskCode=this.showTaskCode; |
| | | } |
| | | /** |
| | | * 获取显示任务编号,优先返回急救转运的调度单编号,其次是服务单编号,最后是任务编号 |
| | | */ |
| | | public String getShowTaskCode(){ |
| | | |
| | | if(this.emergencyInfo!=null){ |
| | | String dispatchOrdCode=this.emergencyInfo.getDispatchCode(); |
| | | if(dispatchOrdCode!=null){ |
| | | return dispatchOrdCode; |
| | | } |
| | | String serviceOrdCode=this.emergencyInfo.getServiceCode(); |
| | | if(serviceOrdCode!=null){ |
| | | return serviceOrdCode; |
| | | } |
| | | } |
| | | return this.taskCode; |
| | | } |
| | | |
| | | public void setTaskId(Long taskId) { |
| | | this.taskId = taskId; |
| | | } |
| | |
| | | |
| | | import java.math.BigDecimal; |
| | | import com.ruoyi.common.core.domain.BaseEntity; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | |
| | | /** |
| | | * 急救转运任务扩展信息对象 sys_task_emergency |
| | |
| | | /** 旧系统ServiceOrdNo(转运单编号) */ |
| | | private String legacyServiceOrdNo; |
| | | |
| | | /** 旧系统调度单编号 */ |
| | | private String legacyDispatchOrdNo; |
| | | |
| | | /** 旧系统服务通知时间 */ |
| | | private java.util.Date legacyServiceNsTime; |
| | | |
| | | /** 旧系统调度通知时间 */ |
| | | private java.util.Date legacyDispatchNsTime; |
| | | |
| | | /** 旧系统调度单分类 */ |
| | | private String legacyDispatchOrdClass; |
| | | |
| | | /** 旧系统服务单分类 */ |
| | | private String legacyServiceOrdClass; |
| | | |
| | | public String getServiceCode(){ |
| | | if(this.legacyServiceOrdClass!=null && this.legacyServiceNsTime!=null && this.legacyServiceOrdNo!=null) { |
| | | String nstime = DateUtils.parseDateToStr(DateUtils.YYYYMMDD, this.legacyServiceNsTime); |
| | | return this.legacyServiceOrdClass + nstime +'-'+ this.legacyServiceOrdNo; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public String getDispatchCode(){ |
| | | if(this.legacyDispatchOrdClass!=null && this.legacyDispatchNsTime!=null && this.legacyDispatchOrdNo!=null) { |
| | | String nstime = DateUtils.parseDateToStr(DateUtils.YYYYMMDD, this.legacyDispatchNsTime); |
| | | //serviceOrdNo 这个是数字,固定3位数 ,将32,转成032;将1转成001 |
| | | Integer intServiceNo = Integer.valueOf(this.legacyDispatchOrdNo); |
| | | String ordNoStr = String.format("%03d", intServiceNo); |
| | | return this.legacyDispatchOrdClass + nstime + "-" + ordNoStr; |
| | | }else{ |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | |
| | | public Long getId() { |
| | |
| | | this.legacyServiceOrdNo = legacyServiceOrdNo; |
| | | } |
| | | |
| | | public String getLegacyDispatchOrdNo() { |
| | | return legacyDispatchOrdNo; |
| | | } |
| | | |
| | | public void setLegacyDispatchOrdNo(String legacyDispatchOrdNo) { |
| | | this.legacyDispatchOrdNo = legacyDispatchOrdNo; |
| | | } |
| | | |
| | | public java.util.Date getLegacyServiceNsTime() { |
| | | return legacyServiceNsTime; |
| | | } |
| | | |
| | | public void setLegacyServiceNsTime(java.util.Date legacyServiceNsTime) { |
| | | this.legacyServiceNsTime = legacyServiceNsTime; |
| | | } |
| | | |
| | | public java.util.Date getLegacyDispatchNsTime() { |
| | | return legacyDispatchNsTime; |
| | | } |
| | | |
| | | public void setLegacyDispatchNsTime(java.util.Date legacyDispatchNsTime) { |
| | | this.legacyDispatchNsTime = legacyDispatchNsTime; |
| | | } |
| | | |
| | | public String getLegacyDispatchOrdClass() { |
| | | return legacyDispatchOrdClass; |
| | | } |
| | | |
| | | public void setLegacyDispatchOrdClass(String legacyDispatchOrdClass) { |
| | | this.legacyDispatchOrdClass = legacyDispatchOrdClass; |
| | | } |
| | | |
| | | public String getLegacyServiceOrdClass() { |
| | | return legacyServiceOrdClass; |
| | | } |
| | | |
| | | public void setLegacyServiceOrdClass(String legacyServiceOrdClass) { |
| | | this.legacyServiceOrdClass = legacyServiceOrdClass; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "SysTaskEmergency{" + |
| | |
| | | ", hospitalInName='" + hospitalInName + '\'' + |
| | | ", transferDistance=" + transferDistance + |
| | | ", transferPrice=" + transferPrice + |
| | | ", legacyServiceOrdNo='" + legacyServiceOrdNo + '\'' + |
| | | ", legacyDispatchOrdNo='" + legacyDispatchOrdNo + '\'' + |
| | | ", legacyServiceNsTime=" + legacyServiceNsTime + |
| | | ", legacyDispatchNsTime=" + legacyDispatchNsTime + |
| | | ", legacyDispatchOrdClass='" + legacyDispatchOrdClass + '\'' + |
| | | ", legacyServiceOrdClass='" + legacyServiceOrdClass + '\'' + |
| | | '}'; |
| | | } |
| | | } |
| | |
| | | /** SQL Server中的OA用户ID */ |
| | | private Integer oaUserId; |
| | | |
| | | /** 企业微信用户ID */ |
| | | private String oaWeixinUserId; |
| | | |
| | | /** 用户账号 */ |
| | | private String userName; |
| | | |
| | |
| | | public void setOaUserId(Integer oaUserId) |
| | | { |
| | | this.oaUserId = oaUserId; |
| | | } |
| | | |
| | | public String getOaWeixinUserId() |
| | | { |
| | | return oaWeixinUserId; |
| | | } |
| | | |
| | | public void setOaWeixinUserId(String oaWeixinUserId) |
| | | { |
| | | this.oaWeixinUserId = oaWeixinUserId; |
| | | } |
| | | |
| | | public String getUserName() |
| | |
| | | { |
| | | return "UserSyncDTO{" + |
| | | "oaUserId=" + oaUserId + |
| | | ", oaWeixinUserId='" + oaWeixinUserId + '\'' + |
| | | ", userName='" + userName + '\'' + |
| | | ", nickName='" + nickName + '\'' + |
| | | ", departmentId=" + departmentId + |
| | |
| | | /** 病情ID列表(ICD-10疾病ID列表,用于同步调度单的OrdICD_ID参数) */ |
| | | private List<Long> diseaseIds; |
| | | |
| | | /** 旧系统调度单编号 */ |
| | | private String legacyDispatchOrdNo; |
| | | |
| | | /** 旧系统服务通知时间 */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date legacyServiceNsTime; |
| | | |
| | | /** 旧系统调度通知时间 */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date legacyDispatchNsTime; |
| | | |
| | | /** 旧系统调度单分类 */ |
| | | private String legacyDispatchOrdClass; |
| | | |
| | | /** 旧系统服务单分类 */ |
| | | private String legacyServiceOrdClass; |
| | | |
| | | private Date createTime; |
| | | |
| | | private String taskStatus; |
| | |
| | | public void setDiseaseIds(List<Long> diseaseIds) { |
| | | this.diseaseIds = diseaseIds; |
| | | } |
| | | |
| | | public String getLegacyDispatchOrdNo() { |
| | | return legacyDispatchOrdNo; |
| | | } |
| | | |
| | | public void setLegacyDispatchOrdNo(String legacyDispatchOrdNo) { |
| | | this.legacyDispatchOrdNo = legacyDispatchOrdNo; |
| | | } |
| | | |
| | | public Date getLegacyServiceNsTime() { |
| | | return legacyServiceNsTime; |
| | | } |
| | | |
| | | public void setLegacyServiceNsTime(Date legacyServiceNsTime) { |
| | | this.legacyServiceNsTime = legacyServiceNsTime; |
| | | } |
| | | |
| | | public Date getLegacyDispatchNsTime() { |
| | | return legacyDispatchNsTime; |
| | | } |
| | | |
| | | public void setLegacyDispatchNsTime(Date legacyDispatchNsTime) { |
| | | this.legacyDispatchNsTime = legacyDispatchNsTime; |
| | | } |
| | | |
| | | public String getLegacyDispatchOrdClass() { |
| | | return legacyDispatchOrdClass; |
| | | } |
| | | |
| | | public void setLegacyDispatchOrdClass(String legacyDispatchOrdClass) { |
| | | this.legacyDispatchOrdClass = legacyDispatchOrdClass; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.event; |
| | | |
| | | /** |
| | | * 任务同步调度单成功后触发事件 |
| | | */ |
| | | public class TaskDispatchSyncEvent extends TaskEvent{ |
| | | |
| | | private Long dispatchOrderId; |
| | | |
| | | public Long getDispatchOrderId(){ |
| | | return this.dispatchOrderId; |
| | | } |
| | | private Integer oaUserId; |
| | | public Integer getOaUserId(){ |
| | | return this.oaUserId; |
| | | } |
| | | private Long serviceOrderId; |
| | | public Long getServiceOrderId(){ |
| | | return this.serviceOrderId; |
| | | } |
| | | public TaskDispatchSyncEvent(Object source, Long taskId, String taskCode,Long serviceOrderId, Long dispatchOrderId,Integer oaUserId) { |
| | | super(source, taskId, taskCode); |
| | | this.dispatchOrderId=dispatchOrderId; |
| | | this.oaUserId=oaUserId; |
| | | this.serviceOrderId=serviceOrderId; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.event; |
| | | |
| | | /** |
| | | * 服务单同步任务成功后触发事件 |
| | | */ |
| | | public class TaskServiceOrderSyncEvent extends TaskEvent{ |
| | | |
| | | private Long serviceOrderId; |
| | | public Long getServiceOrderId(){ |
| | | return this.serviceOrderId; |
| | | } |
| | | public TaskServiceOrderSyncEvent(Object source, Long taskId, String taskCode,Long serviceOrderId) { |
| | | super(source, taskId, taskCode); |
| | | this.serviceOrderId=serviceOrderId; |
| | | } |
| | | } |
| | |
| | | package com.ruoyi.system.listener; |
| | | |
| | | import com.ruoyi.system.domain.*; |
| | | import com.ruoyi.system.event.TaskDispatchSyncEvent; |
| | | import com.ruoyi.system.service.ISysTaskAssigneeService; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | import org.springframework.stereotype.Component; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.system.domain.SysMessage; |
| | | import com.ruoyi.system.domain.SysTask; |
| | | import com.ruoyi.system.domain.SysTaskEmergency; |
| | | import com.ruoyi.system.domain.NotifyTask; |
| | | import com.ruoyi.system.event.TaskCreatedEvent; |
| | | import com.ruoyi.system.event.TaskAssignedEvent; |
| | | import com.ruoyi.system.event.TaskStatusChangedEvent; |
| | |
| | | import com.ruoyi.system.service.INotifyTaskService; |
| | | import com.ruoyi.system.service.INotifyDispatchService; |
| | | |
| | | import java.text.DateFormat; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 任务消息监听器 |
| | |
| | | /** 待准备状态 - 可以发送短信通知 */ |
| | | private static final String TASK_STATUS_PREPARING = "PREPARING"; |
| | | |
| | | @Autowired |
| | | private ISysTaskAssigneeService taskAssigneeService; |
| | | |
| | | @Async |
| | | @EventListener |
| | | public void handleTaskDispatchEvent(TaskDispatchSyncEvent event) { |
| | | try{ |
| | | log.info("收到任务派发同步事件,任务ID:{},任务编号:{},派发单ID:{}", event.getTaskId(), event.getTaskCode(), event.getDispatchOrderId()); |
| | | SysTask task=sysTaskMapper.selectSysTaskByTaskId(event.getTaskId()); |
| | | SysTaskEmergency emergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(event.getTaskId()); |
| | | if(emergency != null){ |
| | | List<SysTaskAssignee> assignees=taskAssigneeService.getAssigneesByTaskId(emergency.getTaskId()); |
| | | if(assignees!=null && !assignees.isEmpty()){ |
| | | List<Long> assigneeIds=assignees.stream().map(SysTaskAssignee::getUserId).collect(Collectors.toList()); |
| | | sendDispatchNotify(assigneeIds, task.getCreatorId(), event.getTaskId(), task.getTaskCode(), buildNotifyContent(task, emergency)); |
| | | } |
| | | } |
| | | |
| | | }catch (Exception ex){ |
| | | log.error("处理任务派发同步事件失败", ex); |
| | | } |
| | | } |
| | | /** |
| | | * 监听任务创建事件 |
| | | * |
| | |
| | | |
| | | // 构建通知内容 |
| | | String notifyContent = buildNotifyContent(task, emergency); |
| | | |
| | | // 收集创建的通知任务 |
| | | List<NotifyTask> createdTasks = new ArrayList<>(); |
| | | |
| | | // 为每个执行人创建通知任务 |
| | | for (Long assigneeId : event.getAssigneeIds()) { |
| | | // 排除创建人 |
| | | if (creatorId != null && creatorId.equals(assigneeId)) { |
| | | log.debug("跳过创建人,不发送任务分配通知,userId={}", assigneeId); |
| | | continue; |
| | | } |
| | | |
| | | // 获取执行人信息 |
| | | SysUser assignee = sysUserMapper.selectUserById(assigneeId); |
| | | if (assignee == null) { |
| | | log.warn("找不到执行人信息,用户ID:{}", assigneeId); |
| | | continue; |
| | | } |
| | | |
| | | // 创建通知任务(带防重) |
| | | NotifyTask notifyTask = new NotifyTask(); |
| | | notifyTask.setTaskId(event.getTaskId()); |
| | | notifyTask.setTaskCode(event.getTaskCode()); |
| | | notifyTask.setNotifyType(NotifyTask.NOTIFY_TYPE_TASK_ASSIGN); |
| | | notifyTask.setUserId(assigneeId); |
| | | notifyTask.setUserName(assignee.getNickName()); |
| | | notifyTask.setUserPhone(assignee.getPhonenumber()); |
| | | notifyTask.setTitle("任务推送"); |
| | | notifyTask.setContent(notifyContent); |
| | | notifyTask.setCreateBy(event.getAssignerName() != null ? event.getAssignerName() : "系统"); |
| | | |
| | | NotifyTask created = notifyTaskService.createNotifyTask(notifyTask); |
| | | if (created != null) { |
| | | createdTasks.add(created); |
| | | log.info("创建通知任务成功,id={}, userId={}", created.getId(), assigneeId); |
| | | } else { |
| | | log.info("通知任务已存在,跳过,taskId={}, userId={}", event.getTaskId(), assigneeId); |
| | | } |
| | | } |
| | | this.sendDispatchNotify(event.getAssigneeIds(), creatorId, event.getTaskId(), event.getTaskCode(), notifyContent); |
| | | |
| | | // 分发通知任务 |
| | | if (!createdTasks.isEmpty()) { |
| | | int successCount = notifyDispatchService.dispatchNotifies(createdTasks); |
| | | log.info("通知分发完成,taskId={},创建数量={},成功数量={}", |
| | | event.getTaskId(), createdTasks.size(), successCount); |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | log.error("处理任务分配事件失败", e); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 向执行人发送任务分配通知 |
| | | * @param assigneeIds |
| | | * @param creatorId |
| | | * @param taskId |
| | | * @param taskCode |
| | | * |
| | | * @param notifyContent |
| | | */ |
| | | |
| | | private void sendDispatchNotify(List<Long> assigneeIds, Long creatorId, |
| | | Long taskId,String taskCode,String notifyContent) { |
| | | // 收集创建的通知任务 |
| | | |
| | | List<NotifyTask> createdTasks = new ArrayList<>(); |
| | | |
| | | // 为每个执行人创建通知任务 |
| | | for (Long assigneeId : assigneeIds) { |
| | | // 排除创建人 |
| | | if (creatorId != null && creatorId.equals(assigneeId)) { |
| | | log.debug("跳过创建人,不发送任务分配通知,userId={}", assigneeId); |
| | | continue; |
| | | } |
| | | |
| | | // 获取执行人信息 |
| | | SysUser assignee = sysUserMapper.selectUserById(assigneeId); |
| | | if (assignee == null) { |
| | | log.warn("找不到执行人信息,用户ID:{}", assigneeId); |
| | | continue; |
| | | } |
| | | |
| | | // 创建通知任务(带防重) |
| | | NotifyTask notifyTask = new NotifyTask(); |
| | | notifyTask.setTaskId(taskId); |
| | | notifyTask.setTaskCode(taskCode); |
| | | notifyTask.setNotifyType(NotifyTask.NOTIFY_TYPE_TASK_ASSIGN); |
| | | notifyTask.setUserId(assigneeId); |
| | | notifyTask.setUserName(assignee.getNickName()); |
| | | notifyTask.setUserPhone(assignee.getPhonenumber()); |
| | | notifyTask.setTitle("转运单任务派单通知"); |
| | | notifyTask.setContent(notifyContent); |
| | | notifyTask.setCreateBy( "系统"); |
| | | |
| | | NotifyTask created = notifyTaskService.createNotifyTask(notifyTask); |
| | | if (created != null) { |
| | | createdTasks.add(created); |
| | | log.info("创建通知任务成功,id={}, userId={}", created.getId(), assigneeId); |
| | | } else { |
| | | log.info("通知任务已存在,跳过,taskId={}, userId={}", taskId, assigneeId); |
| | | } |
| | | } |
| | | |
| | | // 分发通知任务 |
| | | if (!createdTasks.isEmpty()) { |
| | | int successCount = notifyDispatchService.dispatchNotifies(createdTasks); |
| | | log.info("通知分发完成,taskId={},创建数量={},成功数量={}", |
| | | taskId, createdTasks.size(), successCount); |
| | | } |
| | | } |
| | | /** |
| | | * 构建通知内容 |
| | | */ |
| | | private String buildNotifyContent(SysTask task, SysTaskEmergency emergency) { |
| | | StringBuilder content = new StringBuilder("您有新的转运任务,请及时处理,任务单号:"+task.getTaskCode()); |
| | | |
| | | //派发单号 |
| | | String dispatchCode=emergency.getDispatchCode(); |
| | | String taskCode=task.getTaskCode(); |
| | | String orderCode=dispatchCode; |
| | | if(dispatchCode==null){ |
| | | orderCode=taskCode; |
| | | } |
| | | Date dispatchTime=task.getPlanedStartTime(); |
| | | |
| | | StringBuilder content = new StringBuilder(); |
| | | content.append("您有新的转运任务,任务单号:"+orderCode); |
| | | // 添加出发地信息 |
| | | String departure = null; |
| | | if (emergency != null && StringUtils.isNotEmpty(emergency.getHospitalOutName())) { |
| | |
| | | } else if (StringUtils.isNotEmpty(task.getDepartureAddress())) { |
| | | departure = task.getDepartureAddress(); |
| | | } |
| | | |
| | | DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm"); |
| | | content.append(",出发时间:").append(df.format(dispatchTime)); |
| | | |
| | | // 添加目的地信息 |
| | | String destination = null; |
| | | if (emergency != null && StringUtils.isNotEmpty(emergency.getHospitalInName())) { |
| | |
| | | * @param dispatchOrdID 调度单ID |
| | | * @return 转运单数据列表 |
| | | */ |
| | | List<Map<String, Object>> selectTransferOrdersByIDs(@Param("serviceOrdID") String serviceOrdID, @Param("dispatchOrdID") String dispatchOrdID); |
| | | |
| | | List<Map<String, Object>> selectTransferOrdersByIDs(@Param("serviceOrdID") Long serviceOrdID, @Param("dispatchOrdID") Long dispatchOrdID); |
| | | |
| | | /** |
| | | * 根据服务单ID查询转运单数据 |
| | | * |
| | | * @param serviceOrdID 服务单ID |
| | | * @return 转运单数据列表 |
| | | */ |
| | | |
| | | List<Map<String, Object>> selectByServiceOrdId(@Param("serviceOrdID") Long serviceOrdID); |
| | | /** |
| | | * |
| | | * 根据调度单ID查询转运单数据 |
| | | */ |
| | | List<Map<String, Object>> selectByDispatchId(@Param("dispatchId") Long dispatchId); |
| | | /** |
| | | * 根据服务单ID查询病情信息 |
| | | * |
| | |
| | | * @param id 记录ID |
| | | * @param sendStatus 发送状态 |
| | | * @param sendResult 发送结果 |
| | | * @param sendContent 发送内容 |
| | | * @return 结果 |
| | | */ |
| | | int updateSendStatus(@Param("id") Long id, |
| | | @Param("sendStatus") String sendStatus, |
| | | @Param("sendResult") String sendResult); |
| | | @Param("sendResult") String sendResult, |
| | | @Param("sendContent") String sendContent); |
| | | |
| | | /** |
| | | * 删除通知发送记录 |
| | |
| | | * @return 是否发送成功 |
| | | */ |
| | | boolean sendSmsMessage(NotifyTask notifyTask); |
| | | |
| | | /** |
| | | * 发送企业微信消息 |
| | | * |
| | | * @param notifyTask 通知任务 |
| | | * @return 是否发送成功 |
| | | */ |
| | | boolean sendQyWechatMessage(NotifyTask notifyTask); |
| | | } |
| | |
| | | * |
| | | * @param id 记录ID |
| | | * @param result 发送结果信息 |
| | | * @param content 发送内容 |
| | | */ |
| | | void markSendSuccess(Long id, String result, String content); |
| | | |
| | | /** |
| | | * 更新发送状态为成功(向后兼容) |
| | | * |
| | | * @param id 记录ID |
| | | * @param result 发送结果信息 |
| | | */ |
| | | void markSendSuccess(Long id, String result); |
| | | |
| | | /** |
| | | * 更新发送状态为失败 |
| | | * |
| | | * @param id 记录ID |
| | | * @param errorMsg 错误信息 |
| | | * @param content 发送内容 |
| | | */ |
| | | void markSendFailed(Long id, String errorMsg, String content); |
| | | |
| | | /** |
| | | * 更新发送状态为失败(向后兼容) |
| | | * |
| | | * @param id 记录ID |
| | | * @param errorMsg 错误信息 |
| | |
| | | int deleteNotifySendLogById(Long id); |
| | | |
| | | /** |
| | | * 根据任务ID和用户ID查询发送记录 |
| | | * |
| | | * @param taskId 任务ID |
| | | * @param userId 用户ID |
| | | * @param notifyType 通知类型 |
| | | * @param channel 通知渠道 |
| | | * @return 通知发送记录 |
| | | */ |
| | | NotifySendLog selectNotifySendLog(Long taskId, Long userId, String notifyType, String channel); |
| | | /** |
| | | * 查询待重试的失败记录 |
| | | * |
| | | * @param maxRetryCount 最大重试次数 |
| | | * @return 失败记录列表 |
| | | */ |
| | | List<NotifySendLog> selectFailedNotifySendLogs(Integer maxRetryCount); |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.service; |
| | | |
| | | /** |
| | | * 企业微信AccessToken服务接口 |
| | | * |
| | | * @author ruoyi |
| | | * @date 2025-12-11 |
| | | */ |
| | | public interface IQyWechatAccessTokenService { |
| | | |
| | | /** |
| | | * 获取企业微信应用的AccessToken |
| | | * |
| | | * @param corpId 企业ID |
| | | * @param corpSecret 应用密钥 |
| | | * @return AccessToken |
| | | */ |
| | | String getAppAccessToken(String corpId, String corpSecret); |
| | | |
| | | /** |
| | | * 刷新企业微信应用的AccessToken |
| | | * |
| | | * @param corpId 企业ID |
| | | * @param corpSecret 应用密钥 |
| | | * @return 新的AccessToken |
| | | */ |
| | | String refreshAppAccessToken(String corpId, String corpSecret); |
| | | |
| | | /** |
| | | * 检查企业微信服务是否启用 |
| | | * |
| | | * @return true-启用,false-禁用 |
| | | */ |
| | | boolean isEnabled(); |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.service; |
| | | |
| | | /** |
| | | * 企业微信服务接口 |
| | | * |
| | | * @author ruoyi |
| | | * @date 2025-12-11 |
| | | */ |
| | | public interface IQyWechatService { |
| | | |
| | | /** |
| | | * 发送企业微信消息 |
| | | * |
| | | * @param userId 用户ID |
| | | * @param title 消息标题 |
| | | * @param content 消息内容 |
| | | * @return 是否发送成功 |
| | | */ |
| | | boolean sendNotifyMessage(Long userId, String title, String content, String notifyUrl); |
| | | |
| | | /** |
| | | * 发送企业微信文本消息 |
| | | * |
| | | * @param qyUserId 企业微信用户ID |
| | | * @param title 消息标题 |
| | | * @param content 消息内容 |
| | | * @param notifyUrl 通知链接 |
| | | * @return 是否发送成功 |
| | | */ |
| | | boolean sendTextMessage(String qyUserId, String title, String content, String notifyUrl); |
| | | |
| | | /** |
| | | * 获取用户的企业微信ID |
| | | * |
| | | * @param userId 系统用户ID |
| | | * @return 企业微信用户ID |
| | | */ |
| | | String getQyUserIdByUserId(Long userId); |
| | | |
| | | /** |
| | | * 检查企业微信服务是否启用 |
| | | * |
| | | * @return true=启用, false=未启用 |
| | | */ |
| | | boolean isEnabled(); |
| | | } |
| | |
| | | * @return 结果 |
| | | */ |
| | | public boolean checkConfigKeyUnique(SysConfig config); |
| | | |
| | | /** |
| | | * 更新配置值 |
| | | * |
| | | * @param configKey 参数键名 |
| | | * @param configValue 参数值 |
| | | * @return 结果 |
| | | */ |
| | | public int updateConfigValue(String configKey, String configValue); |
| | | } |
| | |
| | | |
| | | void updateEmergencyInfoFromUpdateVO(SysTaskEmergency oldEmergency, TaskUpdateVO updateVO, String userName); |
| | | |
| | | SysTaskEmergency selectSysTaskEmergencyByTaskId(Long taskId); |
| | | /** |
| | | * 从 TaskCreateVO 更新急救转运任务扩展信息(用于旧系统同步) |
| | | * |
| | |
| | | * @date 2024-01-15 |
| | | */ |
| | | public interface ISysTaskService { |
| | | |
| | | |
| | | public Boolean dispatchSyncEvent(Long taskId); |
| | | /** |
| | | * 查询任务管理 |
| | | * |
| | |
| | | public List<SysTask> selectSysTaskList(TaskQueryVO queryVO); |
| | | |
| | | /** |
| | | * 根据任务编号、调度单编号或服务单编号查询任务列表 |
| | | * |
| | | * @param queryVO 任务查询对象 |
| | | * @param taskCode 任务编号 |
| | | * @return 任务管理集合 |
| | | */ |
| | | public List<SysTask> selectSysTaskListByMultiCode(TaskQueryVO queryVO, String taskCode); |
| | | |
| | | /** |
| | | * 新增任务管理 |
| | | * |
| | | * @param createVO 任务创建对象 |
| | |
| | | import javax.net.ssl.TrustManager; |
| | | import javax.net.ssl.X509TrustManager; |
| | | import java.security.cert.X509Certificate; |
| | | |
| | | import com.ruoyi.common.utils.MapValueUtils; |
| | | import com.ruoyi.system.domain.*; |
| | | import com.ruoyi.system.event.TaskDispatchSyncEvent; |
| | | import com.ruoyi.system.event.TaskServiceOrderSyncEvent; |
| | | import com.ruoyi.system.mapper.*; |
| | | import com.ruoyi.system.service.*; |
| | | import com.ruoyi.system.task.ITaskAttachmentService; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.ApplicationEventPublisher; |
| | | import org.springframework.context.event.EventListener; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import com.ruoyi.common.config.LegacySystemConfig; |
| | | import com.ruoyi.common.utils.MapValueUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.core.domain.entity.SysUser; |
| | | import com.ruoyi.common.core.domain.entity.SysDept; |
| | | import com.ruoyi.system.domain.vo.TaskCreateVO; |
| | | import com.ruoyi.system.mapper.SysTaskMapper; |
| | | import com.ruoyi.system.mapper.SysTaskEmergencyMapper; |
| | | import com.ruoyi.system.mapper.SysTaskVehicleMapper; |
| | | import com.ruoyi.system.mapper.SysTaskAssigneeMapper; |
| | | import com.ruoyi.system.mapper.VehicleInfoMapper; |
| | | import com.ruoyi.system.mapper.SysUserMapper; |
| | | import com.ruoyi.system.mapper.SysDeptMapper; |
| | | import com.ruoyi.system.utils.TaskStatusConverter; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | /** |
| | | * 旧系统同步Service业务层处理 |
| | |
| | | private ITaskAttachmentService taskAttachmentService; |
| | | |
| | | |
| | | @Autowired |
| | | private ApplicationEventPublisher eventPublisher; |
| | | |
| | | @Autowired |
| | | private LegacyTransferSyncMapper legacyTransferSyncMapper; |
| | | |
| | | |
| | | public Map<String,Object> getLegacyDispatchByDispatchId(Long dispatchId) { |
| | | List<Map<String, Object>> result = legacyTransferSyncMapper.selectByDispatchId(dispatchId); |
| | | if(!CollectionUtils.isEmpty(result)){ |
| | | return result.get(0); |
| | | }else{ |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | |
| | | private Map<String,Object> getLegacyByServiceOrdId(Long serviceOrdId) { |
| | | List<Map<String, Object>> result = legacyTransferSyncMapper.selectByServiceOrdId(serviceOrdId); |
| | | if(!CollectionUtils.isEmpty(result)){ |
| | | return result.get(0); |
| | | }else{ |
| | | return null; |
| | | } |
| | | } |
| | | /** |
| | | * 同步急救转运任务到旧系统 |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | public Long syncEmergencyTaskToLegacy(Long taskId) { |
| | | if (!legacyConfig.isEnabled()) { |
| | | log.info("旧系统同步已禁用,跳过任务ID: {}", taskId); |
| | |
| | | emergency.setSyncStatus(2); // 同步成功 |
| | | emergency.setSyncTime(new Date()); |
| | | emergency.setSyncErrorMsg(null); |
| | | Map<String, Object> legacy = getLegacyByServiceOrdId(serviceOrdId); |
| | | String serviceOrdNo = MapValueUtils.getStringValue(legacy, "ServiceOrdNo"); |
| | | if(serviceOrdNo!=null) { |
| | | emergency.setLegacyServiceOrdNo(serviceOrdNo); |
| | | } |
| | | String serviceOrdClass = MapValueUtils.getStringValue(legacy, "ServiceOrdClass"); |
| | | if(serviceOrdClass!=null) { |
| | | emergency.setLegacyServiceOrdClass(serviceOrdClass); |
| | | } |
| | | Date serviceCCTime = MapValueUtils.getDateValue(legacy, "ServiceOrd_CC_Time"); |
| | | if(serviceCCTime!=null) { |
| | | emergency.setLegacyServiceNsTime(serviceCCTime); |
| | | } |
| | | sysTaskEmergencyService.updateSysTaskEmergency(emergency); |
| | | |
| | | // 更新任务主表同步标记 |
| | | task.setLegacySynced(1); |
| | | sysTaskMapper.updateSysTask(task); |
| | | |
| | | |
| | | eventPublisher.publishEvent(new TaskServiceOrderSyncEvent(this, taskId, task.getTaskCode(), serviceOrdId)); |
| | | log.info("任务同步成功,任务ID: {}, ServiceOrdID: {}", taskId, serviceOrdId); |
| | | return serviceOrdId; |
| | | } else { |
| | |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | |
| | | //在这里监听派发的事件 |
| | | @EventListener |
| | | public void handleTaskServiceOrderSyncEvent(TaskServiceOrderSyncEvent event) { |
| | | log.info("收到任务服务单同步事件,任务ID:{},任务编号:{},服务单ID:{}", event.getTaskId(), event.getTaskCode(), event.getServiceOrderId()); |
| | | syncDispatchOrderToLegacy(event.getTaskId()); |
| | | } |
| | | /** |
| | | * 批量同步未同步的急救转运任务 |
| | | * 使用分页查询,确保所有符合条件的任务都能被同步 |
| | |
| | | * 同步调度单到旧系统(admin_save_24.asp) |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | public Long syncDispatchOrderToLegacy(Long taskId) { |
| | | if (!legacyConfig.isEnabled()) { |
| | | log.info("旧系统同步已禁用,跳过调度单同步,任务ID: {}", taskId); |
| | |
| | | emergency.setDispatchSyncStatus(2); // 同步成功 |
| | | emergency.setDispatchSyncTime(new Date()); |
| | | emergency.setDispatchSyncErrorMsg(null); |
| | | //更新调度单信息开到新系统 |
| | | Map<String,Object> dispatchInfo = this.getLegacyDispatchByDispatchId(dispatchOrdId); |
| | | if (dispatchInfo != null) { |
| | | emergency.setLegacyDispatchNsTime(MapValueUtils.getDateValue(dispatchInfo, "DispatchOrd_NS_Time")); // 同步成功 |
| | | emergency.setLegacyDispatchOrdClass(MapValueUtils.getStringValue(dispatchInfo, "DispatchOrdClass")); // 同步成功 |
| | | emergency.setLegacyDispatchOrdNo(MapValueUtils.getStringValue(dispatchInfo, "DispatchOrdNo")); // 同步成功 |
| | | emergency.setLegacyServiceNsTime(MapValueUtils.getDateValue(dispatchInfo, "ServiceOrd_CC_Time")); // 同步成功 |
| | | emergency.setLegacyServiceOrdClass(MapValueUtils.getStringValue(dispatchInfo, "ServiceOrdClass")); // 同步成功 |
| | | } |
| | | sysTaskEmergencyService.updateSysTaskEmergency(emergency); |
| | | |
| | | List<SysTaskAttachment> taskAttachments= sysTaskService.getAttachmentsByTaskId(taskId); |
| | | if (taskAttachments != null && !taskAttachments.isEmpty()) { |
| | | //同步附件 |
| | | this.syncAttachmentToLegacy(taskAttachments,serviceOrdId,dispatchOrdId,oaUserID); |
| | | } |
| | | eventPublisher.publishEvent(new TaskDispatchSyncEvent(this, taskId, task.getTaskCode(),serviceOrdId, dispatchOrdId, oaUserID)); |
| | | |
| | | log.info("调度单同步成功,任务ID: {}, DispatchOrdID: {}", taskId, dispatchOrdId); |
| | | return dispatchOrdId; |
| | |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | |
| | | @EventListener |
| | | public void handleTaskDispatchSyncEvent(TaskDispatchSyncEvent event) { |
| | | Long taskId = event.getTaskId(); |
| | | Long dispatchOrdId = event.getDispatchOrderId(); |
| | | Long serviceOrdId = event.getServiceOrderId(); |
| | | Integer oaUserID = event.getOaUserId(); |
| | | List<SysTaskAttachment> taskAttachments= sysTaskService.getAttachmentsByTaskId(taskId); |
| | | if (taskAttachments != null && !taskAttachments.isEmpty()) { |
| | | //同步附件 |
| | | this.syncAttachmentToLegacy(taskAttachments,serviceOrdId,dispatchOrdId,oaUserID); |
| | | } |
| | | } |
| | | /** |
| | | * 批量同步未同步的调度单 |
| | | * 使用分页查询,确保所有符合条件的任务都能被同步 |
| | |
| | | while (true) { |
| | | // 分页查询已同步服务单但未同步调度单的任务 |
| | | List<SysTaskEmergency> pendingTasks = sysTaskEmergencyService.selectPendingDispatchSyncTasks(offset, pageSize); |
| | | log.info("查询到未同步调度单的任务数量: {}", pendingTasks.size()); |
| | | // log.info("查询到未同步调度单的任务数量: {}", pendingTasks.size()); |
| | | if (pendingTasks == null || pendingTasks.isEmpty()) { |
| | | log.info("没有更多需要同步调度单的任务,offset: {}", offset); |
| | | break; // 没有更多数据,退出循环 |
| | | } |
| | | |
| | | log.info("开始同步调度单第 {} 页,任务数量: {}", (offset / pageSize) + 1, pendingTasks.size()); |
| | | // log.info("开始同步调度单第 {} 页,任务数量: {}", (offset / pageSize) + 1, pendingTasks.size()); |
| | | |
| | | int pageSuccessCount = 0; |
| | | for (SysTaskEmergency emergency : pendingTasks) { |
| | | log.info("开始同步调度单,任务ID: {}", emergency.getTaskId()); |
| | | // log.info("开始同步调度单,任务ID: {}", emergency.getTaskId()); |
| | | Long dispatchOrdId = syncDispatchOrderToLegacy(emergency.getTaskId()); |
| | | |
| | | if (dispatchOrdId != null && dispatchOrdId > 0) { |
| | |
| | | } |
| | | } |
| | | |
| | | // 删除下面的重复方法,因为我们将使用MapValueUtils工具类中的方法 |
| | | /* |
| | | private String getStringValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | return value != null ? value.toString() : null; |
| | | } |
| | | |
| | | private BigDecimal getBigDecimalValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | if (value instanceof BigDecimal) { |
| | | return (BigDecimal) value; |
| | | } |
| | | try { |
| | | return new BigDecimal(value.toString()); |
| | | } catch (NumberFormatException e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private Long getLongValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | if (value instanceof Long) { |
| | | return (Long) value; |
| | | } |
| | | try { |
| | | return Long.valueOf(value.toString()); |
| | | } catch (NumberFormatException e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private Integer getIntegerValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | if (value instanceof Integer) { |
| | | return (Integer) value; |
| | | } |
| | | try { |
| | | return Integer.valueOf(value.toString()); |
| | | } catch (NumberFormatException e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private Date getDateValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | if (value instanceof Date) { |
| | | return (Date) value; |
| | | } |
| | | // 如果是字符串,尝试解析 |
| | | if (value instanceof String) { |
| | | try { |
| | | return DateUtils.parseDate(value.toString()); |
| | | } catch (Exception e) { |
| | | return null; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private boolean isValidDateFormat(String dateStr, String format) { |
| | | if (StringUtils.isEmpty(dateStr)) { |
| | | return false; |
| | | } |
| | | |
| | | try { |
| | | SimpleDateFormat sdf = new SimpleDateFormat(format); |
| | | sdf.setLenient(false); |
| | | sdf.parse(dateStr); |
| | | return true; |
| | | } catch (Exception e) { |
| | | return false; |
| | | } |
| | | } |
| | | */ |
| | | |
| | | /** |
| | | * 重新同步车辆和人员变更的任务到旧系统 |
| | | * 当任务的车辆信息或人员信息发生变更时,需要调用旧系统接口重新同步 |
| | |
| | | import com.ruoyi.common.core.domain.entity.SysDept; |
| | | import com.ruoyi.common.core.domain.entity.SysUser; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | import com.ruoyi.common.utils.MapValueUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.system.domain.SysTaskEmergency; |
| | | import com.ruoyi.system.domain.VehicleInfo; |
| | |
| | | for (Map<String, Object> order : transferOrders) { |
| | | processedCount++; |
| | | try { |
| | | String serviceOrdID = getStringValue(order, "ServiceOrdID"); |
| | | String dispatchOrdID = getStringValue(order, "DispatchOrdID"); |
| | | String serviceOrdID = MapValueUtils.getStringValue(order, "ServiceOrdID"); |
| | | String dispatchOrdID = MapValueUtils.getStringValue(order, "DispatchOrdID"); |
| | | |
| | | // 检查参数有效性 |
| | | if (StringUtils.isEmpty(serviceOrdID)) { |
| | |
| | | break; |
| | | } catch (Exception e) { |
| | | log.error("同步单个转运单失败: ServiceOrdID={}, DispatchOrdID={}", |
| | | getStringValue(order, "ServiceOrdID"), |
| | | getStringValue(order, "DispatchOrdID"), e); |
| | | MapValueUtils.getStringValue(order, "ServiceOrdID"), |
| | | MapValueUtils.getStringValue(order, "DispatchOrdID"), e); |
| | | } |
| | | } |
| | | |
| | |
| | | return false; |
| | | } |
| | | // 直接查询指定的转运单信息 |
| | | List<Map<String, Object>> transferOrders = legacyTransferSyncMapper.selectTransferOrdersByIDs(serviceOrdID, dispatchOrdID); |
| | | Long serviceOrdIdLong = null; |
| | | Long dispatchOrdIdLong = null; |
| | | |
| | | try { |
| | | serviceOrdIdLong = Long.valueOf(serviceOrdID); |
| | | } catch (NumberFormatException e) { |
| | | log.error("服务单ID不是有效数字: {}", serviceOrdID); |
| | | return false; |
| | | } |
| | | |
| | | if (StringUtils.isNotEmpty(dispatchOrdID)) { |
| | | try { |
| | | dispatchOrdIdLong = Long.valueOf(dispatchOrdID); |
| | | } catch (NumberFormatException e) { |
| | | log.warn("调度单ID不是有效数字: {}", dispatchOrdID); |
| | | } |
| | | } |
| | | |
| | | List<Map<String, Object>> transferOrders = legacyTransferSyncMapper.selectTransferOrdersByIDs(serviceOrdIdLong, dispatchOrdIdLong); |
| | | |
| | | Map<String, Object> order = transferOrders.get(0); |
| | | |
| | |
| | | } |
| | | sysTaskCode = createTaskVo.getTaskCode(); |
| | | // 记录创建的任务信息 |
| | | log.debug("准备创建任务: ServiceOrdID={}, DispatchOrdID={}, 患者姓名={}, 转出医院={}, 转入医院={}", |
| | | serviceOrdID, dispatchOrdID, |
| | | createTaskVo.getPatient() != null ? createTaskVo.getPatient().getName() : "未知", |
| | | createTaskVo.getHospitalOut() != null ? createTaskVo.getHospitalOut().getName() : "未知", |
| | | createTaskVo.getHospitalIn() != null ? createTaskVo.getHospitalIn().getName() : "未知"); |
| | | // log.debug("准备创建任务: ServiceOrdID={}, DispatchOrdID={}, 患者姓名={}, 转出医院={}, 转入医院={}", |
| | | // serviceOrdID, dispatchOrdID, |
| | | // createTaskVo.getPatient() != null ? createTaskVo.getPatient().getName() : "未知", |
| | | // createTaskVo.getHospitalOut() != null ? createTaskVo.getHospitalOut().getName() : "未知", |
| | | // createTaskVo.getHospitalIn() != null ? createTaskVo.getHospitalIn().getName() : "未知"); |
| | | /** |
| | | * 开单时间 |
| | | */ |
| | | Date ServiceOrd_CC_Time= getDateValue(order, "ServiceOrd_CC_Time"); |
| | | Date ServiceOrd_CC_Time= MapValueUtils.getDateValue(order, "ServiceOrd_CC_Time"); |
| | | // 调用sysTaskService创建任务 |
| | | String serviceOrdClass = getStringValue(order,"ServiceOrdClass"); |
| | | String serviceOrdNo = getStringValue(order,"ServiceOrdNo"); |
| | | String serviceOrdClass = MapValueUtils.getStringValue(order,"ServiceOrdClass"); |
| | | String serviceOrdNo = MapValueUtils.getStringValue(order,"ServiceOrdNo"); |
| | | |
| | | Integer oauserId=getIntegerValue(order,"ServiceOrd_CC_ID"); |
| | | Integer oauserId=MapValueUtils.getIntegerValue(order,"ServiceOrd_CC_ID"); |
| | | if(oauserId==null){ |
| | | oauserId=getIntegerValue(order,"ServiceOrd_NS_ID"); |
| | | oauserId=MapValueUtils.getIntegerValue(order,"ServiceOrd_NS_ID"); |
| | | } |
| | | if(oauserId==null || oauserId==0){ |
| | | log.error("创建任务时,获取创建人信息失败,serviceOrdID={}, DispatchOrdID={} ServiceOrd_NS_ID={},ServiceOrd_CC_ID={}", serviceOrdID, dispatchOrdID, getIntegerValue(order,"ServiceOrd_NS_ID"),getIntegerValue(order,"ServiceOrd_CC_ID")); |
| | | if(oauserId==null || oauserId==0) { |
| | | log.error("创建任务时,获取创建人信息失败,serviceOrdID={}, DispatchOrdID={} ServiceOrd_NS_ID={},ServiceOrd_CC_ID={}", serviceOrdID, dispatchOrdID, MapValueUtils.getIntegerValue(order, "ServiceOrd_NS_ID"), MapValueUtils.getIntegerValue(order, "ServiceOrd_CC_ID")); |
| | | return false; |
| | | } |
| | | SysUser sysUser=sysUserService.selectUserByOaUserId(oauserId); |
| | |
| | | try { |
| | | // 构造TaskCreateVO对象 |
| | | TaskCreateVO createTaskVo = buildCreateTaskVo(serviceOrdID, dispatchOrdID, order); |
| | | sysTaskCode = createTaskVo.getTaskCode(); |
| | | |
| | | if (createTaskVo == null) { |
| | | log.error("构造TaskCreateVO失败: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID); |
| | | return false; |
| | | } |
| | | |
| | | sysTaskCode = createTaskVo.getTaskCode(); |
| | | // 记录创建的任务信息 |
| | | log.debug("准备创建任务: ServiceOrdID={}, DispatchOrdID={}, 患者姓名={}, 转出医院={}, 转入医院={}", |
| | | serviceOrdID, dispatchOrdID, |
| | | createTaskVo.getPatient() != null ? createTaskVo.getPatient().getName() : "未知", |
| | | createTaskVo.getHospitalOut() != null ? createTaskVo.getHospitalOut().getName() : "未知", |
| | | createTaskVo.getHospitalIn() != null ? createTaskVo.getHospitalIn().getName() : "未知"); |
| | | // log.debug("准备创建任务: ServiceOrdID={}, DispatchOrdID={}, 患者姓名={}, 转出医院={}, 转入医院={}", |
| | | // serviceOrdID, dispatchOrdID, |
| | | // createTaskVo.getPatient() != null ? createTaskVo.getPatient().getName() : "未知", |
| | | // createTaskVo.getHospitalOut() != null ? createTaskVo.getHospitalOut().getName() : "未知", |
| | | // createTaskVo.getHospitalIn() != null ? createTaskVo.getHospitalIn().getName() : "未知"); |
| | | /** |
| | | * 开单时间 |
| | | */ |
| | | Date ServiceOrd_CC_Time= getDateValue(order, "ServiceOrd_CC_Time"); |
| | | Date ServiceOrd_CC_Time= MapValueUtils.getDateValue(order, "ServiceOrd_CC_Time"); |
| | | // 调用sysTaskService创建任务 |
| | | String serviceOrdClass = getStringValue(order,"ServiceOrdClass"); |
| | | String serviceOrdNo = getStringValue(order,"ServiceOrdNo"); |
| | | String serviceOrdClass = MapValueUtils.getStringValue(order,"ServiceOrdClass"); |
| | | String serviceOrdNo = MapValueUtils.getStringValue(order,"ServiceOrdNo"); |
| | | |
| | | /** |
| | | * 创建人ID |
| | | */ |
| | | Integer oauserId=getIntegerValue(order,"ServiceOrd_CC_ID"); |
| | | Integer oauserId=MapValueUtils.getIntegerValue(order,"ServiceOrd_CC_ID"); |
| | | if(oauserId==null || oauserId==0) { |
| | | oauserId=getIntegerValue(order,"ServiceOrd_NS_ID"); |
| | | oauserId=MapValueUtils.getIntegerValue(order,"ServiceOrd_NS_ID"); |
| | | } |
| | | SysUser sysUser=sysUserService.selectUserByOaUserId(oauserId); |
| | | if(sysUser==null){ |
| | | log.error("创建任务时,获取创建人信息失败,serviceOrdID={}, DispatchOrdID={} ServiceOrd_CC_ID:{},ServiceOrd_NS_ID:{}", serviceOrdID, dispatchOrdID, getIntegerValue(order,"ServiceOrd_CC_ID"),getIntegerValue(order,"ServiceOrd_NS_ID")); |
| | | if(sysUser==null) { |
| | | log.error("创建任务时,获取创建人信息失败,serviceOrdID={}, DispatchOrdID={} ServiceOrd_CC_ID:{},ServiceOrd_NS_ID:{}", serviceOrdID, dispatchOrdID, MapValueUtils.getIntegerValue(order, "ServiceOrd_CC_ID"), MapValueUtils.getIntegerValue(order, "ServiceOrd_NS_ID")); |
| | | return false; |
| | | } |
| | | |
| | | Long taskCreatorId= sysUser.getUserId(); |
| | | String createUserName= sysUser.getUserName(); |
| | | SysDept dept=sysDeptService.selectDeptByServiceClass(serviceOrdClass); |
| | |
| | | String ServiceOrdNo_Str=String.format("%03d", intServiceNo); |
| | | return serviceOrdClass+ServiceOrd_CC_Time_Str+"-"+ServiceOrdNo_Str; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 构造TaskCreateVO对象用于创建任务 |
| | | * |
| | |
| | | log.error("服务单ID不能为空"); |
| | | return null; |
| | | } |
| | | String serviceOrdClass = getStringValue(order, "ServiceOrdClass"); |
| | | String serviceOrdClass = MapValueUtils.getStringValue(order, "ServiceOrdClass"); |
| | | |
| | | TaskCreateVO createTaskVo = new TaskCreateVO(); |
| | | String serviceOrdCode=this.getServiceOrdCode(getDateValue(order, "ServiceOrd_CC_Time"),serviceOrdClass,getStringValue(order, "ServiceOrdNo")); |
| | | String serviceOrdCode=this.getServiceOrdCode(MapValueUtils.getDateValue(order, "ServiceOrd_CC_Time"),serviceOrdClass,MapValueUtils.getStringValue(order, "ServiceOrdNo")); |
| | | createTaskVo.setTaskCode(serviceOrdCode); |
| | | // log.info("构造TaskCreateVO: ServiceOrdID={}, DispatchOrdID={},taskCode:{}", serviceOrdID, dispatchOrdID,serviceOrdCode); |
| | | // 设置基本信息 |
| | |
| | | createTaskVo.setDocumentTypeId(serviceOrdClass); |
| | | } |
| | | |
| | | String serviceOrdType = getStringValue(order, "ServiceOrdType"); |
| | | String serviceOrdType = MapValueUtils.getStringValue(order, "ServiceOrdType"); |
| | | if (StringUtils.isNotEmpty(serviceOrdType)) { |
| | | createTaskVo.setTaskTypeId(serviceOrdType); |
| | | } |
| | | |
| | | // 设置区域类型 |
| | | String serviceOrdAreaType = getStringValue(order, "ServiceOrdAreaType"); |
| | | String serviceOrdAreaType = MapValueUtils.getStringValue(order, "ServiceOrdAreaType"); |
| | | |
| | | // 设置用户ID |
| | | Long serviceOrdUserID = getLongValue(order, "ServiceOrdUserID"); |
| | | Long serviceOrdUserID = MapValueUtils.getLongValue(order, "ServiceOrdUserID"); |
| | | |
| | | // 设置患者信息 |
| | | TaskCreateVO.PatientInfo patientInfo = new TaskCreateVO.PatientInfo(); |
| | | patientInfo.setName(getStringValue(order, "ServiceOrdPtName")); |
| | | patientInfo.setPhone(getStringValue(order, "ServiceOrdCoPhone")); |
| | | patientInfo.setIdCard(getStringValue(order, "ServiceOrdPtIDCard")); |
| | | patientInfo.setCondition(getStringValue(order, "ServiceOrdPtCondition")); |
| | | patientInfo.setContact(getStringValue(order, "ServiceOrdCoName")); |
| | | patientInfo.setName(MapValueUtils.getStringValue(order, "ServiceOrdPtName")); |
| | | patientInfo.setPhone(MapValueUtils.getStringValue(order, "ServiceOrdCoPhone")); |
| | | patientInfo.setIdCard(MapValueUtils.getStringValue(order, "ServiceOrdPtIDCard")); |
| | | patientInfo.setCondition(MapValueUtils.getStringValue(order, "ServiceOrdPtCondition")); |
| | | patientInfo.setContact(MapValueUtils.getStringValue(order, "ServiceOrdCoName")); |
| | | |
| | | String serviceOrdPtSex = getStringValue(order, "ServiceOrdPtSex"); |
| | | String serviceOrdPtSex = MapValueUtils.getStringValue(order, "ServiceOrdPtSex"); |
| | | if(serviceOrdPtSex!=null){ |
| | | if(serviceOrdPtSex.equals("男")){ |
| | | patientInfo.setGender("male"); |
| | |
| | | } |
| | | createTaskVo.setPatient(patientInfo); |
| | | //1000公里,提取数字 |
| | | String ServiceOrdTraDistance=getStringValue(order, "ServiceOrdTraDistance"); |
| | | String ServiceOrdTraDistance=MapValueUtils.getStringValue(order, "ServiceOrdTraDistance"); |
| | | if(ServiceOrdTraDistance!=null){ |
| | | ServiceOrdTraDistance=ServiceOrdTraDistance.replaceAll("[^0-9]", ""); |
| | | createTaskVo.setDistance(new BigDecimal(ServiceOrdTraDistance)); |
| | |
| | | // 设置转出医院信息 |
| | | |
| | | TaskCreateVO.HospitalInfo hospitalOutInfo = new TaskCreateVO.HospitalInfo(); |
| | | Long hospitalOutId = getLongValue(order, "ServiceOrdPtOutHospID"); |
| | | Long hospitalOutId = MapValueUtils.getLongValue(order, "ServiceOrdPtOutHospID"); |
| | | hospitalOutInfo.setId(hospitalOutId); |
| | | if (hospitalOutId != null) { |
| | | String hospitalOutName = legacyTransferSyncMapper.selectHospitalNameByHospID(hospitalOutId.toString()); |
| | |
| | | hospitalOutInfo.setName(hospitalOutName); |
| | | } |
| | | } |
| | | String ServiceOrdTraVia=getStringValue(order, "ServiceOrdTraVia"); |
| | | String ServiceOrdTraVia=MapValueUtils.getStringValue(order, "ServiceOrdTraVia"); |
| | | if(ServiceOrdTraVia!=null){ |
| | | hospitalOutInfo.setAddress(ServiceOrdTraVia); |
| | | } |
| | | |
| | | |
| | | String hospitalOutDeptId = getStringValue(order, "ServiceOrdPtServicesID"); |
| | | String hospitalOutDeptId = MapValueUtils.getStringValue(order, "ServiceOrdPtServicesID"); |
| | | hospitalOutInfo.setDepartmentId(hospitalOutDeptId); |
| | | if (StringUtils.isNotEmpty(hospitalOutDeptId)) { |
| | | String hospitalOutDeptName = legacyTransferSyncMapper.selectDepartmentNameByDeptID(hospitalOutDeptId); |
| | |
| | | } |
| | | } |
| | | //转出床位 |
| | | String serviceOrdPtServices=getStringValue(order, "ServiceOrdPtServices"); |
| | | String serviceOrdPtServices=MapValueUtils.getStringValue(order, "ServiceOrdPtServices"); |
| | | if(serviceOrdPtServices!= null){ |
| | | hospitalOutInfo.setBedNumber(serviceOrdPtServices); |
| | | } |
| | |
| | | |
| | | // 设置转入医院信息 |
| | | TaskCreateVO.HospitalInfo hospitalInInfo = new TaskCreateVO.HospitalInfo(); |
| | | Long hospitalInId = getLongValue(order, "ServiceOrdPtInHospID"); |
| | | Long hospitalInId = MapValueUtils.getLongValue(order, "ServiceOrdPtInHospID"); |
| | | hospitalInInfo.setId(hospitalInId); |
| | | if (hospitalInId != null) { |
| | | String hospitalInName = legacyTransferSyncMapper.selectHospitalNameByHospID(hospitalInId.toString()); |
| | |
| | | hospitalInInfo.setName(hospitalInName); |
| | | } |
| | | } |
| | | String serviceOrdTraEnd = getStringValue(order, "ServiceOrdTraEnd"); |
| | | String serviceOrdTraEnd = MapValueUtils.getStringValue(order, "ServiceOrdTraEnd"); |
| | | if(serviceOrdTraEnd!= null){ |
| | | hospitalInInfo.setAddress(serviceOrdTraEnd); |
| | | } |
| | | //转入床位 |
| | | String serviceOrdPtInServices =getStringValue(order, "ServiceOrdPtInServices"); |
| | | String serviceOrdPtInServices =MapValueUtils.getStringValue(order, "ServiceOrdPtInServices"); |
| | | if(serviceOrdPtInServices!= null){ |
| | | hospitalInInfo.setBedNumber(serviceOrdPtInServices); |
| | | } |
| | | |
| | | |
| | | String hospitalInDeptId = getStringValue(order, "ServiceOrdPtInServicesID"); |
| | | String hospitalInDeptId = MapValueUtils.getStringValue(order, "ServiceOrdPtInServicesID"); |
| | | hospitalInInfo.setDepartmentId(hospitalInDeptId); |
| | | if (StringUtils.isNotEmpty(hospitalInDeptId)) { |
| | | String hospitalInDeptName = legacyTransferSyncMapper.selectDepartmentNameByDeptID(hospitalInDeptId); |
| | |
| | | createTaskVo.setHospitalIn(hospitalInInfo); |
| | | |
| | | // 设置地址信息 |
| | | createTaskVo.setDepartureAddress(getStringValue(order, "ServiceOrdTraStreet")); |
| | | createTaskVo.setDestinationAddress(getStringValue(order, "ServiceOrdTraEnd")); |
| | | createTaskVo.setDepartureAddress(MapValueUtils.getStringValue(order, "ServiceOrdTraStreet")); |
| | | createTaskVo.setDestinationAddress(MapValueUtils.getStringValue(order, "ServiceOrdTraEnd")); |
| | | |
| | | // 设置价格和距离信息 |
| | | createTaskVo.setPrice(getBigDecimalValue(order, "ServiceOrdTraTxnPrice")); |
| | | createTaskVo.setPrice(MapValueUtils.getBigDecimalValue(order, "ServiceOrdTraTxnPrice")); |
| | | // 距离信息需要从其他字段计算或获取 |
| | | |
| | | if(dispatchOrdID!=null) { |
| | |
| | | } |
| | | // 设置车辆信息 |
| | | // 车辆ID需要根据DispatchOrdCarID查询获取 |
| | | String carID = getStringValue(order, "DispatchOrdCarID"); |
| | | String carID = MapValueUtils.getStringValue(order, "DispatchOrdCarID"); |
| | | if (StringUtils.isNotEmpty(carID)) { |
| | | String carLicense = legacyTransferSyncMapper.selectCarLicenseByCarID(carID); |
| | | if (StringUtils.isNotEmpty(carLicense)) { |
| | |
| | | |
| | | // 设置备注信息 |
| | | String remark = "服务单ID: " + serviceOrdID + ", 调度单ID: " + dispatchOrdID; |
| | | String serviceOrdCoTies = getStringValue(order, "ServiceOrdCoTies"); |
| | | String serviceOrdCoTies = MapValueUtils.getStringValue(order, "ServiceOrdCoTies"); |
| | | if (StringUtils.isNotEmpty(serviceOrdCoTies)) { |
| | | remark += ", 联系人关系: " + serviceOrdCoTies; |
| | | } |
| | | createTaskVo.setRemark(remark); |
| | | |
| | | // 设置计划开始时间 |
| | | Date plannedStartTime = getDateValue(order, "ServiceOrdApptDate"); |
| | | Date plannedStartTime = MapValueUtils.getDateValue(order, "ServiceOrdApptDate"); |
| | | if (plannedStartTime != null) { |
| | | createTaskVo.setPlannedStartTime(plannedStartTime); |
| | | } |
| | | |
| | | Date actualStartTime = getDateValue(order, "DispatchOrdActualDate"); |
| | | Date actualStartTime = MapValueUtils.getDateValue(order, "DispatchOrdActualDate"); |
| | | if (actualStartTime != null) { |
| | | createTaskVo.setActualStartTime(actualStartTime); |
| | | } |
| | | |
| | | Date actualEndTime = getDateValue(order, "DispatchOrdReturnDate"); |
| | | Date actualEndTime = MapValueUtils.getDateValue(order, "DispatchOrdReturnDate"); |
| | | if (actualEndTime != null) { |
| | | createTaskVo.setActualEndTime(actualEndTime); |
| | | } |
| | |
| | | |
| | | |
| | | // 设置创建时间 开单日期 |
| | | Date createTime = getDateValue(order, "ServiceOrd_CC_Time"); |
| | | Date createTime = MapValueUtils.getDateValue(order, "ServiceOrd_CC_Time"); |
| | | if (createTime != null) { |
| | | createTaskVo.setCreateTime(createTime); |
| | | } |
| | |
| | | createTaskVo.setDiseaseIds(diseaseIds); |
| | | } |
| | | |
| | | Integer dispatchOrdStatus = getIntegerValue(order, "DispatchOrdStatus"); |
| | | Integer dispatchOrdStatus = MapValueUtils.getIntegerValue(order, "DispatchOrdStatus"); |
| | | TaskStatus status= TaskStatusConverter.convertFromLegacyStatus(dispatchOrdStatus); |
| | | if(status!=null) { |
| | | createTaskVo.setTaskStatus(status.getCode()); |
| | | } |
| | | |
| | | |
| | | // log.info("TaskCreateVO构造完成: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID); |
| | | // 设置旧系统同步字段 |
| | | String dispatchOrdNo = MapValueUtils.getStringValue(order, "DispatchOrdNo"); |
| | | if(dispatchOrdNo!=null) { |
| | | createTaskVo.setLegacyDispatchOrdNo(dispatchOrdNo); |
| | | } |
| | | Date ccTime=MapValueUtils.getDateValue(order, "ServiceOrd_CC_Time"); |
| | | |
| | | if(ccTime!=null) { |
| | | createTaskVo.setLegacyServiceNsTime(ccTime); |
| | | } |
| | | Date nsTime=MapValueUtils.getDateValue(order, "DispatchOrd_NS_Time"); |
| | | if(nsTime!=null) { |
| | | createTaskVo.setLegacyDispatchNsTime(MapValueUtils.getDateValue(order, "DispatchOrd_NS_Time")); |
| | | } |
| | | String dispatchOrdClass=MapValueUtils.getStringValue(order, "DispatchOrdClass"); |
| | | if(dispatchOrdClass!=null) { |
| | | createTaskVo.setLegacyDispatchOrdClass(dispatchOrdClass); |
| | | } |
| | | |
| | | // String serviceOrdClass=MapValueUtils.getStringValue(order, "ServiceOrdClass"); |
| | | if(serviceOrdClass!=null) { |
| | | createTaskVo.setLegacyServiceOrdClass(serviceOrdClass); |
| | | } |
| | | |
| | | return createTaskVo; |
| | | |
| | | } catch (Exception e) { |
| | |
| | | List<TaskCreateVO.AssigneeInfo> assignees = new ArrayList<>(); |
| | | if (assigneeList != null && !assigneeList.isEmpty()) { |
| | | for (Map<String, Object> assigneeMap : assigneeList) { |
| | | String entourageOAId = getStringValue(assigneeMap, "EntourageOAId"); |
| | | String entourageState = getStringValue(assigneeMap, "EntourageID"); |
| | | String entourageOAId = MapValueUtils.getStringValue(assigneeMap, "EntourageOAId"); |
| | | String entourageState = MapValueUtils.getStringValue(assigneeMap, "EntourageID"); |
| | | |
| | | if (StringUtils.isNotEmpty(entourageOAId)) { |
| | | try { |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 从Map中获取字符串值 |
| | | * |
| | | * @param map Map对象 |
| | | * @param key 键 |
| | | * @return 字符串值 |
| | | */ |
| | | private String getStringValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | return value != null ? value.toString() : null; |
| | | } |
| | | |
| | | /** |
| | | * 从Map中获取BigDecimal值 |
| | | * |
| | | * @param map Map对象 |
| | | * @param key 键 |
| | | * @return BigDecimal值 |
| | | */ |
| | | private BigDecimal getBigDecimalValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | if (value instanceof BigDecimal) { |
| | | return (BigDecimal) value; |
| | | } |
| | | try { |
| | | return new BigDecimal(value.toString()); |
| | | } catch (NumberFormatException e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 从Map中获取Long值 |
| | | * |
| | | * @param map Map对象 |
| | | * @param key 键 |
| | | * @return Long值 |
| | | */ |
| | | private Long getLongValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | if (value instanceof Long) { |
| | | return (Long) value; |
| | | } |
| | | try { |
| | | return Long.valueOf(value.toString()); |
| | | } catch (NumberFormatException e) { |
| | | return null; |
| | | } |
| | | } |
| | | private Integer getIntegerValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | if (value instanceof Integer) { |
| | | return (Integer) value; |
| | | } |
| | | try { |
| | | return Integer.valueOf(value.toString()); |
| | | } catch (NumberFormatException e) { |
| | | return null; |
| | | } |
| | | } |
| | | /** |
| | | * 从Map中获取Date值 |
| | | * |
| | | * @param map Map对象 |
| | | * @param key 键 |
| | | * @return Date值 |
| | | */ |
| | | private Date getDateValue(Map<String, Object> map, String key) { |
| | | Object value = map.get(key); |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | if (value instanceof Date) { |
| | | return (Date) value; |
| | | } |
| | | // 如果是字符串,尝试解析 |
| | | if (value instanceof String) { |
| | | try { |
| | | return DateUtils.parseDate(value.toString()); |
| | | } catch (Exception e) { |
| | | return null; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 验证日期字符串格式是否有效 |
| | | * |
| | | * @param dateStr 日期字符串 |
| | | * @param format 日期格式 |
| | | * @return 是否有效 |
| | | */ |
| | | private boolean isValidDateFormat(String dateStr, String format) { |
| | | if (StringUtils.isEmpty(dateStr)) { |
| | | return false; |
| | | } |
| | | |
| | | try { |
| | | SimpleDateFormat sdf = new SimpleDateFormat(format); |
| | | sdf.setLenient(false); |
| | | sdf.parse(dateStr); |
| | | return true; |
| | | } catch (Exception e) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | private void notifyTransferOrderByWechat(Long taskId, |
| | | String serviceOrdID, |
| | |
| | | @Autowired |
| | | private ISmsService smsService; |
| | | |
| | | @Autowired |
| | | private IQyWechatService qyWechatService; |
| | | |
| | | |
| | | @Autowired |
| | | private ISysEmergencyTaskService sysEmergencyTaskService; |
| | | |
| | | /** |
| | | * 获取指定通知类型启用的渠道列表 |
| | | */ |
| | |
| | | break; |
| | | case NotifyChannelConfig.CHANNEL_SMS: |
| | | success = sendSmsMessage(notifyTask); |
| | | break; |
| | | case NotifyChannelConfig.CHANNEL_QY_WECHAT: |
| | | success = sendQyWechatMessage(notifyTask); |
| | | break; |
| | | default: |
| | | log.warn("不支持的渠道类型:{}", channel); |
| | |
| | | sendLog.setChannel(channel); |
| | | sendLog.setSendStatus(success ? NotifySendLog.SEND_STATUS_SUCCESS : NotifySendLog.SEND_STATUS_FAILED); |
| | | sendLog.setSendTime(DateUtils.getNowDate()); |
| | | sendLog.setSendContent(notifyTask.getContent()); |
| | | sendLog.setResponseMsg(errorMsg); |
| | | |
| | | notifySendLogService.insertNotifySendLog(sendLog); |
| | |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | @Autowired |
| | | private ISysConfigService sysConfigService; |
| | | /** |
| | | * 发送企业微信消息 |
| | | */ |
| | | @Override |
| | | public boolean sendQyWechatMessage(NotifyTask notifyTask) { |
| | | try { |
| | | // 检查企业微信服务是否启用 |
| | | if (!qyWechatService.isEnabled()) { |
| | | log.info("企业微信服务已关闭,跳过发送"); |
| | | return false; |
| | | } |
| | | Long taskId= notifyTask.getTaskId(); |
| | | SysTaskEmergency emergency = this.sysEmergencyTaskService.selectSysTaskEmergencyByTaskId(taskId); |
| | | if(emergency==null){ |
| | | return false; |
| | | } |
| | | Long dispatchOrderId = emergency.getLegacyDispatchOrdId(); |
| | | String oldsiteUrl= sysConfigService.selectConfigByKey("oldsite.url"); |
| | | if(oldsiteUrl==null){ |
| | | oldsiteUrl="https://sys.966120.com.cn/m_DispatchOrder.gds?DispatchOrdID="; |
| | | } |
| | | String url=oldsiteUrl+dispatchOrderId; |
| | | // 发送企业微信消息 |
| | | boolean success = qyWechatService.sendNotifyMessage( |
| | | notifyTask.getUserId(), |
| | | notifyTask.getTitle(), |
| | | notifyTask.getContent(),url |
| | | ); |
| | | |
| | | if (success) { |
| | | log.info("企业微信消息发送成功,userId={}", notifyTask.getUserId()); |
| | | } else { |
| | | log.warn("企业微信消息发送失败,userId={}", notifyTask.getUserId()); |
| | | } |
| | | return success; |
| | | } catch (Exception e) { |
| | | log.error("企业微信消息发送异常,taskId={}, userId={}", notifyTask.getTaskId(), notifyTask.getUserId(), e); |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * 根据任务ID和用户ID查询发送记录 |
| | | */ |
| | | @Override |
| | | public NotifySendLog selectNotifySendLog(Long taskId, Long userId, String notifyType, String channel) { |
| | | return notifySendLogMapper.selectNotifySendLog(taskId, userId, notifyType, channel); |
| | | } |
| | | |
| | | /** |
| | | * 检查是否已发送过通知(防重检查) |
| | | * |
| | | * @param taskId 任务ID |
| | |
| | | } |
| | | |
| | | /** |
| | | * 更新发送状态为成功 |
| | | * 更新发送状态为成功(向后兼容) |
| | | * |
| | | * @param id 记录ID |
| | | * @param result 发送结果信息 |
| | | */ |
| | | @Override |
| | | public void markSendSuccess(Long id, String result) { |
| | | markSendSuccess(id, result, null); |
| | | } |
| | | |
| | | /** |
| | | * 更新发送状态为成功 |
| | | * |
| | | * @param id 记录ID |
| | | * @param result 发送结果信息 |
| | | * @param content 发送内容 |
| | | */ |
| | | @Override |
| | | public void markSendSuccess(Long id, String result, String content) { |
| | | if (id == null) { |
| | | return; |
| | | } |
| | | try { |
| | | notifySendLogMapper.updateSendStatus(id, NotifySendLog.SEND_STATUS_SUCCESS, result); |
| | | notifySendLogMapper.updateSendStatus(id, NotifySendLog.SEND_STATUS_SUCCESS, result, content); |
| | | log.debug("更新通知发送状态为成功,id={}", id); |
| | | } catch (Exception e) { |
| | | log.error("更新通知发送状态失败,id={}", id, e); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 更新发送状态为失败 |
| | | * 更新发送状态为失败(向后兼容) |
| | | * |
| | | * @param id 记录ID |
| | | * @param errorMsg 错误信息 |
| | | */ |
| | | @Override |
| | | public void markSendFailed(Long id, String errorMsg) { |
| | | markSendFailed(id, errorMsg, null); |
| | | } |
| | | |
| | | /** |
| | | * 更新发送状态为失败 |
| | | * |
| | | * @param id 记录ID |
| | | * @param errorMsg 错误信息 |
| | | * @param content 发送内容 |
| | | */ |
| | | @Override |
| | | public void markSendFailed(Long id, String errorMsg, String content) { |
| | | if (id == null) { |
| | | return; |
| | | } |
| | |
| | | if (errorMsg != null && errorMsg.length() > 500) { |
| | | errorMsg = errorMsg.substring(0, 500); |
| | | } |
| | | notifySendLogMapper.updateSendStatus(id, NotifySendLog.SEND_STATUS_FAILED, errorMsg); |
| | | notifySendLogMapper.updateSendStatus(id, NotifySendLog.SEND_STATUS_FAILED, errorMsg, content); |
| | | log.debug("更新通知发送状态为失败,id={}, error={}", id, errorMsg); |
| | | } catch (Exception e) { |
| | | log.error("更新通知发送状态失败,id={}", id, e); |
| | |
| | | * @param maxRetryCount 最大重试次数 |
| | | * @return 失败记录列表 |
| | | */ |
| | | @Override |
| | | |
| | | public List<NotifySendLog> selectFailedNotifySendLogs(Integer maxRetryCount) { |
| | | return notifySendLogMapper.selectFailedNotifySendLogs(maxRetryCount); |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.system.service.IQyWechatAccessTokenService; |
| | | import com.ruoyi.system.service.ISysConfigService; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * 企业微信AccessToken服务实现类 |
| | | * |
| | | * @author ruoyi |
| | | * @date 2025-12-11 |
| | | */ |
| | | @Service |
| | | public class QyWechatAccessTokenServiceImpl implements IQyWechatAccessTokenService { |
| | | |
| | | private static final Logger log = LoggerFactory.getLogger(QyWechatAccessTokenServiceImpl.class); |
| | | |
| | | @Autowired |
| | | private ISysConfigService configService; |
| | | |
| | | /** |
| | | * 企业微信获取access_token的URL |
| | | */ |
| | | private static final String GET_ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"; |
| | | |
| | | /** |
| | | * 获取企业微信应用的AccessToken |
| | | * |
| | | * @param corpId 企业ID |
| | | * @param corpSecret 应用密钥 |
| | | * @return AccessToken |
| | | */ |
| | | @Override |
| | | public String getAppAccessToken(String corpId, String corpSecret) { |
| | | try { |
| | | // 参数校验 |
| | | if (StringUtils.isEmpty(corpId) || StringUtils.isEmpty(corpSecret)) { |
| | | log.warn("企业微信配置参数不完整,corpId或corpSecret为空"); |
| | | return null; |
| | | } |
| | | |
| | | // 检查服务是否启用 |
| | | if (!isEnabled()) { |
| | | log.info("企业微信服务已禁用,无法获取AccessToken"); |
| | | return null; |
| | | } |
| | | |
| | | // 构建配置键名 |
| | | String tokenKey = "qy_wechat.access_token." + corpId; |
| | | String expiresKey = "qy_wechat.access_token_expires." + corpId; |
| | | |
| | | // 从配置中获取Token和过期时间 |
| | | String accessToken = configService.selectConfigByKey(tokenKey); |
| | | String expiresStr = configService.selectConfigByKey(expiresKey); |
| | | |
| | | // 检查Token是否存在且未过期 |
| | | if (StringUtils.isNotEmpty(accessToken) && StringUtils.isNotEmpty(expiresStr)) { |
| | | try { |
| | | long expiresTime = Long.parseLong(expiresStr); |
| | | long currentTime = System.currentTimeMillis(); |
| | | |
| | | // 预留60秒安全边界,避免临界点过期 |
| | | if (currentTime < expiresTime - 60000) { |
| | | log.debug("使用缓存的企业微信AccessToken,剩余有效时间: {}秒", |
| | | (expiresTime - currentTime) / 1000); |
| | | return accessToken; |
| | | } else { |
| | | log.info("企业微信AccessToken已过期或即将过期,需要刷新"); |
| | | } |
| | | } catch (NumberFormatException e) { |
| | | log.warn("解析企业微信AccessToken过期时间失败: {}", expiresStr); |
| | | } |
| | | } |
| | | |
| | | // Token不存在或已过期,刷新Token |
| | | return refreshAppAccessToken(corpId, corpSecret); |
| | | } catch (Exception e) { |
| | | log.error("获取企业微信AccessToken失败", e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 刷新企业微信应用的AccessToken |
| | | * |
| | | * @param corpId 企业ID |
| | | * @param corpSecret 应用密钥 |
| | | * @return 新的AccessToken |
| | | */ |
| | | @Override |
| | | public String refreshAppAccessToken(String corpId, String corpSecret) { |
| | | try { |
| | | log.info("开始刷新企业微信AccessToken"); |
| | | |
| | | // 构建请求URL |
| | | String url = GET_ACCESS_TOKEN_URL + "?corpid=" + corpId + "&corpsecret=" + corpSecret; |
| | | |
| | | // 发送HTTP请求获取Token |
| | | String response = sendHttpGetRequest(url); |
| | | |
| | | if (StringUtils.isEmpty(response)) { |
| | | log.error("获取企业微信AccessToken失败,响应为空"); |
| | | return null; |
| | | } |
| | | |
| | | // 解析响应 |
| | | QyWechatTokenResponse tokenResponse = parseTokenResponse(response); |
| | | |
| | | if (tokenResponse == null || StringUtils.isEmpty(tokenResponse.getAccessToken())) { |
| | | log.error("解析企业微信AccessToken响应失败: {}", response); |
| | | return null; |
| | | } |
| | | |
| | | // 计算过期时间(当前时间 + 有效期 - 60秒安全边界) |
| | | long expiresTime = System.currentTimeMillis() + (tokenResponse.getExpiresIn() * 1000L) - 60000L; |
| | | |
| | | // 构建配置键名 |
| | | String tokenKey = "qy_wechat.access_token." + corpId; |
| | | String expiresKey = "qy_wechat.access_token_expires." + corpId; |
| | | |
| | | // 保存到系统配置表 |
| | | configService.updateConfigValue(tokenKey, tokenResponse.getAccessToken()); |
| | | configService.updateConfigValue(expiresKey, String.valueOf(expiresTime)); |
| | | |
| | | log.info("企业微信AccessToken刷新成功,有效期: {}秒", tokenResponse.getExpiresIn()); |
| | | return tokenResponse.getAccessToken(); |
| | | } catch (Exception e) { |
| | | log.error("刷新企业微信AccessToken失败", e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 检查企业微信服务是否启用 |
| | | * |
| | | * @return true-启用,false-禁用 |
| | | */ |
| | | @Override |
| | | public boolean isEnabled() { |
| | | try { |
| | | String enabled = configService.selectConfigByKey("qy_wechat.enable"); |
| | | return !"false".equals(enabled); // 默认启用 |
| | | } catch (Exception e) { |
| | | log.warn("获取企业微信服务启用状态失败,使用默认值(true)", e); |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 发送HTTP GET请求 |
| | | * |
| | | * @param url 请求URL |
| | | * @return 响应内容 |
| | | */ |
| | | private String sendHttpGetRequest(String url) { |
| | | try { |
| | | java.net.HttpURLConnection conn = (java.net.HttpURLConnection) new java.net.URL(url).openConnection(); |
| | | conn.setRequestMethod("GET"); |
| | | conn.setConnectTimeout(5000); |
| | | conn.setReadTimeout(5000); |
| | | |
| | | int responseCode = conn.getResponseCode(); |
| | | if (responseCode == 200) { |
| | | java.io.BufferedReader reader = new java.io.BufferedReader( |
| | | new java.io.InputStreamReader(conn.getInputStream(), "UTF-8")); |
| | | StringBuilder response = new StringBuilder(); |
| | | String line; |
| | | while ((line = reader.readLine()) != null) { |
| | | response.append(line); |
| | | } |
| | | reader.close(); |
| | | return response.toString(); |
| | | } else { |
| | | log.error("HTTP请求失败,响应码: {}", responseCode); |
| | | return null; |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("发送HTTP请求失败", e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 解析企业微信Token响应 |
| | | * |
| | | * @param response 响应JSON |
| | | * @return Token响应对象 |
| | | */ |
| | | private QyWechatTokenResponse parseTokenResponse(String response) { |
| | | try { |
| | | // 简单JSON解析(实际项目中建议使用Jackson或Gson) |
| | | // 示例响应: {"errcode":0,"errmsg":"ok","access_token":"xxxxxx","expires_in":7200} |
| | | |
| | | // 移除花括号 |
| | | String content = response.substring(1, response.length() - 1); |
| | | |
| | | // 按逗号分割 |
| | | String[] pairs = content.split(","); |
| | | |
| | | QyWechatTokenResponse tokenResponse = new QyWechatTokenResponse(); |
| | | |
| | | for (String pair : pairs) { |
| | | String[] keyValue = pair.split(":"); |
| | | if (keyValue.length == 2) { |
| | | String key = keyValue[0].trim().replaceAll("\"", ""); |
| | | String value = keyValue[1].trim().replaceAll("\"", ""); |
| | | |
| | | switch (key) { |
| | | case "errcode": |
| | | tokenResponse.setErrcode(Integer.parseInt(value)); |
| | | break; |
| | | case "errmsg": |
| | | tokenResponse.setErrmsg(value); |
| | | break; |
| | | case "access_token": |
| | | tokenResponse.setAccessToken(value); |
| | | break; |
| | | case "expires_in": |
| | | tokenResponse.setExpiresIn(Integer.parseInt(value)); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 检查是否有错误 |
| | | if (tokenResponse.getErrcode() != 0) { |
| | | log.error("获取企业微信AccessToken失败,错误码: {}, 错误信息: {}", |
| | | tokenResponse.getErrcode(), tokenResponse.getErrmsg()); |
| | | return null; |
| | | } |
| | | |
| | | return tokenResponse; |
| | | } catch (Exception e) { |
| | | log.error("解析企业微信Token响应失败: {}", response, e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 企业微信Token响应内部类 |
| | | */ |
| | | private static class QyWechatTokenResponse { |
| | | private int errcode; |
| | | private String errmsg; |
| | | private String accessToken; |
| | | private int expiresIn; |
| | | |
| | | // Getters and Setters |
| | | public int getErrcode() { |
| | | return errcode; |
| | | } |
| | | |
| | | public void setErrcode(int errcode) { |
| | | this.errcode = errcode; |
| | | } |
| | | |
| | | public String getErrmsg() { |
| | | return errmsg; |
| | | } |
| | | |
| | | public void setErrmsg(String errmsg) { |
| | | this.errmsg = errmsg; |
| | | } |
| | | |
| | | public String getAccessToken() { |
| | | return accessToken; |
| | | } |
| | | |
| | | public void setAccessToken(String accessToken) { |
| | | this.accessToken = accessToken; |
| | | } |
| | | |
| | | public int getExpiresIn() { |
| | | return expiresIn; |
| | | } |
| | | |
| | | public void setExpiresIn(int expiresIn) { |
| | | this.expiresIn = expiresIn; |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.ruoyi.common.core.domain.entity.SysUser; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.system.domain.QyWechatArticle; |
| | | import com.ruoyi.system.mapper.SysUserMapper; |
| | | import com.ruoyi.system.service.IQyWechatAccessTokenService; |
| | | import com.ruoyi.system.service.IQyWechatService; |
| | | import com.ruoyi.system.service.ISysConfigService; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 企业微信服务实现类 |
| | | * |
| | | * @author ruoyi |
| | | * @date 2025-12-11 |
| | | */ |
| | | @Service |
| | | public class QyWechatServiceImpl implements IQyWechatService { |
| | | |
| | | private static final Logger log = LoggerFactory.getLogger(QyWechatServiceImpl.class); |
| | | |
| | | @Autowired |
| | | private IQyWechatAccessTokenService qyWechatAccessTokenService; |
| | | |
| | | @Autowired |
| | | private ISysConfigService configService; |
| | | |
| | | @Autowired |
| | | private SysUserMapper userMapper; |
| | | |
| | | /** |
| | | * 发送企业微信消息 |
| | | */ |
| | | @Override |
| | | public boolean sendNotifyMessage(Long userId, String title, String content,String notifyUrl) { |
| | | try { |
| | | // 检查服务是否启用 |
| | | if (!isEnabled()) { |
| | | log.info("企业微信服务未启用,跳过消息发送"); |
| | | return false; |
| | | } |
| | | |
| | | // 获取用户的企业微信ID |
| | | String qyUserId = getQyUserIdByUserId(userId); |
| | | if (StringUtils.isEmpty(qyUserId)) { |
| | | log.warn("用户{}未绑定企业微信ID,无法发送消息", userId); |
| | | return false; |
| | | } |
| | | |
| | | // 发送文本消息 |
| | | return sendTextMessage(qyUserId, title, content, notifyUrl); |
| | | } catch (Exception e) { |
| | | log.error("企业微信消息发送异常,userId={}", userId, e); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 发送企业微信文本消息 |
| | | */ |
| | | @Override |
| | | public boolean sendTextMessage(String qyUserId, String title, String content, String notifyUrl) { |
| | | try { |
| | | // 检查服务是否启用 |
| | | if (!isEnabled()) { |
| | | log.info("企业微信服务未启用,跳过消息发送"); |
| | | return false; |
| | | } |
| | | |
| | | // 获取企业微信配置 |
| | | String corpId = configService.selectConfigByKey("qy_wechat.corp_id"); |
| | | String corpSecret = configService.selectConfigByKey("qy_wechat.corp_secret"); |
| | | |
| | | if (StringUtils.isEmpty(corpId) || StringUtils.isEmpty(corpSecret)) { |
| | | log.error("企业微信配置不完整,缺少corpId或corpSecret"); |
| | | return false; |
| | | } |
| | | |
| | | // 获取AccessToken |
| | | String accessToken = qyWechatAccessTokenService.getAppAccessToken(corpId, corpSecret); |
| | | if (StringUtils.isEmpty(accessToken)) { |
| | | log.error("获取企业微信AccessToken失败"); |
| | | return false; |
| | | } |
| | | |
| | | // 构造请求URL |
| | | String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + accessToken; |
| | | |
| | | // 构造文章对象 |
| | | QyWechatArticle article = new QyWechatArticle(); |
| | | article.setTitle(title); |
| | | article.setDescription(content); |
| | | article.setUrl(notifyUrl); |
| | | // 设置默认图片URL,您可以根据需要修改 |
| | | |
| | | |
| | | // 构造请求参数 |
| | | Map<String, Object> params = new HashMap<>(); |
| | | params.put("touser", qyUserId); |
| | | params.put("msgtype", "news"); |
| | | params.put("agentid", Integer.parseInt(configService.selectConfigByKey("qy_wechat.agent_id"))); |
| | | |
| | | // 构造文章列表 |
| | | List<QyWechatArticle> articles = new ArrayList<>(); |
| | | articles.add(article); |
| | | params.put("news", Collections.singletonMap("articles", articles)); |
| | | |
| | | // 发送HTTP POST请求 |
| | | String response = sendHttpPostRequest(url, params); |
| | | |
| | | if (StringUtils.isEmpty(response)) { |
| | | log.error("发送企业微信消息失败,响应为空"); |
| | | return false; |
| | | } |
| | | |
| | | // 解析响应结果 |
| | | QyWechatResponse result = parseResponse(response); |
| | | |
| | | if (result != null && result.getErrcode() == 0) { |
| | | log.info("企业微信消息发送成功,用户ID: {}", qyUserId); |
| | | return true; |
| | | } else { |
| | | log.error("企业微信消息发送失败,错误码: {}, 错误信息: {}", |
| | | result != null ? result.getErrcode() : "unknown", |
| | | result != null ? result.getErrmsg() : response); |
| | | return false; |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("企业微信文本消息发送异常,qyUserId={}", qyUserId, e); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取用户的企业微信ID |
| | | */ |
| | | @Override |
| | | public String getQyUserIdByUserId(Long userId) { |
| | | try { |
| | | if (userId == null) { |
| | | log.warn("用户ID不能为空"); |
| | | return null; |
| | | } |
| | | |
| | | // 查询用户信息 |
| | | SysUser user = userMapper.selectUserById(userId); |
| | | if (user == null) { |
| | | log.warn("未找到用户,userId={}", userId); |
| | | return null; |
| | | } |
| | | |
| | | // 返回企业微信用户ID |
| | | return user.getQyWechatUserId(); |
| | | } catch (Exception e) { |
| | | log.error("获取用户企业微信ID异常,userId={}", userId, e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 检查企业微信服务是否启用 |
| | | */ |
| | | @Override |
| | | public boolean isEnabled() { |
| | | try { |
| | | String enabled = configService.selectConfigByKey("qy_wechat.enable"); |
| | | return "true".equals(enabled); |
| | | } catch (Exception e) { |
| | | log.warn("获取企业微信服务启用状态失败,使用默认值(false)", e); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 发送HTTP POST请求 |
| | | * |
| | | * @param url 请求URL |
| | | * @param params 请求参数 |
| | | * @return 响应内容 |
| | | */ |
| | | private String sendHttpPostRequest(String url, Map<String, Object> params) { |
| | | try { |
| | | // 将参数转换为JSON字符串 |
| | | String jsonParams = toJsonString(params); |
| | | |
| | | java.net.HttpURLConnection conn = (java.net.HttpURLConnection) new java.net.URL(url).openConnection(); |
| | | conn.setRequestMethod("POST"); |
| | | conn.setConnectTimeout(5000); |
| | | conn.setReadTimeout(5000); |
| | | conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); |
| | | conn.setDoOutput(true); |
| | | |
| | | // 发送请求数据 |
| | | java.io.OutputStream os = conn.getOutputStream(); |
| | | os.write(jsonParams.getBytes("UTF-8")); |
| | | os.flush(); |
| | | os.close(); |
| | | |
| | | int responseCode = conn.getResponseCode(); |
| | | if (responseCode == 200) { |
| | | java.io.BufferedReader reader = new java.io.BufferedReader( |
| | | new java.io.InputStreamReader(conn.getInputStream(), "UTF-8")); |
| | | StringBuilder response = new StringBuilder(); |
| | | String line; |
| | | while ((line = reader.readLine()) != null) { |
| | | response.append(line); |
| | | } |
| | | reader.close(); |
| | | return response.toString(); |
| | | } else { |
| | | log.error("HTTP请求失败,响应码: {}", responseCode); |
| | | return null; |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("发送HTTP POST请求失败", e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 简单的JSON序列化方法 |
| | | * |
| | | * @param map 要序列化的Map |
| | | * @return JSON字符串 |
| | | */ |
| | | private String toJsonString(Map<String, Object> map) { |
| | | StringBuilder json = new StringBuilder("{"); |
| | | boolean first = true; |
| | | |
| | | for (Map.Entry<String, Object> entry : map.entrySet()) { |
| | | if (!first) { |
| | | json.append(","); |
| | | } |
| | | |
| | | json.append("\"").append(entry.getKey()).append("\":"); |
| | | |
| | | Object value = entry.getValue(); |
| | | if (value instanceof String) { |
| | | json.append("\"").append(value).append("\""); |
| | | } else if (value instanceof Map) { |
| | | // 处理嵌套Map |
| | | json.append(toJsonString((Map<String, Object>) value)); |
| | | } else if (value instanceof List) { |
| | | // 处理列表 |
| | | json.append(toJsonList((List<Object>) value)); |
| | | } else { |
| | | json.append(value); |
| | | } |
| | | |
| | | first = false; |
| | | } |
| | | |
| | | json.append("}"); |
| | | return json.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 序列化列表为JSON |
| | | * |
| | | * @param list 列表 |
| | | * @return JSON字符串 |
| | | */ |
| | | private String toJsonList(List<Object> list) { |
| | | StringBuilder json = new StringBuilder("["); |
| | | boolean first = true; |
| | | |
| | | for (Object item : list) { |
| | | if (!first) { |
| | | json.append(","); |
| | | } |
| | | |
| | | if (item instanceof String) { |
| | | json.append("\"").append(item).append("\""); |
| | | } else if (item instanceof Map) { |
| | | json.append(toJsonString((Map<String, Object>) item)); |
| | | } else if (item instanceof QyWechatArticle) { |
| | | json.append(toJsonArticle((QyWechatArticle) item)); |
| | | } else { |
| | | json.append(item); |
| | | } |
| | | |
| | | first = false; |
| | | } |
| | | |
| | | json.append("]"); |
| | | return json.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 序列化文章对象为JSON |
| | | * |
| | | * @param article 文章对象 |
| | | * @return JSON字符串 |
| | | */ |
| | | private String toJsonArticle(QyWechatArticle article) { |
| | | StringBuilder json = new StringBuilder("{"); |
| | | boolean first = true; |
| | | |
| | | // 添加非空字段 |
| | | if (article.getTitle() != null) { |
| | | if (!first) json.append(","); |
| | | json.append("\"title\":\"").append(escapeJsonString(article.getTitle())).append("\""); |
| | | first = false; |
| | | } |
| | | if (article.getDescription() != null) { |
| | | if (!first) json.append(","); |
| | | json.append("\"description\":\"").append(escapeJsonString(article.getDescription())).append("\""); |
| | | first = false; |
| | | } |
| | | if (article.getUrl() != null) { |
| | | if (!first) json.append(","); |
| | | json.append("\"url\":\"").append(escapeJsonString(article.getUrl())).append("\""); |
| | | first = false; |
| | | } |
| | | if (article.getPicurl() != null) { |
| | | if (!first) json.append(","); |
| | | json.append("\"picurl\":\"").append(escapeJsonString(article.getPicurl())).append("\""); |
| | | first = false; |
| | | } |
| | | if (article.getAppid() != null) { |
| | | if (!first) json.append(","); |
| | | json.append("\"appid\":\"").append(escapeJsonString(article.getAppid())).append("\""); |
| | | first = false; |
| | | } |
| | | if (article.getPagepath() != null) { |
| | | if (!first) json.append(","); |
| | | json.append("\"pagepath\":\"").append(escapeJsonString(article.getPagepath())).append("\""); |
| | | first = false; |
| | | } |
| | | |
| | | json.append("}"); |
| | | return json.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 转义JSON字符串中的特殊字符 |
| | | * |
| | | * @param str 原始字符串 |
| | | * @return 转义后的字符串 |
| | | */ |
| | | private String escapeJsonString(String str) { |
| | | if (str == null) return ""; |
| | | return str.replace("\\", "\\\\") |
| | | .replace("\"", "\\\"") |
| | | .replace("\n", "\\n") |
| | | .replace("\r", "\\r") |
| | | .replace("\t", "\\t"); |
| | | } |
| | | |
| | | /** |
| | | * 解析企业微信响应 |
| | | * |
| | | * @param response 响应JSON |
| | | * @return 响应对象 |
| | | */ |
| | | private QyWechatResponse parseResponse(String response) { |
| | | try { |
| | | // 使用简单JSON解析 |
| | | QyWechatResponse result = new QyWechatResponse(); |
| | | |
| | | // 移除首尾花括号 |
| | | String content = response.trim(); |
| | | if (content.startsWith("{")) { |
| | | content = content.substring(1); |
| | | } |
| | | if (content.endsWith("}")) { |
| | | content = content.substring(0, content.length() - 1); |
| | | } |
| | | |
| | | // 按逗号分割键值对 |
| | | String[] pairs = content.split(","); |
| | | |
| | | for (String pair : pairs) { |
| | | String[] keyValue = pair.split(":", 2); // 只分割第一个冒号 |
| | | if (keyValue.length == 2) { |
| | | String key = keyValue[0].trim().replaceAll("\"", ""); |
| | | String value = keyValue[1].trim().replaceAll("\"", ""); |
| | | |
| | | switch (key) { |
| | | case "errcode": |
| | | result.setErrcode(Integer.parseInt(value)); |
| | | break; |
| | | case "errmsg": |
| | | result.setErrmsg(value); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | } catch (Exception e) { |
| | | log.error("解析企业微信响应失败: {}", response, e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 企业微信响应内部类 |
| | | */ |
| | | private static class QyWechatResponse { |
| | | private int errcode; |
| | | private String errmsg; |
| | | |
| | | // Getters and Setters |
| | | public int getErrcode() { |
| | | return errcode; |
| | | } |
| | | |
| | | public void setErrcode(int errcode) { |
| | | this.errcode = errcode; |
| | | } |
| | | |
| | | public String getErrmsg() { |
| | | return errmsg; |
| | | } |
| | | |
| | | public void setErrmsg(String errmsg) { |
| | | this.errmsg = errmsg; |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * 更新配置值 |
| | | * |
| | | * @param configKey 参数键名 |
| | | * @param configValue 参数值 |
| | | * @return 结果 |
| | | */ |
| | | @Override |
| | | public int updateConfigValue(String configKey, String configValue) { |
| | | // 先查询是否存在该配置项 |
| | | SysConfig config = new SysConfig(); |
| | | config.setConfigKey(configKey); |
| | | SysConfig existingConfig = configMapper.selectConfig(config); |
| | | |
| | | if (existingConfig != null) { |
| | | // 如果存在,更新配置值 |
| | | existingConfig.setConfigValue(configValue); |
| | | existingConfig.setUpdateTime(new java.util.Date()); |
| | | int result = configMapper.updateConfig(existingConfig); |
| | | // 更新缓存 |
| | | if (result > 0) { |
| | | redisCache.setCacheObject(getCacheKey(configKey), configValue); |
| | | } |
| | | return result; |
| | | } else { |
| | | // 如果不存在,创建新的配置项 |
| | | SysConfig newConfig = new SysConfig(); |
| | | newConfig.setConfigKey(configKey); |
| | | newConfig.setConfigValue(configValue); |
| | | newConfig.setConfigName("企业微信配置"); |
| | | newConfig.setConfigType("N"); // 非系统内置 |
| | | newConfig.setCreateBy("system"); |
| | | int result = configMapper.insertConfig(newConfig); |
| | | // 更新缓存 |
| | | if (result > 0) { |
| | | redisCache.setCacheObject(getCacheKey(configKey), configValue); |
| | | } |
| | | return result; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置cache key |
| | | * |
| | | * @param configKey 参数键 |
| | |
| | | emergencyInfo.setCreateBy(createUserName); |
| | | emergencyInfo.setUpdateBy(createUserName); |
| | | |
| | | if(createVO.getLegacyDispatchNsTime() != null){ |
| | | emergencyInfo.setLegacyDispatchNsTime(createVO.getLegacyDispatchNsTime()); |
| | | } |
| | | if(createVO.getLegacyDispatchOrdClass() != null){ |
| | | emergencyInfo.setLegacyDispatchOrdClass(createVO.getLegacyDispatchOrdClass()); |
| | | } |
| | | if(createVO.getLegacyDispatchOrdNo() != null){ |
| | | emergencyInfo.setLegacyDispatchOrdNo(createVO.getLegacyDispatchOrdNo()); |
| | | } |
| | | if(createVO.getLegacyServiceNsTime() != null){ |
| | | emergencyInfo.setLegacyServiceNsTime(createVO.getLegacyServiceNsTime()); |
| | | } |
| | | if(createVO.getLegacyServiceOrdClass() != null){ |
| | | emergencyInfo.setLegacyServiceOrdClass(createVO.getLegacyServiceOrdClass()); |
| | | } |
| | | sysTaskEmergencyMapper.insertSysTaskEmergency(emergencyInfo); |
| | | } |
| | | |
| | |
| | | oldEmergency.setUpdateTime(DateUtils.getNowDate()); |
| | | oldEmergency.setUpdateBy(userName); |
| | | |
| | | if( updateVO.getLegacyDispatchNsTime() != null) { |
| | | oldEmergency.setLegacyDispatchNsTime(updateVO.getLegacyDispatchNsTime()); |
| | | } |
| | | if( updateVO.getLegacyServiceNsTime() != null){ |
| | | oldEmergency.setLegacyServiceNsTime(updateVO.getLegacyServiceNsTime()); |
| | | } |
| | | if( updateVO.getLegacyDispatchOrdClass() != null){ |
| | | oldEmergency.setLegacyDispatchOrdClass(updateVO.getLegacyDispatchOrdClass()); |
| | | } |
| | | if( updateVO.getLegacyDispatchOrdNo() != null){ |
| | | oldEmergency.setLegacyDispatchOrdNo(updateVO.getLegacyDispatchOrdNo()); |
| | | } |
| | | if( updateVO.getLegacyServiceOrdClass() != null){ |
| | | oldEmergency.setLegacyServiceOrdClass(updateVO.getLegacyServiceOrdClass()); |
| | | } |
| | | |
| | | sysTaskEmergencyMapper.updateSysTaskEmergency(oldEmergency); |
| | | } |
| | | |
| | | @Override |
| | | public SysTaskEmergency selectSysTaskEmergencyByTaskId(Long taskId) { |
| | | return sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId); |
| | | } |
| | | |
| | | @Override |
| | |
| | | // 系统字段 |
| | | existingInfo.setUpdateTime(DateUtils.getNowDate()); |
| | | existingInfo.setUpdateBy(userName); |
| | | |
| | | if(createVO.getLegacyDispatchNsTime() != null){ |
| | | existingInfo.setLegacyDispatchNsTime(createVO.getLegacyDispatchNsTime()); |
| | | } |
| | | if(createVO.getLegacyDispatchOrdNo() != null){ |
| | | existingInfo.setLegacyDispatchOrdNo(createVO.getLegacyDispatchOrdNo()); |
| | | } |
| | | if(createVO.getLegacyServiceNsTime() != null){ |
| | | existingInfo.setLegacyServiceNsTime(createVO.getLegacyServiceNsTime()); |
| | | } |
| | | if(createVO.getLegacyDispatchOrdClass() != null){ |
| | | existingInfo.setLegacyDispatchOrdClass(createVO.getLegacyDispatchOrdClass()); |
| | | } |
| | | if(createVO.getLegacyServiceOrdClass() != null){ |
| | | existingInfo.setLegacyServiceOrdClass(createVO.getLegacyServiceOrdClass()); |
| | | } |
| | | |
| | | // 执行更新 |
| | | sysTaskEmergencyMapper.updateSysTaskEmergency(existingInfo); |
| | |
| | | import com.ruoyi.common.core.domain.AjaxResult; |
| | | import com.ruoyi.common.core.domain.entity.SysUser; |
| | | import com.ruoyi.system.domain.vo.*; |
| | | import com.ruoyi.system.event.TaskDispatchSyncEvent; |
| | | import com.ruoyi.system.mapper.*; |
| | | import com.ruoyi.system.service.*; |
| | | import com.ruoyi.system.utils.TaskCodeGenerator; |
| | |
| | | @Autowired |
| | | private ISysTaskVehicleService sysTaskVehicleService; |
| | | |
| | | @Override |
| | | public Boolean dispatchSyncEvent(Long taskId) { |
| | | SysTask task= sysTaskMapper.selectSysTaskByTaskId(taskId); |
| | | SysUser user= sysUserMapper.selectUserById(task.getCreatorId()); |
| | | Integer oaUser=user.getOaUserId(); |
| | | SysTaskEmergency emergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId); |
| | | eventPublisher.publishEvent(new TaskDispatchSyncEvent(this, taskId, task.getTaskCode(),emergency.getLegacyServiceOrdId(), emergency.getLegacyDispatchOrdId(),oaUser)); |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 查询任务管理 |
| | | * |
| | |
| | | */ |
| | | @Override |
| | | public List<SysTask> selectSysTaskList(TaskQueryVO queryVO) { |
| | | return sysTaskMapper.selectSysTaskList(queryVO); |
| | | List<SysTask> tasks= sysTaskMapper.selectSysTaskList(queryVO); |
| | | tasks.forEach(task -> { |
| | | if ("EMERGENCY_TRANSFER".equals(task.getTaskType())) { |
| | | SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(task.getTaskId()); |
| | | task.setEmergencyInfo(emergencyInfo); |
| | | } |
| | | }); |
| | | return tasks; |
| | | } |
| | | |
| | | /** |
| | | * 根据任务编号、调度单编号或服务单编号查询任务列表 |
| | | * |
| | | * @param queryVO 任务查询对象 |
| | | * @param taskCode 任务编号 |
| | | * @return 任务管理集合 |
| | | */ |
| | | @Override |
| | | public List<SysTask> selectSysTaskListByMultiCode(TaskQueryVO queryVO, String taskCode) { |
| | | // Create a new query object without the taskCode filter |
| | | TaskQueryVO newQuery = new TaskQueryVO(); |
| | | // Copy all properties except taskCode |
| | | try { |
| | | org.springframework.beans.BeanUtils.copyProperties(queryVO, newQuery, "taskCode"); |
| | | } catch (Exception e) { |
| | | // If copy fails, manually copy the important fields |
| | | newQuery.setTaskType(queryVO.getTaskType()); |
| | | newQuery.setTaskStatus(queryVO.getTaskStatus()); |
| | | newQuery.setVehicleNo(queryVO.getVehicleNo()); |
| | | newQuery.setCreatorId(queryVO.getCreatorId()); |
| | | newQuery.setAssigneeId(queryVO.getAssigneeId()); |
| | | newQuery.setDeptId(queryVO.getDeptId()); |
| | | newQuery.setDeptIds(queryVO.getDeptIds()); |
| | | newQuery.setPlannedStartTimeBegin(queryVO.getPlannedStartTimeBegin()); |
| | | newQuery.setPlannedStartTimeEnd(queryVO.getPlannedStartTimeEnd()); |
| | | newQuery.setPlannedEndTimeBegin(queryVO.getPlannedEndTimeBegin()); |
| | | newQuery.setPlannedEndTimeEnd(queryVO.getPlannedEndTimeEnd()); |
| | | newQuery.setOverdue(queryVO.getOverdue()); |
| | | } |
| | | |
| | | // Get all tasks matching the other criteria |
| | | List<SysTask> allTasks = sysTaskMapper.selectSysTaskList(newQuery); |
| | | allTasks.stream().forEach(task -> { |
| | | if ("EMERGENCY_TRANSFER".equals(task.getTaskType())) { |
| | | SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(task.getTaskId()); |
| | | task.setEmergencyInfo(emergencyInfo); |
| | | } |
| | | }); |
| | | return allTasks.stream().filter(task -> { |
| | | if (task.getTaskCode() != null && task.getTaskCode().contains(taskCode)) { |
| | | return true; |
| | | } |
| | | if ("EMERGENCY_TRANSFER".equals(task.getTaskType()) && task.getEmergencyInfo() != null) { |
| | | String dispatchCode = task.getEmergencyInfo().getDispatchCode(); |
| | | String serviceCode = task.getEmergencyInfo().getServiceCode(); |
| | | return (dispatchCode != null && dispatchCode.contains(taskCode)) || |
| | | (serviceCode != null && serviceCode.contains(taskCode)); |
| | | } |
| | | return false; |
| | | |
| | | }).collect(Collectors.toList()); |
| | | |
| | | } |
| | | |
| | | /** |
| | |
| | | )); |
| | | } |
| | | |
| | | // 发布任务分配事件 |
| | | if (result > 0 && createVO.getAssignees() != null && !createVO.getAssignees().isEmpty()) { |
| | | this.sendTaskAssigneeEvent(createVO,task,SecurityUtils.getUserId(),SecurityUtils.getUsername()); |
| | | } |
| | | |
| | | |
| | | // 异步同步急救转运任务到旧系统 |
| | | if (result > 0 && "EMERGENCY_TRANSFER".equals(createVO.getTaskType()) && legacySystemSyncService != null) { |
| | |
| | | )); |
| | | } |
| | | |
| | | // 发布任务分配事件 |
| | | if (result > 0 && createVO.getAssignees() != null && !createVO.getAssignees().isEmpty()) { |
| | | this.sendTaskAssigneeEvent(createVO,task,userId,userName); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | |
| | | needResync = true; |
| | | } |
| | | } |
| | | |
| | | Long dispatchOrderId=0L; |
| | | // 更新急救转运扩展信息(检测地址和成交价变更) |
| | | if (result > 0 && "EMERGENCY_TRANSFER".equals(oldTask.getTaskType())) { |
| | | SysTaskEmergency oldEmergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(updateVO.getTaskId()); |
| | | sysEmergencyTaskService.updateEmergencyInfoFromUpdateVO(oldEmergency, updateVO, userName); |
| | | dispatchOrderId= oldEmergency.getLegacyDispatchOrdId(); |
| | | sysEmergencyTaskService.markNeedResyncIfNecessary(updateVO.getTaskId(), oldTask, updateVO, updateFromLegacy); |
| | | } |
| | | |
| | |
| | | userId, userName); |
| | | } |
| | | |
| | | if(result > 0 && oldTask.getTaskStatus().equals(TaskStatus.PENDING.getCode()) && updateVO.getAssignees() != null && !updateVO.getAssignees().isEmpty()){ |
| | | if(result > 0 && oldTask.getTaskStatus().equals(TaskStatus.PENDING.getCode()) && updateVO.getAssignees() != null && !updateVO.getAssignees().isEmpty() && dispatchOrderId>0L){ |
| | | |
| | | this.sendTaskAssigneeEvent(updateVO,oldTask,userId,userName); |
| | | } |
| | |
| | | // log.info("更新执行人员 ServiceOrdID:{},dispatchOrderId:{}",serviceOrderId,dispatchOrderId); |
| | | sysTaskAssigneeService.updateTaskAssignees(taskId, updateVO.getAssignees(), userName); |
| | | } |
| | | |
| | | Long dispatchOrderIdLong = 0L; |
| | | // 更新急救转运扩展信息 |
| | | if (result > 0) { |
| | | // 更新旧系统ID |
| | | if (serviceOrderId != null) { |
| | | taskEmergency.setLegacyServiceOrdId(Long.parseLong(serviceOrderId)); |
| | | } |
| | | taskEmergency.setLegacyServiceOrdId(Long.parseLong(serviceOrderId)); |
| | | if (dispatchOrderId != null) { |
| | | taskEmergency.setLegacyDispatchOrdId(Long.parseLong(dispatchOrderId)); |
| | | taskEmergency.setLegacyDispatchOrdId(Long.parseLong(dispatchOrderId)); |
| | | dispatchOrderIdLong = Long.parseLong(dispatchOrderId); |
| | | taskEmergency.setLegacyDispatchOrdId(dispatchOrderIdLong); |
| | | taskEmergency.setDispatchSyncStatus(2); |
| | | taskEmergency.setDispatchSyncTime(new Date()); |
| | | taskEmergency.setDispatchSyncErrorMsg("旧系统同步过来"); |
| | |
| | | taskEmergency.setUpdateTime(DateUtils.getNowDate()); |
| | | |
| | | Boolean hasEmergencyInfo = updateVO.getHospitalOut() != null || updateVO.getHospitalIn() != null || updateVO.getPatient() != null; |
| | | // log.info("更新转运任务信息 serviceOrdID:{},dispatchOrderId:{} hasEmergencyInfo:{}",serviceOrderId, |
| | | // dispatchOrderId,hasEmergencyInfo); |
| | | |
| | | |
| | | // 使用TaskCreateVO的字段来更新急救转运信息 |
| | | if (hasEmergencyInfo) { |
| | | sysEmergencyTaskService.updateEmergencyInfoFromCreateVO(taskEmergency, updateVO, userName); |
| | | } |
| | | SysTaskEmergency emergency= sysEmergencyTaskService.selectSysTaskEmergencyByTaskId(taskId); |
| | | dispatchOrderIdLong = emergency.getLegacyDispatchOrdId(); |
| | | } |
| | | |
| | | if(updateVO.getTaskStatus()!=null && updateVO.getTaskStatus().equals(TaskStatus.PENDING.getCode()) && updateVO.getAssignees()!=null && !updateVO.getAssignees().isEmpty()){ |
| | | if(updateVO.getTaskStatus()!=null && updateVO.getTaskStatus().equals(TaskStatus.PENDING.getCode()) && updateVO.getAssignees()!=null && !updateVO.getAssignees().isEmpty() && dispatchOrderIdLong>0L){ |
| | | this.sendTaskAssigneeEvent(updateVO,task,userId,userName); |
| | | } |
| | | |
| | |
| | | */ |
| | | @Override |
| | | public List<SysTask> selectMyTasks(Long userId) { |
| | | return sysTaskMapper.selectMyTasks(userId); |
| | | List<SysTask> list = sysTaskMapper.selectMyTasks(userId); |
| | | list.stream().forEach(task -> { |
| | | if(task.getTaskType().equals("EMERGENCY_TRANSFER")){ |
| | | task.setEmergencyInfo(sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(task.getTaskId())); |
| | | } |
| | | }); |
| | | return list; |
| | | } |
| | | |
| | | /** |
| | |
| | | { |
| | | existingUser.setCanViewAllConsult(dto.getCanViewAllConsult()); |
| | | } |
| | | // 同步企业微信用户ID |
| | | if (StringUtils.isNotEmpty(dto.getOaWeixinUserId())) |
| | | { |
| | | existingUser.setQyWechatUserId(dto.getOaWeixinUserId()); |
| | | existingUser.setQyWechatUpdateTime(new Date()); |
| | | } |
| | | sysUserMapper.updateUser(existingUser); |
| | | } |
| | | |
| | |
| | | newUser.setCanViewAllConsult(dto.getCanViewAllConsult()); |
| | | } |
| | | |
| | | // 设置企业微信用户ID |
| | | if (StringUtils.isNotEmpty(dto.getOaWeixinUserId())) |
| | | { |
| | | newUser.setQyWechatUserId(dto.getOaWeixinUserId()); |
| | | newUser.setQyWechatUpdateTime(new Date()); |
| | | } |
| | | |
| | | if (deptId != null) |
| | | { |
| | | newUser.setDeptId(deptId); |
| | |
| | | <result property="ServiceOrdTraDistance" column="ServiceOrdTraDistance" /> |
| | | <result property="ServiceOrdApptDate" column="ServiceOrdApptDate" /> |
| | | <result property="DispatchOrdState" column="DispatchOrdState" /> |
| | | <result property="DispatchOrdNo" column="DispatchOrdNo" /> |
| | | <result property="DispatchOrdClass" column="DispatchOrdClass" /> |
| | | <result property="DispatchOrd_NS_Time" column="DispatchOrd_NS_Time" /> |
| | | |
| | | </resultMap> |
| | | |
| | | <!-- 执行人结果映射 --> |
| | |
| | | b.DispatchOrdCarID, |
| | | a.ServiceOrdPtServices, |
| | | a.ServiceOrdPtInServices, |
| | | a.ServiceOrdPtName |
| | | a.ServiceOrdPtName, |
| | | b.DispatchOrdState, |
| | | b.DispatchOrdNo, |
| | | b.DispatchOrdClass, |
| | | a.ServiceOrdClass |
| | | FROM ServiceOrder as a |
| | | left JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt |
| | | WHERE a.ServiceOrdState <= 3 |
| | |
| | | a.ServiceOrdApptDate, |
| | | a.ServiceOrdUserID, |
| | | a.ServiceOrd_NS_ID, |
| | | a.ServiceOrd_NS_Time, |
| | | a.ServiceOrd_CC_ID, |
| | | a.ServiceOrd_CC_Time, |
| | | a.ServiceOrdAreaType, |
| | |
| | | a.ServiceOrdPtServices, |
| | | a.ServiceOrdPtInServices, |
| | | a.ServiceOrdPtName, |
| | | b.DispatchOrdState |
| | | b.DispatchOrdState, |
| | | b.DispatchOrdNo, |
| | | b.DispatchOrdClass, |
| | | a.ServiceOrdClass |
| | | |
| | | FROM ServiceOrder as a |
| | | left JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt |
| | | WHERE a.ServiceOrdID = #{serviceOrdID} |
| | | WHERE a.ServiceOrdID = #{serviceOrdID} |
| | | AND (b.DispatchOrdID = #{dispatchOrdID} OR #{dispatchOrdID} IS NULL) |
| | | AND a.ServiceOrdState <=3 |
| | | |
| | | </select> |
| | | <select id="selectByServiceOrdId" resultMap="TransferOrderResult"> |
| | | SELECT |
| | | a.ServiceOrdID, |
| | | a.Old_ServiceOrdID_TXT, |
| | | a.ServiceOrdTraVia, |
| | | a.ServiceOrdNo, |
| | | a.ServiceOrdApptDate, |
| | | a.ServiceOrdUserID, |
| | | a.ServiceOrd_NS_ID, |
| | | a.ServiceOrd_NS_Time, |
| | | a.ServiceOrd_CC_ID, |
| | | a.ServiceOrd_CC_Time, |
| | | a.ServiceOrdAreaType, |
| | | a.ServiceOrdType, |
| | | a.ServiceOrdPtSex, |
| | | a.ServiceOrdTraTxnPrice, |
| | | a.ServiceOrdPtOutHospID, |
| | | a.ServiceOrdPtServicesID, |
| | | a.ServiceOrdPtInHospID, |
| | | a.ServiceOrdPtInServicesID, |
| | | a.ServiceOrdCoTies, |
| | | a.ServiceOrdCoName, |
| | | a.ServiceOrdTraDistance, |
| | | a.ServiceOrdCoPhone, |
| | | a.ServiceOrdClass, |
| | | a.ServiceOrdTraStreet, |
| | | a.ServiceOrdTraEnd, |
| | | a.ServiceOrdPtCondition, |
| | | b.DispatchOrd_NS_Time, |
| | | a.ServiceOrdState, |
| | | a.ServiceOrdPtIDCard, |
| | | b.DispatchOrdTraStreet, |
| | | b.DispatchOrdStartDate, |
| | | b.DispatchOrdTraEnd, |
| | | b.DispatchOrdID, |
| | | b.DispatchOrdCarID, |
| | | a.ServiceOrdPtServices, |
| | | a.ServiceOrdPtInServices, |
| | | a.ServiceOrdPtName, |
| | | b.DispatchOrdState, |
| | | b.DispatchOrdNo, |
| | | b.DispatchOrdClass, |
| | | a.ServiceOrdClass |
| | | |
| | | FROM ServiceOrder as a |
| | | left JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt |
| | | WHERE a.ServiceOrdID = #{serviceOrdID} |
| | | </select> |
| | | <select id="selectByDispatchId" resultMap="TransferOrderResult"> |
| | | SELECT |
| | | a.ServiceOrdID, |
| | | a.Old_ServiceOrdID_TXT, |
| | | a.ServiceOrdTraVia, |
| | | a.ServiceOrdNo, |
| | | a.ServiceOrdApptDate, |
| | | a.ServiceOrdUserID, |
| | | a.ServiceOrd_NS_ID, |
| | | a.ServiceOrd_NS_Time, |
| | | a.ServiceOrd_CC_ID, |
| | | a.ServiceOrd_CC_Time, |
| | | a.ServiceOrdAreaType, |
| | | a.ServiceOrdType, |
| | | a.ServiceOrdPtSex, |
| | | a.ServiceOrdTraTxnPrice, |
| | | a.ServiceOrdPtOutHospID, |
| | | a.ServiceOrdPtServicesID, |
| | | a.ServiceOrdPtInHospID, |
| | | a.ServiceOrdPtInServicesID, |
| | | a.ServiceOrdCoTies, |
| | | a.ServiceOrdCoName, |
| | | a.ServiceOrdTraDistance, |
| | | a.ServiceOrdCoPhone, |
| | | a.ServiceOrdClass, |
| | | a.ServiceOrdTraStreet, |
| | | a.ServiceOrdTraEnd, |
| | | a.ServiceOrdPtCondition, |
| | | b.DispatchOrd_NS_Time, |
| | | a.ServiceOrdState, |
| | | a.ServiceOrdPtIDCard, |
| | | b.DispatchOrdTraStreet, |
| | | b.DispatchOrdStartDate, |
| | | b.DispatchOrdTraEnd, |
| | | b.DispatchOrdID, |
| | | b.DispatchOrdCarID, |
| | | a.ServiceOrdPtServices, |
| | | a.ServiceOrdPtInServices, |
| | | a.ServiceOrdPtName, |
| | | b.DispatchOrdState, |
| | | b.DispatchOrdNo, |
| | | b.DispatchOrdClass, |
| | | a.ServiceOrdClass |
| | | |
| | | FROM ServiceOrder as a |
| | | left JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt |
| | | WHERE b.DispatchOrdID = #{dispatchId} |
| | | </select> |
| | | |
| | | |
| | | <!-- 根据服务单ID查询病情信息 --> |
| | | <select id="selectDiseaseIdsByServiceOrdID" resultType="String"> |
| | |
| | | <result property="notifyType" column="notify_type" /> |
| | | <result property="channel" column="channel" /> |
| | | <result property="sendStatus" column="send_status" /> |
| | | <result property="sendContent" column="send_content" /> |
| | | <result property="sendTime" column="send_time" /> |
| | | <result property="sendResult" column="send_result" /> |
| | | <result property="responseMsg" column="response_msg" /> |
| | |
| | | |
| | | <sql id="selectNotifySendLogVo"> |
| | | select id, notify_task_id, task_id, user_id, user_name, notify_type, channel, send_status, |
| | | send_time, send_result, response_msg, retry_count, create_time, create_by, |
| | | send_content, send_time, send_result, response_msg, retry_count, create_time, create_by, |
| | | update_time, update_by, remark |
| | | from sys_notify_send_log |
| | | </sql> |
| | |
| | | <if test="notifyType != null and notifyType != ''">notify_type,</if> |
| | | <if test="channel != null and channel != ''">channel,</if> |
| | | <if test="sendStatus != null">send_status,</if> |
| | | <if test="sendContent != null">send_content,</if> |
| | | <if test="sendTime != null">send_time,</if> |
| | | <if test="sendResult != null">send_result,</if> |
| | | <if test="responseMsg != null">response_msg,</if> |
| | |
| | | <if test="notifyType != null and notifyType != ''">#{notifyType},</if> |
| | | <if test="channel != null and channel != ''">#{channel},</if> |
| | | <if test="sendStatus != null">#{sendStatus},</if> |
| | | <if test="sendContent != null">#{sendContent},</if> |
| | | <if test="sendTime != null">#{sendTime},</if> |
| | | <if test="sendResult != null">#{sendResult},</if> |
| | | <if test="responseMsg != null">#{responseMsg},</if> |
| | |
| | | <if test="notifyType != null and notifyType != ''">notify_type = #{notifyType},</if> |
| | | <if test="channel != null and channel != ''">channel = #{channel},</if> |
| | | <if test="sendStatus != null">send_status = #{sendStatus},</if> |
| | | <if test="sendContent != null">send_content = #{sendContent},</if> |
| | | <if test="sendTime != null">send_time = #{sendTime},</if> |
| | | <if test="sendResult != null">send_result = #{sendResult},</if> |
| | | <if test="retryCount != null">retry_count = #{retryCount},</if> |
| | |
| | | update sys_notify_send_log |
| | | set send_status = #{sendStatus}, |
| | | send_result = #{sendResult}, |
| | | send_content = #{sendContent}, |
| | | send_time = now(), |
| | | update_time = now(), |
| | | retry_count = retry_count + 1 |
| | |
| | | <result property="dispatchSyncErrorMsg" column="dispatch_sync_error_msg" /> |
| | | <result property="needResync" column="need_resync" /> |
| | | <result property="legacyServiceOrdNo" column="legacy_service_ord_no" /> |
| | | <result property="legacyDispatchOrdNo" column="legacy_dispatch_ord_no" /> |
| | | <result property="legacyServiceNsTime" column="legacy_service_ns_time" /> |
| | | <result property="legacyDispatchNsTime" column="legacy_dispatch_ns_time" /> |
| | | <result property="legacyDispatchOrdClass" column="legacy_dispatch_ord_class" /> |
| | | <result property="legacyServiceOrdClass" column="legacy_service_ord_class" /> |
| | | <result property="createTime" column="create_time" /> |
| | | <result property="updateTime" column="update_time" /> |
| | | <result property="createBy" column="create_by" /> |
| | |
| | | hospital_in_department_id, hospital_in_bed_number, hospital_in_address, hospital_in_longitude, |
| | | hospital_in_latitude, transfer_distance, transfer_price, passenger_contact, |
| | | passenger_phone, disease_ids, document_type_id, task_type_id, legacy_service_ord_id, legacy_dispatch_ord_id, |
| | | sync_status, sync_time, sync_error_msg, dispatch_sync_status, dispatch_sync_time, dispatch_sync_error_msg, need_resync, legacy_service_ord_no, |
| | | sync_status, sync_time, sync_error_msg, dispatch_sync_status, dispatch_sync_time, dispatch_sync_error_msg, need_resync, legacy_service_ord_no, legacy_dispatch_ord_no, legacy_service_ns_time, legacy_dispatch_ns_time, legacy_dispatch_ord_class, legacy_service_ord_class, |
| | | create_time, update_time, create_by, update_by |
| | | from sys_task_emergency |
| | | </sql> |
| | |
| | | <if test="dispatchSyncErrorMsg != null">dispatch_sync_error_msg,</if> |
| | | <if test="needResync != null">need_resync,</if> |
| | | <if test="legacyServiceOrdNo != null">legacy_service_ord_no,</if> |
| | | <if test="legacyDispatchOrdNo != null">legacy_dispatch_ord_no,</if> |
| | | <if test="legacyServiceNsTime != null">legacy_service_ns_time,</if> |
| | | <if test="legacyDispatchNsTime != null">legacy_dispatch_ns_time,</if> |
| | | <if test="legacyDispatchOrdClass != null">legacy_dispatch_ord_class,</if> |
| | | <if test="legacyServiceOrdClass != null">legacy_service_ord_class,</if> |
| | | <if test="createTime != null">create_time,</if> |
| | | <if test="updateTime != null">update_time,</if> |
| | | <if test="createBy != null">create_by,</if> |
| | |
| | | <if test="dispatchSyncErrorMsg != null">#{dispatchSyncErrorMsg},</if> |
| | | <if test="needResync != null">#{needResync},</if> |
| | | <if test="legacyServiceOrdNo != null">#{legacyServiceOrdNo},</if> |
| | | <if test="legacyDispatchOrdNo != null">#{legacyDispatchOrdNo},</if> |
| | | <if test="legacyServiceNsTime != null">#{legacyServiceNsTime},</if> |
| | | <if test="legacyDispatchNsTime != null">#{legacyDispatchNsTime},</if> |
| | | <if test="legacyDispatchOrdClass != null">#{legacyDispatchOrdClass},</if> |
| | | <if test="legacyServiceOrdClass != null">#{legacyServiceOrdClass},</if> |
| | | <if test="createTime != null">#{createTime},</if> |
| | | <if test="updateTime != null">#{updateTime},</if> |
| | | <if test="createBy != null">#{createBy},</if> |
| | |
| | | <if test="dispatchSyncErrorMsg != null">dispatch_sync_error_msg = #{dispatchSyncErrorMsg},</if> |
| | | <if test="needResync != null">need_resync = #{needResync},</if> |
| | | <if test="legacyServiceOrdNo != null">legacy_service_ord_no = #{legacyServiceOrdNo},</if> |
| | | <if test="legacyDispatchOrdNo != null">legacy_dispatch_ord_no = #{legacyDispatchOrdNo},</if> |
| | | <if test="legacyServiceNsTime != null">legacy_service_ns_time = #{legacyServiceNsTime},</if> |
| | | <if test="legacyDispatchNsTime != null">legacy_dispatch_ns_time = #{legacyDispatchNsTime},</if> |
| | | <if test="legacyDispatchOrdClass != null">legacy_dispatch_ord_class = #{legacyDispatchOrdClass},</if> |
| | | <if test="legacyServiceOrdClass != null">legacy_service_ord_class = #{legacyServiceOrdClass},</if> |
| | | <if test="updateTime != null">update_time = #{updateTime},</if> |
| | | <if test="updateBy != null">update_by = #{updateBy},</if> |
| | | </trim> |
| | |
| | | <result property="openId" column="open_id" /> |
| | | <result property="unionId" column="union_id" /> |
| | | <result property="wechatNickname" column="wechat_nickname" /> |
| | | <result property="qyWechatUserId" column="qy_wechat_user_id" /> |
| | | <result property="qyWechatUpdateTime" column="qy_wechat_update_time" /> |
| | | <result property="canViewAllConsult" column="can_view_all_consult" /> |
| | | <association property="dept" javaType="SysDept" resultMap="deptResult" /> |
| | | <collection property="roles" javaType="java.util.List" resultMap="RoleResult" /> |
| | |
| | | </resultMap> |
| | | |
| | | <sql id="selectUserVo"> |
| | | select u.user_id, u.dept_id, u.user_name,u.oa_user_id, u.oa_order_class, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.oa_user_id, u.create_by, u.create_time, u.remark,u.open_id,u.union_id,u.wechat_nickname,u.can_view_all_consult, |
| | | select u.user_id, u.dept_id, u.user_name,u.oa_user_id, u.oa_order_class, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.oa_user_id, u.create_by, u.create_time, u.remark,u.open_id,u.union_id,u.wechat_nickname,u.qy_wechat_user_id,u.qy_wechat_update_time,u.can_view_all_consult, |
| | | d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status, |
| | | r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status |
| | | from sys_user u |
| | |
| | | <if test="status != null and status != ''">status,</if> |
| | | <if test="oaUserId != null">oa_user_id,</if> |
| | | <if test="oaOrderClass != null and oaOrderClass != ''">oa_order_class,</if> |
| | | <if test="canViewAllConsult != null and canViewAllConsult != ''">can_view_all_consult,</if> |
| | | <if test="qyWechatUserId != null and qyWechatUserId != ''">qy_wechat_user_id,</if> |
| | | <if test="qyWechatUpdateTime != null">qy_wechat_update_time,</if> |
| | | <if test="createBy != null and createBy != ''">create_by,</if> |
| | | <if test="remark != null and remark != ''">remark,</if> |
| | | create_time |
| | |
| | | <if test="oaUserId != null">#{oaUserId},</if> |
| | | <if test="oaOrderClass != null and oaOrderClass != ''">#{oaOrderClass},</if> |
| | | <if test="canViewAllConsult != null and canViewAllConsult != ''">#{canViewAllConsult},</if> |
| | | <if test="qyWechatUserId != null and qyWechatUserId != ''">#{qyWechatUserId},</if> |
| | | <if test="qyWechatUpdateTime != null">#{qyWechatUpdateTime},</if> |
| | | <if test="createBy != null and createBy != ''">#{createBy},</if> |
| | | <if test="remark != null and remark != ''">#{remark},</if> |
| | | sysdate() |
| | |
| | | <if test="oaUserId != null">oa_user_id = #{oaUserId},</if> |
| | | <if test="oaOrderClass != null">oa_order_class = #{oaOrderClass},</if> |
| | | <if test="canViewAllConsult != null and canViewAllConsult != ''">can_view_all_consult = #{canViewAllConsult},</if> |
| | | <if test="qyWechatUserId != null and qyWechatUserId != ''">qy_wechat_user_id = #{qyWechatUserId},</if> |
| | | <if test="qyWechatUpdateTime != null">qy_wechat_update_time = #{qyWechatUpdateTime},</if> |
| | | <if test="openId != null and openId != ''">open_id = #{openId},</if> |
| | | <if test="unionId != null and unionId != ''">union_id = #{unionId},</if> |
| | | <if test="loginIp != null and loginIp != ''">login_ip = #{loginIp},</if> |
| | |
| | | |
| | | <resultMap type="UserSyncDTO" id="UserSyncResult"> |
| | | <result property="oaUserId" column="OA_UserID" /> |
| | | <result property="oaWeixinUserId" column="OA_weixinUserID" /> |
| | | <result property="userName" column="user_name" /> |
| | | <result property="nickName" column="nick_name" /> |
| | | <result property="departmentId" column="department_id" /> |
| | |
| | | <![CDATA[ |
| | | SELECT |
| | | OA_User_ID AS OA_UserID, |
| | | OA_weixinUserID AS OA_weixinUserID, |
| | | OA_User AS user_name, |
| | | OA_Name AS nick_name, |
| | | OA_departmentID AS department_id, |
| New file |
| | |
| | | import request from '@/utils/request' |
| | | |
| | | // 获取企业微信AccessToken |
| | | export function getToken() { |
| | | return request({ |
| | | url: '/system/qywechat/test/token', |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // 刷新企业微信AccessToken |
| | | export function refreshToken() { |
| | | return request({ |
| | | url: '/system/qywechat/test/refreshToken', |
| | | method: 'post' |
| | | }) |
| | | } |
| | | |
| | | // 发送企业微信通知消息 |
| | | export function sendMessage(data) { |
| | | return request({ |
| | | url: '/system/qywechat/test/sendMessage', |
| | | method: 'post', |
| | | params: data |
| | | }) |
| | | } |
| | | |
| | | // 发送企业微信文本消息 |
| | | export function sendTextMessage(data) { |
| | | return request({ |
| | | url: '/system/qywechat/test/sendTextMessage', |
| | | method: 'post', |
| | | params: data |
| | | }) |
| | | } |
| | | |
| | | // 检查企业微信服务状态 |
| | | export function checkServiceStatus() { |
| | | return request({ |
| | | url: '/system/qywechat/test/enabled', |
| | | method: 'get' |
| | | }) |
| | | } |
| | |
| | | <el-option label="短信" value="SMS" /> |
| | | <el-option label="站内消息" value="SITE_MSG" /> |
| | | <el-option label="APP推送" value="APP_PUSH" /> |
| | | <el-option label="企业微信" value="QY_WECHAT" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="是否启用" prop="enabled"> |
| | |
| | | <span>{{ parseTime(scope.row.sendTime) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="发送内容" align="center" prop="sendContent" show-overflow-tooltip /> |
| | | <el-table-column label="发送结果" align="center" prop="sendResult" show-overflow-tooltip /> |
| | | <el-table-column label="重试次数" align="center" prop="retryCount" /> |
| | | <el-table-column label="创建时间" align="center" prop="createTime" width="180"> |
| | |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="发送内容:"> |
| | | <el-input |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="发送内容" |
| | | v-model="form.sendContent" |
| | | readonly> |
| | | </el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="响应消息:">{{ form.responseMsg }}</el-form-item> |
| | | </el-col> |
| | | </el-row> |
| New file |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <h1>企业微信测试页面</h1> |
| | | <p>这是一个测试页面,用于验证企业微信功能。</p> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | // 简单测试导入 |
| | | import * as qywechatApi from '@/api/system/qywechat/index' |
| | | |
| | | export default { |
| | | name: 'QyWechatIndex', |
| | | mounted() { |
| | | console.log('企业微信API导入测试:', qywechatApi) |
| | | } |
| | | } |
| | | </script> |
| New file |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-card class="box-card"> |
| | | <div slot="header" class="clearfix"> |
| | | <span>企业微信功能测试</span> |
| | | </div> |
| | | |
| | | <el-tabs v-model="activeTab"> |
| | | <!-- AccessToken测试 --> |
| | | <el-tab-pane label="AccessToken测试" name="token"> |
| | | <el-form ref="tokenForm" :model="tokenForm" label-width="120px"> |
| | | <el-form-item label="CorpID"> |
| | | <el-input v-model="tokenForm.corpId" placeholder="请输入企业微信CorpID" /> |
| | | </el-form-item> |
| | | <el-form-item label="CorpSecret"> |
| | | <el-input v-model="tokenForm.corpSecret" placeholder="请输入企业微信CorpSecret" show-password /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="getToken">获取AccessToken</el-button> |
| | | <el-button type="success" @click="refreshToken">刷新AccessToken</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <el-divider /> |
| | | |
| | | <div v-if="tokenResult"> |
| | | <h4>测试结果:</h4> |
| | | <pre>{{ tokenResult }}</pre> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <!-- 消息发送测试 --> |
| | | <el-tab-pane label="消息发送测试" name="message"> |
| | | <el-form ref="messageForm" :model="messageForm" label-width="120px"> |
| | | <el-form-item label="用户ID"> |
| | | <el-input v-model="messageForm.userId" placeholder="请输入系统用户ID" /> |
| | | </el-form-item> |
| | | <el-form-item label="企业微信用户ID"> |
| | | <el-input v-model="messageForm.qyUserId" placeholder="请输入企业微信用户ID" /> |
| | | </el-form-item> |
| | | <el-form-item label="消息标题"> |
| | | <el-input v-model="messageForm.title" placeholder="请输入消息标题" /> |
| | | </el-form-item> |
| | | <el-form-item label="消息内容"> |
| | | <el-input v-model="messageForm.content" type="textarea" :rows="4" placeholder="请输入消息内容" /> |
| | | </el-form-item> |
| | | <el-form-item label="通知链接"> |
| | | <el-input v-model="messageForm.notifyUrl" placeholder="请输入通知链接" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="sendMessage">发送通知消息</el-button> |
| | | <el-button type="success" @click="sendTextMessage">发送文本消息</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <el-divider /> |
| | | |
| | | <div v-if="messageResult"> |
| | | <h4>测试结果:</h4> |
| | | <pre>{{ messageResult }}</pre> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <!-- 服务状态检查 --> |
| | | <el-tab-pane label="服务状态检查" name="status"> |
| | | <el-button type="primary" @click="checkServiceStatus">检查服务状态</el-button> |
| | | |
| | | <el-divider /> |
| | | |
| | | <div v-if="statusResult"> |
| | | <h4>服务状态:</h4> |
| | | <el-tag :type="statusResult.enabled ? 'success' : 'danger'"> |
| | | {{ statusResult.enabled ? '已启用' : '已禁用' }} |
| | | </el-tag> |
| | | <p v-if="statusResult.message">{{ statusResult.message }}</p> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getToken, refreshToken, sendMessage, sendTextMessage, checkServiceStatus } from '@/api/system/qywechat/index' |
| | | |
| | | export default { |
| | | name: 'QyWechatTest', |
| | | data() { |
| | | return { |
| | | activeTab: 'token', |
| | | tokenForm: { |
| | | corpId: 'wx248505bfbab6d0c1', |
| | | corpSecret: '2MCilqWYC0FWjOQ894sbb-s7Lb5sVH4HHuJgOsd9l1k' |
| | | }, |
| | | messageForm: { |
| | | userId: '', |
| | | qyUserId: '', |
| | | title: '测试消息标题', |
| | | content: '这是一条测试消息内容', |
| | | notifyUrl: 'https://www.example.com' |
| | | }, |
| | | tokenResult: null, |
| | | messageResult: null, |
| | | statusResult: null |
| | | } |
| | | }, |
| | | methods: { |
| | | // 获取AccessToken |
| | | async getToken() { |
| | | try { |
| | | const response = await getToken() |
| | | this.tokenResult = JSON.stringify(response, null, 2) |
| | | this.$message.success('获取AccessToken成功') |
| | | } catch (error) { |
| | | this.tokenResult = error.message || '获取AccessToken失败' |
| | | this.$message.error('获取AccessToken失败: ' + (error.message || '未知错误')) |
| | | } |
| | | }, |
| | | |
| | | // 刷新AccessToken |
| | | async refreshToken() { |
| | | try { |
| | | const response = await refreshToken() |
| | | this.tokenResult = JSON.stringify(response, null, 2) |
| | | this.$message.success('刷新AccessToken成功') |
| | | } catch (error) { |
| | | this.tokenResult = error.message || '刷新AccessToken失败' |
| | | this.$message.error('刷新AccessToken失败: ' + (error.message || '未知错误')) |
| | | } |
| | | }, |
| | | |
| | | // 发送通知消息 |
| | | async sendMessage() { |
| | | if (!this.messageForm.userId) { |
| | | this.$message.warning('请输入用户ID') |
| | | return |
| | | } |
| | | if (!this.messageForm.title) { |
| | | this.$message.warning('请输入消息标题') |
| | | return |
| | | } |
| | | if (!this.messageForm.content) { |
| | | this.$message.warning('请输入消息内容') |
| | | return |
| | | } |
| | | |
| | | try { |
| | | const params = { |
| | | userId: this.messageForm.userId, |
| | | title: this.messageForm.title, |
| | | content: this.messageForm.content |
| | | } |
| | | const response = await sendMessage(params) |
| | | this.messageResult = JSON.stringify(response, null, 2) |
| | | this.$message.success('发送通知消息成功') |
| | | } catch (error) { |
| | | this.messageResult = error.message || '发送通知消息失败' |
| | | this.$message.error('发送通知消息失败: ' + (error.message || '未知错误')) |
| | | } |
| | | }, |
| | | |
| | | // 发送文本消息 |
| | | async sendTextMessage() { |
| | | if (!this.messageForm.qyUserId) { |
| | | this.$message.warning('请输入企业微信用户ID') |
| | | return |
| | | } |
| | | if (!this.messageForm.content) { |
| | | this.$message.warning('请输入消息内容') |
| | | return |
| | | } |
| | | |
| | | try { |
| | | const params = { |
| | | qyUserId: this.messageForm.qyUserId, |
| | | title: this.messageForm.title || '测试消息', |
| | | content: this.messageForm.content, |
| | | notifyUrl: this.messageForm.notifyUrl |
| | | } |
| | | const response = await sendTextMessage(params) |
| | | this.messageResult = JSON.stringify(response, null, 2) |
| | | this.$message.success('发送文本消息成功') |
| | | } catch (error) { |
| | | this.messageResult = error.message || '发送文本消息失败' |
| | | this.$message.error('发送文本消息失败: ' + (error.message || '未知错误')) |
| | | } |
| | | }, |
| | | |
| | | // 检查服务状态 |
| | | async checkServiceStatus() { |
| | | try { |
| | | const response = await checkServiceStatus() |
| | | this.statusResult = { |
| | | enabled: response.data, |
| | | message: response.msg |
| | | } |
| | | this.$message.success('检查服务状态成功') |
| | | } catch (error) { |
| | | this.statusResult = { |
| | | enabled: false, |
| | | message: error.message || '检查服务状态失败' |
| | | } |
| | | this.$message.error('检查服务状态失败: ' + (error.message || '未知错误')) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .box-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .el-divider { |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | pre { |
| | | background-color: #f5f5f5; |
| | | padding: 10px; |
| | | border-radius: 4px; |
| | | white-space: pre-wrap; |
| | | word-wrap: break-word; |
| | | } |
| | | </style> |
| | |
| | | |
| | | <!-- 基本信息 --> |
| | | <el-descriptions title="基本信息" :column="2" border> |
| | | <el-descriptions-item label="任务编号">{{ taskDetail.taskCode }}</el-descriptions-item> |
| | | <el-descriptions-item label="任务编号">{{ taskDetail.showTaskCode }}</el-descriptions-item> |
| | | <el-descriptions-item label="任务类型"> |
| | | <dict-tag :options="dict.type.sys_task_type" :value="taskDetail.taskType"/> |
| | | </el-descriptions-item> |
| | |
| | | </span> |
| | | <span v-else style="color: #C0C4CC;">--</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="服务单编码"> |
| | | <span v-if="taskDetail.emergencyInfo.serviceCode"> |
| | | <el-tag type="success" size="small">{{ taskDetail.emergencyInfo.serviceCode }}</el-tag> |
| | | </span> |
| | | <span v-else style="color: #C0C4CC;">--</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="服务单同步时间"> |
| | | <span v-if="taskDetail.emergencyInfo.syncTime">{{ parseTime(taskDetail.emergencyInfo.syncTime) }}</span> |
| | | <span v-else style="color: #C0C4CC;">--</span> |
| | |
| | | <el-descriptions-item label="调度单号"> |
| | | <span v-if="taskDetail.emergencyInfo.legacyDispatchOrdId"> |
| | | <el-tag type="primary" size="small">{{ taskDetail.emergencyInfo.legacyDispatchOrdId }}</el-tag> |
| | | </span> |
| | | <span v-else style="color: #C0C4CC;">--</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="调度单编码"> |
| | | <span v-if="taskDetail.emergencyInfo.dispatchCode"> |
| | | <el-tag type="success" size="small">{{ taskDetail.emergencyInfo.dispatchCode }}</el-tag> |
| | | </span> |
| | | <span v-else style="color: #C0C4CC;">--</span> |
| | | </el-descriptions-item> |
| | |
| | | </el-descriptions> |
| | | |
| | | <!-- 操作按钮 --> |
| | | <div style="margin-top: 20px; text-align: center;"> |
| | | <!-- <div style="margin-top: 20px; text-align: center;"> |
| | | <el-button type="primary" @click="handleEdit" v-hasPermi="['task:general:edit']">编辑任务</el-button> |
| | | <el-button type="success" @click="handleAssign" v-hasPermi="['task:general:assign']">分配任务</el-button> |
| | | <el-button type="warning" @click="handleStatusChange" v-hasPermi="['task:general:status']">状态变更</el-button> |
| | | <el-button type="info" @click="handleVehicleAssign" v-hasPermi="['task:general:assign']">分配车辆</el-button> |
| | | </div> |
| | | </div> --> |
| | | </el-card> |
| | | |
| | | <!-- 执行人员列表 --> |
| | |
| | | |
| | | <el-table v-loading="loading" :data="taskList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="任务编号" align="center" prop="taskCode" min-width="180"> |
| | | <el-table-column label="任务编号" align="center" prop="showTaskCode" min-width="120"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | type="text" |
| | | @click="handleView(scope.row)" |
| | | v-hasPermi="['task:general:query']" |
| | | style="font-family: 'Courier New', monospace; font-size: 13px;" |
| | | >{{ scope.row.taskCode }}</el-button> |
| | | >{{ scope.row.showTaskCode }}</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="任务类型" align="center" prop="taskType" width="120"> |
| | | <template slot-scope="scope"> |
| | | <dict-tag :options="dict.type.sys_task_type" :value="scope.row.taskType"/> |
| | | <el-tag v-if="scope.row.taskType === 'EMERGENCY_TRANSFER'" type="danger" size="mini" style="margin-left: 5px;"> |
| | | <i class="el-icon-warning"></i> |
| | | </el-tag> |
| | | |
| | | </template> |
| | | </el-table-column> |
| | | |
| | |
| | | <span v-else style="color: #C0C4CC;">--</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="出发地址" align="center" prop="departureAddress" show-overflow-tooltip /> |
| | | <el-table-column label="目的地址" align="center" prop="destinationAddress" show-overflow-tooltip /> |
| | | |
| | | <!-- <el-table-column label="目的地址" align="center" prop="destinationAddress" show-overflow-tooltip /> --> |
| | | <el-table-column label="预计公里数" align="center" prop="estimatedDistance" width="120"> |
| | | <template slot-scope="scope"> |
| | | <span v-if="scope.row.estimatedDistance">{{ scope.row.estimatedDistance }} km</span> |
| | |
| | | |
| | | |
| | | <el-table-column label="创建人" align="center" prop="creatorName" /> |
| | | <el-table-column label="执行人" align="center" prop="assigneeName" /> |
| | | |
| | | <el-table-column label="创建时间" align="center" prop="createTime" width="180"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span> |
| | |
| | | @click="handleView(scope.row)" |
| | | v-hasPermi="['task:general:query']" |
| | | >查看</el-button> |
| | | <el-button |
| | | <!-- <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-edit" |
| | | @click="handleUpdate(scope.row)" |
| | | v-hasPermi="['task:general:edit']" |
| | | >修改</el-button> |
| | | <el-button |
| | | >修改</el-button> --> |
| | | <!-- <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-user" |
| | | @click="handleAssign(scope.row)" |
| | | v-hasPermi="['task:general:assign']" |
| | | >分配</el-button> |
| | | <el-button |
| | | >分配</el-button> --> |
| | | <!-- <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-refresh" |
| | | @click="handleStatusChange(scope.row)" |
| | | v-hasPermi="['task:general:status']" |
| | | >状态</el-button> |
| | | >状态</el-button> --> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| New file |
| | |
| | | -- 在sys_user表中添加qy_wechat_user_id字段,用于记录企业微信用户ID |
| | | -- 该字段用于企业微信消息推送功能 |
| | | |
| | | -- 添加qy_wechat_user_id字段 |
| | | ALTER TABLE sys_user ADD COLUMN qy_wechat_user_id VARCHAR(100) NULL COMMENT '企业微信用户ID'; |
| | | |
| | | -- 为qy_wechat_user_id字段创建索引,提高查询效率 |
| | | CREATE INDEX idx_qy_wechat_user_id ON sys_user(qy_wechat_user_id); |
| | | |
| | | -- 添加更新时间字段,记录企业微信用户ID的最后更新时间 |
| | | ALTER TABLE sys_user ADD COLUMN qy_wechat_update_time datetime NULL COMMENT '企业微信用户ID更新时间'; |
| | |
| | | (1, '微信订阅消息', 'WECHAT', 'sys_notify_channel', '', 'primary', 'Y', '0', 'admin', SYSDATE(), '微信订阅消息'), |
| | | (2, '短信', 'SMS', 'sys_notify_channel', '', 'success', 'N', '0', 'admin', SYSDATE(), '短信'), |
| | | (3, '站内消息', 'SITE_MSG', 'sys_notify_channel', '', 'info', 'N', '0', 'admin', SYSDATE(), '站内消息'), |
| | | (4, 'APP推送', 'APP_PUSH', 'sys_notify_channel', '', 'warning', 'N', '0', 'admin', SYSDATE(), 'APP推送'); |
| | | (4, 'APP推送', 'APP_PUSH', 'sys_notify_channel', '', 'warning', 'N', '0', 'admin', SYSDATE(), 'APP推送'), |
| | | (5, '企业微信', 'QY_WECHAT', 'sys_notify_channel', '', 'primary', 'N', '0', 'admin', SYSDATE(), '企业微信'); |
| | | |
| | | -- 4. 通知发送状态字典 |
| | | INSERT INTO sys_dict_type(dict_name, dict_type, status, create_by, create_time, remark) |
| | |
| | | ('渠道配置查询', @channelConfigParentId, 1, '#', '', 1, 0, 'F', '0', '0', 'system:notify:channel:config:query', '#', 'admin', SYSDATE(), '', NULL, ''), |
| | | ('渠道配置新增', @channelConfigParentId, 2, '#', '', 1, 0, 'F', '0', '0', 'system:notify:channel:config:add', '#', 'admin', SYSDATE(), '', NULL, ''), |
| | | ('渠道配置修改', @channelConfigParentId, 3, '#', '', 1, 0, 'F', '0', '0', 'system:notify:channel:config:edit', '#', 'admin', SYSDATE(), '', NULL, ''), |
| | | ('渠道配置删除', @channelConfigParentId, 4, '#', '', 1, 0, 'F', '0', '0', 'system:notify:channel:config:remove', '#', 'admin', SYSDATE(), '', NULL, ''); |
| | | ('渠道配置删除', @channelConfigParentId, 4, '#', '', 1, 0, 'F', '0', '0', 'system:notify:channel:config:remove', '#', 'admin', SYSDATE(), '', NULL, ''); |
| | | |
| | | -- 企业微信测试菜单 |
| | | INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) |
| | | VALUES |
| | | ('企业微信测试', @parentId, 4, 'qywechat/test', 'system/qywechat/test', 1, 0, 'C', '0', '0', 'system:qywechat:test:list', 'wechat', 'admin', SYSDATE(), '', NULL, '企业微信测试菜单'); |
| | | |
| | | -- 获取刚插入的企业微信测试菜单ID |
| | | SET @qywechatTestParentId = (SELECT menu_id FROM sys_menu WHERE menu_name = '企业微信测试' AND menu_type = 'C'); |
| | | |
| | | -- 企业微信测试按钮 SQL |
| | | INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) |
| | | VALUES |
| | | ('企业微信测试查询', @qywechatTestParentId, 1, '#', '', 1, 0, 'F', '0', '0', 'system:qywechat:test:query', '#', 'admin', SYSDATE(), '', NULL, ''), |
| | | ('企业微信测试新增', @qywechatTestParentId, 2, '#', '', 1, 0, 'F', '0', '0', 'system:qywechat:test:add', '#', 'admin', SYSDATE(), '', NULL, ''), |
| | | ('企业微信测试修改', @qywechatTestParentId, 3, '#', '', 1, 0, 'F', '0', '0', 'system:qywechat:test:edit', '#', 'admin', SYSDATE(), '', NULL, ''), |
| | | ('企业微信测试删除', @qywechatTestParentId, 4, '#', '', 1, 0, 'F', '0', '0', 'system:qywechat:test:remove', '#', 'admin', SYSDATE(), '', NULL, ''); |
| New file |
| | |
| | | -- 企业微信配置初始化脚本 |
| | | -- 该脚本用于初始化企业微信相关的系统配置项 |
| | | |
| | | -- 删除已存在的配置项 |
| | | DELETE FROM sys_config WHERE config_key IN ( |
| | | 'qy_wechat.enable', |
| | | 'qy_wechat.corp_id', |
| | | 'qy_wechat.corp_secret', |
| | | 'qy_wechat.agent_id' |
| | | ); |
| | | |
| | | -- 插入企业微信配置项 |
| | | INSERT INTO sys_config (config_name, config_key, config_value, config_type, create_by, create_time, update_by, update_time, remark) VALUES |
| | | ('企业微信服务启用状态', 'qy_wechat.enable', 'false', 'Y', 'admin', SYSDATE(), '', NULL, '企业微信服务是否启用,true-启用,false-禁用'), |
| | | ('企业微信CorpID', 'qy_wechat.corp_id', 'wx248505bfbab6d0c1', 'N', 'admin', SYSDATE(), '', NULL, '企业微信企业ID'), |
| | | ('企业微信CorpSecret', 'qy_wechat.corp_secret', '2MCilqWYC0FWjOQ894sbb-s7Lb5sVH4HHuJgOsd9l1k', 'N', 'admin', SYSDATE(), '', NULL, '企业微信应用密钥'), |
| | | ('企业微信AgentId', 'qy_wechat.agent_id', '1000002', 'N', 'admin', SYSDATE(), '', NULL, '企业微信应用AgentId'); |
| | | |
| | | COMMIT; |
| New file |
| | |
| | | -- 企业微信用户ID同步定时任务 |
| | | -- 该任务每天凌晨2点执行一次,同步OA系统中的企业微信用户ID到本地系统 |
| | | |
| | | -- 删除已存在的同名任务 |
| | | DELETE FROM QRTZ_JOB_DETAILS WHERE sched_name = 'RuoyiScheduler' AND job_name = 'qyWechatUserSyncTask' AND job_group = 'DEFAULT'; |
| | | DELETE FROM QRTZ_TRIGGERS WHERE sched_name = 'RuoyiScheduler' AND trigger_name = 'qyWechatUserSyncTask' AND trigger_group = 'DEFAULT'; |
| | | DELETE FROM QRTZ_CRON_TRIGGERS WHERE sched_name = 'RuoyiScheduler' AND trigger_name = 'qyWechatUserSyncTask' AND trigger_group = 'DEFAULT'; |
| | | |
| | | -- 插入任务详细信息 |
| | | INSERT INTO QRTZ_JOB_DETAILS ( |
| | | sched_name, |
| | | job_name, |
| | | job_group, |
| | | description, |
| | | job_class_name, |
| | | is_durable, |
| | | is_nonconcurrent, |
| | | is_update_data, |
| | | requests_recovery, |
| | | job_data |
| | | ) VALUES ( |
| | | 'RuoyiScheduler', |
| | | 'qyWechatUserSyncTask', |
| | | 'DEFAULT', |
| | | '企业微信用户ID同步任务', |
| | | 'com.ruoyi.quartz.task.QyWechatUserSyncTask', |
| | | '1', |
| | | '0', |
| | | '0', |
| | | '0', |
| | | '' |
| | | ); |
| | | |
| | | -- 插入触发器信息 |
| | | INSERT INTO QRTZ_TRIGGERS ( |
| | | sched_name, |
| | | trigger_name, |
| | | trigger_group, |
| | | job_name, |
| | | job_group, |
| | | description, |
| | | next_fire_time, |
| | | prev_fire_time, |
| | | priority, |
| | | trigger_state, |
| | | trigger_type, |
| | | start_time, |
| | | end_time, |
| | | calendar_name, |
| | | misfire_instr, |
| | | job_data |
| | | ) VALUES ( |
| | | 'RuoyiScheduler', |
| | | 'qyWechatUserSyncTask', |
| | | 'DEFAULT', |
| | | 'qyWechatUserSyncTask', |
| | | 'DEFAULT', |
| | | '企业微信用户ID同步任务触发器', |
| | | 0, |
| | | 0, |
| | | 5, |
| | | 'WAITING', |
| | | 'CRON', |
| | | 1702281600000, |
| | | 0, |
| | | '', |
| | | 0, |
| | | '' |
| | | ); |
| | | |
| | | -- 插入Cron触发器信息(每天凌晨2点执行) |
| | | INSERT INTO QRTZ_CRON_TRIGGERS ( |
| | | sched_name, |
| | | trigger_name, |
| | | trigger_group, |
| | | cron_expression, |
| | | time_zone_id |
| | | ) VALUES ( |
| | | 'RuoyiScheduler', |
| | | 'qyWechatUserSyncTask', |
| | | 'DEFAULT', |
| | | '0 0 2 * * ?', |
| | | 'Asia/Shanghai' |
| | | ); |
| | | |
| | | COMMIT; |
| | |
| | | update_by varchar(64) default '' comment '更新者', |
| | | update_time datetime comment '更新时间', |
| | | remark varchar(500) default null comment '备注', |
| | | oa_user_id int(11) default null comment 'SQL Server中的OA用户ID', |
| | | oa_order_class varchar(255) default null comment 'OA系统的订单编码列表(如:BF,AB,SA)', |
| | | open_id varchar(100) default null comment '微信OpenID', |
| | | union_id varchar(100) default null comment '微信UnionID', |
| | | wechat_nickname varchar(100) default null comment '微信昵称', |
| | | qy_wechat_user_id varchar(100) default null comment '企业微信用户ID', |
| | | qy_wechat_update_time datetime default null comment '企业微信用户ID更新时间', |
| | | can_view_all_consult char(1) default '0' comment '是否可查看所有咨询单(0否 1是)', |
| | | primary key (user_id) |
| | | ) engine=innodb auto_increment=100 comment = '用户信息表'; |
| | | |
| | | -- ---------------------------- |
| | | -- 初始化-用户信息表数据 |
| | | -- ---------------------------- |
| | | insert into sys_user values(1, 103, 'admin', '若依', '00', 'ry@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '管理员'); |
| | | insert into sys_user values(2, 105, 'ry', '若依', '00', 'ry@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '测试员'); |
| | | insert into sys_user values(1, 103, 'admin', '若依', '00', 'ry@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '管理员', null, null, null, null, null, null, null, '0'); |
| | | insert into sys_user values(2, 105, 'ry', '若依', '00', 'ry@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '测试员', null, null, null, null, null, null, null, '0'); |
| | | |
| | | |
| | | -- ---------------------------- |
| | |
| | | `notify_type` varchar(32) NOT NULL COMMENT '通知类型:TASK_ASSIGN-任务分配, STATUS_CHANGE-状态变更, TASK_CREATE-任务创建', |
| | | `channel` varchar(32) NOT NULL COMMENT '通知渠道:WECHAT-微信订阅消息, SMS-短信, APP_PUSH-APP推送, SITE_MSG-站内消息', |
| | | `send_status` char(1) DEFAULT '0' COMMENT '发送状态:0-待发送, 1-发送成功, 2-发送失败', |
| | | `send_content` text COMMENT '发送的内容', |
| | | `send_time` datetime DEFAULT NULL COMMENT '发送时间', |
| | | `send_result` varchar(500) DEFAULT NULL COMMENT '发送结果/错误信息', |
| | | `send_result` text DEFAULT NULL COMMENT '发送结果/错误信息', |
| | | `retry_count` int(11) DEFAULT 0 COMMENT '重试次数', |
| | | `create_time` datetime NOT NULL COMMENT '创建时间', |
| | | `create_by` varchar(64) DEFAULT '' COMMENT '创建者', |
| | |
| | | INSERT INTO `sys_notify_channel_config` (`notify_type`, `channel`, `enabled`, `priority`, `config_json`, `create_by`, `create_time`, `remark`) VALUES |
| | | ('TASK_ASSIGN', 'SITE_MSG', '1', 100, NULL, 'admin', NOW(), '任务分配-站内消息'), |
| | | ('TASK_ASSIGN', 'WECHAT', '1', 90, NULL, 'admin', NOW(), '任务分配-微信订阅消息'), |
| | | ('TASK_ASSIGN', 'SMS', '0', 80, NULL, 'admin', NOW(), '任务分配-短信(默认关闭)'); |
| | | ('TASK_ASSIGN', 'SMS', '0', 80, NULL, 'admin', NOW(), '任务分配-短信(默认关闭)'), |
| | | ('TASK_ASSIGN', 'QY_WECHAT', '0', 85, NULL, 'admin', NOW(), '任务分配-企业微信(默认关闭)'); |
| | | |
| | | -- 状态变更通知 - 仅启用站内消息 |
| | | INSERT INTO `sys_notify_channel_config` (`notify_type`, `channel`, `enabled`, `priority`, `config_json`, `create_by`, `create_time`, `remark`) VALUES |
| | |
| | | -- 病情诊断信息 |
| | | disease_ids VARCHAR(500) COMMENT '病情ID列表(ICD-10疾病ID列表,逗号分隔,用于同步调度单的OrdICD_ID参数)', |
| | | |
| | | -- 旧系统同步字段 |
| | | legacy_dispatch_ord_no VARCHAR(50) COMMENT '旧系统调度单编号', |
| | | legacy_service_ns_time DATETIME COMMENT '旧系统服务通知时间', |
| | | legacy_dispatch_ns_time DATETIME COMMENT '旧系统调度通知时间', |
| | | legacy_dispatch_ord_class VARCHAR(50) COMMENT '旧系统调度单分类', |
| | | |
| | | -- 系统字段 |
| | | create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
| | | update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| New file |
| | |
| | | -- ---------------------------- |
| | | -- 更新急救转运任务扩展表,添加旧系统同步字段 |
| | | -- ---------------------------- |
| | | |
| | | -- 添加旧系统调度单编号字段 |
| | | ALTER TABLE sys_task_emergency |
| | | ADD COLUMN legacy_dispatch_ord_no VARCHAR(50) COMMENT '旧系统调度单编号'; |
| | | |
| | | -- 添加旧系统服务通知时间字段 |
| | | ALTER TABLE sys_task_emergency |
| | | ADD COLUMN legacy_service_ns_time DATETIME COMMENT '旧系统服务通知时间'; |
| | | |
| | | -- 添加旧系统调度通知时间字段 |
| | | ALTER TABLE sys_task_emergency |
| | | ADD COLUMN legacy_dispatch_ns_time DATETIME COMMENT '旧系统调度通知时间'; |
| | | |
| | | -- 添加旧系统调度单分类字段 |
| | | ALTER TABLE sys_task_emergency |
| | | ADD COLUMN legacy_dispatch_ord_class VARCHAR(50) COMMENT '旧系统调度单分类'; |
| New file |
| | |
| | | -- ---------------------------- |
| | | -- 为sys_task_emergency表添加legacy_service_ord_class字段 |
| | | -- 用于存储旧系统服务单分类信息 |
| | | -- ---------------------------- |
| | | |
| | | -- 添加旧系统服务单分类字段 |
| | | ALTER TABLE sys_task_emergency |
| | | ADD COLUMN legacy_service_ord_class VARCHAR(50) COMMENT '旧系统服务单分类'; |