| 
					
				 | 
			
			
				@@ -5,60 +5,135 @@ import cn.hutool.json.JSONUtil; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.alibaba.druid.support.json.JSONUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.alibaba.nacos.common.utils.MD5Utils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springblade.common.utils.SnowFlakeUtil; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springblade.core.oss.model.BladeFile; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springblade.core.tool.jackson.JsonUtil; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springblade.core.tool.utils.BeanUtil; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springblade.core.tool.utils.CollectionUtil; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springblade.manager.entity.QProfilerData; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springblade.manager.entity.QProfilerOffset; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springblade.manager.entity.QProfilerStandardSectionBean; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springblade.manager.entity.profiler.ProfilerResult; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springblade.manager.entity.profiler.ProfilerSaveDTO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springblade.manager.service.QProfilerDataService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springblade.manager.service.QProfilerOffsetService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springblade.manager.mapper.QProfilerOffsetMapper; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springblade.manager.service.QProfilerStandardSectionBeanService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springblade.manager.utils.FileUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springblade.resource.feign.NewIOSSClient; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.stereotype.Service; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.transaction.annotation.Transactional; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.web.multipart.MultipartFile; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import javax.annotation.Resource; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.time.Instant; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.List; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-* @author LHB 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-* @description 针对表【q_profiler_offset(断面仪-基础信息+测量者信息)】的数据库操作Service实现 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-* @createDate 2025-10-27 15:58:56 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @author LHB 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @description 针对表【q_profiler_offset(断面仪-基础信息+测量者信息)】的数据库操作Service实现 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @createDate 2025-10-27 15:58:56 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 @Service 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 public class QProfilerOffsetServiceImpl extends ServiceImpl<QProfilerOffsetMapper, QProfilerOffset> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    implements QProfilerOffsetService{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        implements QProfilerOffsetService { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     //第三方的appKey 固定值 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private final static  String APP_KEY = "QDM123"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final static String APP_KEY = "QDM123"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     //第三方密钥 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private final static  String APP_SECRET = "MDc1YWI4OTMtY2M0NC00NDViLTlkZmUtYzAzZTVmZTUxMmE1"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final static String APP_SECRET = "MDc1YWI4OTMtY2M0NC00NDViLTlkZmUtYzAzZTVmZTUxMmE1"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // 时间戳有效期(秒),防止重放攻击 // 5分钟 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private static final long TIMESTAMP_EXPIRE = 300; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Resource 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private NewIOSSClient newIOSSClient; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Resource 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private QProfilerDataService dataService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Resource 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private QProfilerStandardSectionBeanService beanService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Transactional(rollbackFor = Exception.class) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public ProfilerResult save(ProfilerSaveDTO save, MultipartFile file) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(!save.getAppKey().equals(APP_KEY)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return ProfilerResult.error("10006","appKey错误",""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!save.getAppKey().equals(APP_KEY)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return ProfilerResult.error("10006", "appKey错误", ""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         String s = MD5Utils.md5Hex(APP_KEY + save.getTimestamp() + APP_SECRET, "UTF-8"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(!s.equals(save.getSign())){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return ProfilerResult.error("10007","sign错误",""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!s.equals(save.getSign())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return ProfilerResult.error("10007", "sign错误", ""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(!isValidTimestamp(save.getTimestamp())){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return ProfilerResult.error("10008","签名验证失败:timeTicks的时间和当前时间必须小于30分钟",""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //主键id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Long id = SnowFlakeUtil.getId(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //断面仪测量设备编码或名称 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         String deviceCode = save.getDeviceCode(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //字符串转json 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        JSONObject jsonObject = JSONUtil.parseObj(deviceCode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        JSONObject jsonObject = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            jsonObject = JSONUtil.parseObj(save.getData()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return ProfilerResult.error("10009","data参数格式错误",""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //获取基础信息 + 测量者信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        System.out.println(save); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        QProfilerOffset offset = jsonObject.getBean("offset", QProfilerOffset.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(offset == null){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            offset = new QProfilerOffset(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        offset.setId(id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        offset.setDeviceCode(deviceCode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        QProfilerOffset info = jsonObject.getBean("info", QProfilerOffset.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //把测量者信息赋值给基础信息对象 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(info != null){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            offset.setChannelName(info.getChannelName()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            offset.setConstructionUnit(info.getConstructionUnit()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            offset.setDate(info.getDate()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            offset.setNameOfProject(info.getNameOfProject()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            offset.setUserName(info.getUserName()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            offset.setMileageNumber(info.getMileageNumber()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //获取标准断面数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        JSONObject mStandardSectionDataBeanList = jsonObject.getJSONObject("standardSectionBean"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        List<QProfilerStandardSectionBean> standardSectionBean = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(mStandardSectionDataBeanList != null){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            standardSectionBean = mStandardSectionDataBeanList.getBeanList("mStandardSectionDataBeanList", QProfilerStandardSectionBean.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(standardSectionBean != null){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                standardSectionBean.forEach(f ->{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    f.setId(SnowFlakeUtil.getId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    f.setOffsetId(id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //获取测量数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        List<QProfilerData> data = jsonObject.getBeanList("data", QProfilerData.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(data != null){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            data.forEach(f -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                f.setId(SnowFlakeUtil.getId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                f.setOffsetId(id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //上传文件 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (file != null && !file.isEmpty() && file.getSize() > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //获取文件名称后缀 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BladeFile bladeFile = this.newIOSSClient.uploadFileByInputStream(file); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            offset.setFileUrl(bladeFile.getLink()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //保存数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        baseMapper.insert(offset); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(CollectionUtil.isNotEmpty(standardSectionBean)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            beanService.saveBatch(standardSectionBean); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(CollectionUtil.isNotEmpty(data)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            dataService.saveBatch(data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return ProfilerResult.success(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 验证时间戳有效性 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @param timestamp 时间戳字符串 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @return 是否有效 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -72,8 +147,28 @@ public class QProfilerOffsetServiceImpl extends ServiceImpl<QProfilerOffsetMappe 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 获取文件后缀名(包含点号) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param file MultipartFile对象 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @return 文件后缀名,如 ".jpg", ".png" 等 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static String getFileExtensionWithDot(MultipartFile file) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (file == null || file.isEmpty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return ""; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String originalFilename = file.getOriginalFilename(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (originalFilename == null || originalFilename.lastIndexOf(".") == -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return ""; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return originalFilename.substring(originalFilename.lastIndexOf(".")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public static void main(String[] args) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        System.out.println(MD5Utils.md5Hex("QDM123" + 1761554359 + "MDc1YWI4OTMtY2M0NC00NDViLTlkZmUtYzAzZTVmZTUxMmE1", "UTF-8")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        System.out.println(MD5Utils.md5Hex("QDM123" + 1761613837 + "MDc1YWI4OTMtY2M0NC00NDViLTlkZmUtYzAzZTVmZTUxMmE1", "UTF-8")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |