wlzboy
4 天以前 cfe0b79fbea0fb1d7a5a796e71ada7d3b7812046
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
package com.ruoyi.system.service.impl;
 
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.config.SmsConfig;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SmsUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysTask;
import com.ruoyi.system.domain.SysTaskEmergency;
import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
import com.ruoyi.system.mapper.SysTaskMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISmsService;
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.List;
 
/**
 * 短信发送服务实现类
 * 
 * @author ruoyi
 * @date 2025-12-07
 */
@Service
public class SmsServiceImpl implements ISmsService {
 
    private static final Logger log = LoggerFactory.getLogger(SmsServiceImpl.class);
 
    /** 系统配置键:短信开关 */
    private static final String CONFIG_KEY_SMS_ENABLED = "sms.enabled";
 
    @Autowired
    private SmsConfig smsConfig;
 
    @Autowired
    private ISysConfigService configService;
 
    @Autowired
    private SysUserMapper sysUserMapper;
 
    @Autowired
    private SysTaskMapper sysTaskMapper;
 
    @Autowired
    private SysTaskEmergencyMapper sysTaskEmergencyMapper;
 
    /**
     * 检查短信服务是否启用
     * 优先从数据库配置读取,其次从配置文件读取
     * 
     * @return true=启用, false=禁用
     */
    @Override
    public boolean isEnabled() {
        try {
            // 优先从数据库配置读取
            String enabled = configService.selectConfigByKey(CONFIG_KEY_SMS_ENABLED);
            if (StringUtils.isNotEmpty(enabled)) {
                return "true".equalsIgnoreCase(enabled);
            }
        } catch (Exception e) {
            log.warn("获取短信开关配置失败,使用配置文件配置", e);
        }
        // 从配置文件读取
        return smsConfig.isEnabled();
    }
 
    /**
     * 发送短信
     * 
     * @param phone 手机号
     * @param content 短信内容
     * @return 是否发送成功
     */
    @Override
    public boolean sendSms(String phone, String content) {
        if (!isEnabled()) {
            log.info("短信服务已关闭,跳过发送,phone={}", phone);
            return false;
        }
 
        if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(content)) {
            log.warn("短信发送参数不完整,phone={}, content={}", phone, content);
            return false;
        }
 
        try {
            // 添加签名
            String fullContent = smsConfig.getSignName() + content;
            
            JSONObject result = SmsUtils.sendSms(
                    smsConfig.getAddress(),
                    smsConfig.getUserName(),
                    smsConfig.getPassword(),
                    phone,
                    fullContent
            );
 
            if (result != null) {
                int code = result.getIntValue("code", -1);
                if (code == 0) {
                    log.info("短信发送成功,phone={}", phone);
                    return true;
                } else {
                    log.error("短信发送失败,phone={},code={},msg={}", 
                            phone, code, result.getString("msg"));
                }
            }
        } catch (Exception e) {
            log.error("短信发送异常,phone={}", phone, e);
        }
 
        return false;
    }
 
    /**
     * 批量发送短信
     * 
     * @param phones 手机号列表
     * @param content 短信内容
     * @return 成功发送的数量
     */
    @Override
    public int sendSmsBatch(List<String> phones, String content) {
        if (!isEnabled()) {
            log.info("短信服务已关闭,跳过批量发送");
            return 0;
        }
 
        if (phones == null || phones.isEmpty() || StringUtils.isEmpty(content)) {
            log.warn("批量短信发送参数不完整");
            return 0;
        }
 
        int successCount = 0;
        for (String phone : phones) {
            if (sendSms(phone, content)) {
                successCount++;
            }
        }
 
        log.info("批量短信发送完成,总数={},成功={}", phones.size(), successCount);
        return successCount;
    }
 
    /**
     * 发送任务分配通知短信
     * 
     * @param taskId 任务ID
     * @param userIds 用户ID列表
     * @param excludeUserId 排除的用户ID(可选,如创建人)
     * @return 成功发送的数量
     */
    @Override
    public int sendTaskAssignSms(Long taskId, List<Long> userIds, Long excludeUserId) {
        if (!isEnabled()) {
            log.info("短信服务已关闭,跳过任务分配短信发送,taskId={}", taskId);
            return 0;
        }
 
        if (taskId == null || userIds == null || userIds.isEmpty()) {
            log.warn("任务分配短信发送参数不完整,taskId={}, userIds={}", taskId, userIds);
            return 0;
        }
 
        // 查询任务信息
        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
        if (task == null) {
            log.warn("任务不存在,无法发送短信,taskId={}", taskId);
            return 0;
        }
 
        // 查询急救扩展信息
        SysTaskEmergency emergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
 
        // 构建短信内容
        String content = buildTaskAssignSmsContent(task, emergency);
 
        int successCount = 0;
        for (Long userId : userIds) {
            // 排除指定用户
            if (excludeUserId != null && excludeUserId.equals(userId)) {
                log.debug("跳过排除用户,userId={}", userId);
                continue;
            }
 
            // 查询用户信息
            SysUser user = sysUserMapper.selectUserById(userId);
            if (user == null) {
                log.warn("用户不存在,跳过发送,userId={}", userId);
                continue;
            }
 
            String phone = user.getPhonenumber();
            if (StringUtils.isEmpty(phone)) {
                log.warn("用户手机号为空,跳过发送,userId={}, userName={}", userId, user.getNickName());
                continue;
            }
 
            // 发送短信
            if (sendSms(phone, content)) {
                successCount++;
                log.info("任务分配短信发送成功,taskId={},userId={},phone={}", taskId, userId, phone);
            }
        }
 
        log.info("任务分配短信发送完成,taskId={},总数={},成功={}", taskId, userIds.size(), successCount);
        return successCount;
    }
 
    /**
     * 发送任务分配通知短信(不排除任何用户)
     * 
     * @param taskId 任务ID
     * @param userIds 用户ID列表
     * @return 成功发送的数量
     */
    @Override
    public int sendTaskAssignSms(Long taskId, List<Long> userIds) {
        return sendTaskAssignSms(taskId, userIds, null);
    }
 
    /**
     * 构建任务分配短信内容
     * 
     * @param task 任务信息
     * @param emergency 急救扩展信息(可选)
     * @return 短信内容
     */
    private String buildTaskAssignSmsContent(SysTask task, SysTaskEmergency emergency) {
        String template = smsConfig.getTaskAssignTemplate();
        
        // 任务编号
        String taskCode = StringUtils.isNotEmpty(task.getTaskCode()) 
                ? task.getTaskCode() : String.valueOf(task.getTaskId());
        
        // 出发地
        String departure;
        if (emergency != null && StringUtils.isNotEmpty(emergency.getHospitalOutName())) {
            departure = emergency.getHospitalOutName();
        } else if (StringUtils.isNotEmpty(task.getDepartureAddress())) {
            departure = task.getDepartureAddress();
        } else {
            departure = "待确认";
        }
        
        // 目的地
        String destination;
        if (emergency != null && StringUtils.isNotEmpty(emergency.getHospitalInName())) {
            destination = emergency.getHospitalInName();
        } else if (StringUtils.isNotEmpty(task.getDestinationAddress())) {
            destination = task.getDestinationAddress();
        } else {
            destination = "待确认";
        }
        
        // 限制地址长度,避免短信过长
        if (departure.length() > 20) {
            departure = departure.substring(0, 17) + "...";
        }
        if (destination.length() > 20) {
            destination = destination.substring(0, 17) + "...";
        }
        
        // 替换模板变量
        return template
                .replace("{taskCode}", taskCode)
                .replace("{departure}", departure)
                .replace("{destination}", destination);
    }
 
    /**
     * 查询短信余额
     * 
     * @return 余额信息
     */
    @Override
    public String getBalance() {
        try {
            JSONObject result = SmsUtils.getBalance(
                    smsConfig.getAddress(),
                    smsConfig.getUserName(),
                    smsConfig.getPassword()
            );
 
            if (result != null) {
                return result.toJSONString();
            }
        } catch (Exception e) {
            log.error("查询短信余额失败", e);
        }
        return "查询失败";
    }
}