427 lines
16 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.example.caseData.service;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.caseData.dao.BasicHospitalDao;
import com.example.caseData.dao.CaseClinicalDoctorDao;
import com.example.caseData.dao.CaseClinicalRecordScoreDao;
import com.example.caseData.dao.UserDao;
import com.example.caseData.dto.publicDto.LoginDto;
import com.example.caseData.exception.BusinessException;
import com.example.caseData.extend.aliyun.Oss;
import com.example.caseData.extend.app.Hospital.GetHospitalByUuidResponse;
import com.example.caseData.extend.app.Hospital.Hospital;
import com.example.caseData.extend.app.Score.Score;
import com.example.caseData.extend.app.UserInfo.GetUserInfoResponse;
import com.example.caseData.extend.app.UserInfo.UserInfo;
import com.example.caseData.model.*;
import com.example.caseData.request.UserRequest.ReportUserScoreRequest;
import com.example.caseData.utils.JwtUtil;
import com.example.caseData.utils.Replace;
import com.example.caseData.utils.StringToInt;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Random;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import static com.baomidou.mybatisplus.extension.toolkit.Db.save;
@Slf4j
@Service
public class UserService {
@Resource
private UserDao userDao;
@Resource
private UserInfo userInfo;
@Resource
private BasicHospitalDao basicHospitalDao;
@Resource
private CaseClinicalDoctorDao caseClinicalDoctorDao;
@Resource
private CaseClinicalRecordScoreDao caseClinicalRecordScoreDao;
@Resource
private Hospital hospital;
@Resource
private JwtUtil jwtUtil;
@Resource
private Score score;
/**
* 用户登陆-手机号
* @return UserModel
*/
@Transactional
public LoginDto UserLoginWithMobile(String phone) throws BusinessException {
// 获取app用户数据
GetUserInfoResponse result = userInfo.getUserInfoByMobile(phone);
UserModel user = GetAppUserInfo(result);
// 生成jwt
String token = jwtUtil.createToken(String.valueOf(user.getUserId()));
// 获取对应医生数据
LambdaQueryWrapper<CaseClinicalDoctorModel> caseClinicalDoctorWrapper = new LambdaQueryWrapper<>();
caseClinicalDoctorWrapper.eq(CaseClinicalDoctorModel::getDoctorIden, user.getUserIden());
CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectOne(caseClinicalDoctorWrapper);
// 处理返回值
LoginDto g = new LoginDto();
g.setUserId(String.valueOf(user.getUserId()));
g.setUserName(user.getUserName());
g.setAvatar(Replace.addOssDomain(user.getAvatar()));
g.setToken(token);
if (caseClinicalDoctor != null) {
g.setDoctorId(String.valueOf(caseClinicalDoctor.getDoctorId()));
}
return g;
}
/**
* 用户登陆-app
* @param appToken 1
*/
@Transactional
public LoginDto UserLoginWithApp(String appToken) throws BusinessException {
GetUserInfoResponse result = userInfo.getUserInfoByToken(appToken);
UserModel user = GetAppUserInfo(result);
// 生成jwt
String token = jwtUtil.createToken(String.valueOf(user.getUserId()));
// 获取对应医生数据
LambdaQueryWrapper<CaseClinicalDoctorModel> caseClinicalDoctorWrapper = new LambdaQueryWrapper<>();
caseClinicalDoctorWrapper.eq(CaseClinicalDoctorModel::getDoctorIden, user.getUserIden());
CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectOne(caseClinicalDoctorWrapper);
// 处理返回值
LoginDto g = new LoginDto();
g.setUserId(String.valueOf(user.getUserId()));
g.setUserName(user.getUserName());
g.setAvatar(Replace.addOssDomain(user.getAvatar()));
g.setToken(token);
if (caseClinicalDoctor != null) {
g.setDoctorId(String.valueOf(caseClinicalDoctor.getDoctorId()));
}
return g;
}
/**
* 获取app用户数据
* @return UserModel
*/
public UserModel GetAppUserInfo(GetUserInfoResponse r) throws BusinessException {
GetUserInfoResponse.ResponsData data = r.getData();
// 查询数据库用户信息
LambdaQueryWrapper<UserModel> userModelWrapper = new LambdaQueryWrapper<>();
userModelWrapper.eq(UserModel::getUserIden, r.getData().getUuid());
UserModel user = userDao.selectOne(userModelWrapper);
if (user == null){
// 构造 UserModel 对象
user = new UserModel();
user.setUserIden(data.getUuid());
user.setUserName(data.getRealname());
user.setUserMobile(data.getMobile());
user.setMobileEncryption(SecureUtil.md5(data.getMobile()));
user.setStatus(1);
user.setRegisterSource(2);
user.setOpenId("");
user.setUnionId("");
user.setSex(0);
if (data.getPhoto() != null) {
String ossPath = UserService.handleUserImage(data.getImg_host() + data.getPhoto());
user.setAvatar(ossPath);
}else{
user.setAvatar("");
}
user.setDepartmentName(data.getOfficeName());
user.setTitle(StringToInt.DoctorTitleToInt(data.getPositionName()));
user.setAddress(data.getProvName());
int res = userDao.insert(user);
if (res <= 0){
throw new BusinessException("操作失败");
}
}else{
if (!Objects.equals(user.getUserName(), data.getRealname())){
user.setUserName(data.getRealname());
}
if (!Objects.equals(user.getUserMobile(), data.getMobile())){
user.setUserMobile(data.getMobile());
user.setMobileEncryption(SecureUtil.md5(data.getMobile()));
}
if (!Objects.equals(user.getTitle(), StringToInt.DoctorTitleToInt(data.getPositionName()))){
user.setTitle(StringToInt.DoctorTitleToInt(data.getPositionName()));
}
if (!Objects.equals(user.getDepartmentName(), data.getOfficeName())){
user.setDepartmentName(data.getOfficeName());
}
if (!Objects.equals(user.getAddress(), data.getProvName())){
user.setAddress(data.getProvName());
}
if (data.getPhoto() != null) {
try {
String ossPath = UserService.handleUserImage(data.getImg_host() + data.getPhoto());
user.setAvatar(ossPath);
}catch (Exception e){
// 不处理
}
}
userDao.updateById(user);
}
// 获取app医院数据
BasicHospitalModel basicHospital = GetAppHospital(data.getHospitalUuid());
// 修改用户所属医院
if (!Objects.equals(user.getHospitalId(), basicHospital.getHospitalId())){
user.setHospitalId(basicHospital.getHospitalId());
userDao.updateById(user);
}
// 获取对应医生数据
LambdaQueryWrapper<CaseClinicalDoctorModel> caseClinicalDoctorWrapper = new LambdaQueryWrapper<>();
caseClinicalDoctorWrapper.eq(CaseClinicalDoctorModel::getDoctorIden, user.getUserIden());
CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectOne(caseClinicalDoctorWrapper);
if (caseClinicalDoctor == null){
// 二次匹配:通过姓名-医院获取医生信息
caseClinicalDoctorWrapper = new LambdaQueryWrapper<>();
caseClinicalDoctorWrapper.eq(CaseClinicalDoctorModel::getDoctorId, user.getUserName());
caseClinicalDoctorWrapper.eq(CaseClinicalDoctorModel::getHospitalId, basicHospital.getHospitalId());
caseClinicalDoctor = caseClinicalDoctorDao.selectOne(caseClinicalDoctorWrapper);
}
if (caseClinicalDoctor == null){
CaseClinicalDoctorModel c = new CaseClinicalDoctorModel();
c.setDoctorName(user.getUserName());
c.setDoctorIden(user.getUserIden());
c.setHospitalId(user.getHospitalId());
c.setAvatar(user.getAvatar());
int res = caseClinicalDoctorDao.insert(c);
if (res <= 0){
throw new BusinessException("操作失败");
}
}else{
if (!Objects.equals(caseClinicalDoctor.getDoctorName(), data.getRealname())){
caseClinicalDoctor.setDoctorName(data.getRealname());
}
if (!Objects.equals(basicHospital.getHospitalId(), caseClinicalDoctor.getHospitalId())){
caseClinicalDoctor.setHospitalId(basicHospital.getHospitalId());
}
if (!Objects.equals(user.getAvatar(), caseClinicalDoctor.getAvatar())){
caseClinicalDoctor.setAvatar(user.getAvatar());
}
caseClinicalDoctorDao.updateById(caseClinicalDoctor);
}
return user;
}
/**
* 获取app医院数据
* @param hospitalIden app医院唯一标识
* @return BasicHospitalModel
*/
public BasicHospitalModel GetAppHospital(String hospitalIden) throws BusinessException {
// 查询数据库医院信息
LambdaQueryWrapper<BasicHospitalModel> basicHospitalWrapper = new LambdaQueryWrapper<>();
basicHospitalWrapper.eq(BasicHospitalModel::getHospitalIden, hospitalIden);
BasicHospitalModel basicHospital = basicHospitalDao.selectOne(basicHospitalWrapper);
if (basicHospital == null){
// 请求接口获取数据
GetHospitalByUuidResponse result = hospital.getHospitalByUuid(hospitalIden);
GetHospitalByUuidResponse.GetHospitalByUuidData data = result.getData();
// 构造 UserModel 对象
basicHospital = new BasicHospitalModel();
basicHospital.setHospitalIden(hospitalIden);
basicHospital.setHospitalName(data.getName());
basicHospital.setSource(2);
basicHospital.setHospitalLevel(data.getLevel());
basicHospital.setDoctorNumber(data.getExpert_num());
basicHospital.setProvince(data.getProv_name());
save(basicHospital);
}
return basicHospital;
}
/**
* 获取临床医生数据
* @return UserModel
*/
public CaseClinicalDoctorModel GetCaseClinicalDoctor(GetUserInfoResponse r) throws BusinessException {
GetUserInfoResponse.ResponsData data = r.getData();
// 获取app医院数据
BasicHospitalModel basicHospital = GetAppHospital(data.getHospitalUuid());
// 获取对应医生数据
LambdaQueryWrapper<CaseClinicalDoctorModel> caseClinicalDoctorWrapper = new LambdaQueryWrapper<>();
caseClinicalDoctorWrapper.eq(CaseClinicalDoctorModel::getDoctorIden, data.getUuid());
CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectOne(caseClinicalDoctorWrapper);
if (caseClinicalDoctor == null){
caseClinicalDoctor = new CaseClinicalDoctorModel();
caseClinicalDoctor.setDoctorName(data.getRealname());
caseClinicalDoctor.setDoctorIden(data.getUuid());
caseClinicalDoctor.setHospitalId(basicHospital.getHospitalId());
caseClinicalDoctor.setAvatar(data.getPhoto());
int res = caseClinicalDoctorDao.insert(caseClinicalDoctor);
if (res <= 0){
throw new BusinessException("操作失败");
}
}else{
if (!Objects.equals(caseClinicalDoctor.getDoctorName(), data.getRealname())){
caseClinicalDoctor.setDoctorName(data.getRealname());
}
if (!Objects.equals(basicHospital.getHospitalId(), caseClinicalDoctor.getHospitalId())){
caseClinicalDoctor.setHospitalId(basicHospital.getHospitalId());
}
caseClinicalDoctorDao.updateById(caseClinicalDoctor);
}
return caseClinicalDoctor;
}
// 发放积分
public boolean ReportUserScore(String id,Integer type,String userId) throws BusinessException{
// 获取积分发放记录
// 获取今天的日期,并设置时间为 00:00:00
LocalDateTime startOfToday = LocalDate.now().atStartOfDay(); // 例如2025-07-30 00:00:00
QueryWrapper<CaseClinicalRecordScoreModel> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", userId)
.ge("created_at", startOfToday) // created_at >= 今天 00:00:00
.orderByDesc("created_at"); // 最新的在前
List<CaseClinicalRecordScoreModel> caseClinicalRecordScores = caseClinicalRecordScoreDao.selectList(queryWrapper);
if (caseClinicalRecordScores.size() > 3){
return true;
}
// 获取用户数据
UserModel user = userDao.selectById(userId);
if (user == null){
throw new BusinessException("积分");
}
// 发放积分
score.ReportUserScore(user.getUserIden(),5,"病例库-病例互动");
// 添加打赏记录
CaseClinicalRecordScoreModel data = new CaseClinicalRecordScoreModel();
data.setUserId(Long.valueOf(userId));
data.setScore(5);
data.setId(Long.valueOf(id));
data.setUserName(user.getUserName());
data.setNodeName("病例库-病例互动");
data.setType(type);
data.setScoreType(5);
caseClinicalRecordScoreDao.insert(data);
return true;
}
/**
* 处理用户头像:下载远程头像并上传至 OSS
*
* @param wxAvatarUrl 微信头像地址
* @return OSS 路径(以 / 开头),如 /user/avatar/202507301530123456.png
*/
public static String handleUserImage(String wxAvatarUrl) {
if (wxAvatarUrl == null || wxAvatarUrl.isEmpty()) {
return null;
}
HttpURLConnection conn = null;
try {
// 1. 下载远程图片
URL url = new URL(wxAvatarUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(10000);
conn.setRequestMethod("GET");
if (conn.getResponseCode() != 200) {
throw new BusinessException("图片处理失败");
}
try (InputStream input = conn.getInputStream();
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
byte[] buffer = new byte[4096];
int len;
while ((len = input.read(buffer)) != -1) {
output.write(buffer, 0, len);
}
byte[] imageBytes = output.toByteArray();
if (imageBytes.length == 0) {
throw new BusinessException("图片处理失败");
}
// 2. 生成 OSS 路径
String dateTimeStr = LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
int randomSuffix = new Random().nextInt(9000) + 1000;
String ossPath = "dev/static/images/" + dateTimeStr + randomSuffix + ".png";
// 3. 上传 OSS
boolean success = Oss.putObject(ossPath, imageBytes);
if (!success) {
throw new BusinessException("图片处理失败");
}
return "/" + ossPath;
}
} catch (Exception e) {
// 头像处理失败
System.out.println(e.getMessage());
return "";
} finally {
if (conn != null) {
conn.disconnect();
}
}
}
}