liyong
7 小时以前 1cf91e355038837f30f2d727507b2229263d7de7
Merge remote-tracking branch 'origin/dev_New' into dev_New
已添加3个文件
已修改4个文件
428 ■■■■ 文件已修改
src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/ApproveTypeEnum.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/http/HttpUtils.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/controller/HomeController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/http/service/RealTimeEnergyConsumptionService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/http/service/impl/RealTimeEnergyConsumptionServiceImpl.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java
@@ -131,6 +131,9 @@
     */
    private Integer approveType;
    @TableField(exist = false)
    private String approveTypeName;
    /**
     * å®¡æ‰¹å¤‡æ³¨
     */
src/main/java/com/ruoyi/common/enums/ApproveTypeEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
package com.ruoyi.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
 * <br>
 * å®¡æ‰¹ç±»åž‹æžšä¸¾
 * </br>
 *
 * @author deslrey
 * @version 1.0
 * @since 2026/1/27 17:10
 */
@Getter
@AllArgsConstructor
public enum ApproveTypeEnum {
    PUBLIC_AFFAIRS(1, "公出管理"),
    LEAVE(2, "请假管理"),
    BUSINESS_TRIP(3, "出差管理"),
    REIMBURSEMENT(4, "报销管理"),
    PURCHASE(5, "采购审批"),
    QUOTATION(6, "报价审批"),
    DELIVERY(7, "发货审批");
    private final Integer code;
    private final String name;
    /**
     * æ ¹æ® code èŽ·å–å¯¹åº”çš„åç§°
     */
    public static String getNameByCode(Integer code) {
        if (code == null) return null;
        for (ApproveTypeEnum type : ApproveTypeEnum.values()) {
            if (type.getCode().equals(code)) {
                return type.getName();
            }
        }
        return "";
    }
}
src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
@@ -290,4 +290,93 @@
            return true;
        }
    }
    /**
     * å‘指定URL发送JSON格式的POST请求(推荐通用方法,默认UTF-8编码)
     * @param url å‘送请求的URL
     * @param jsonParam JSON格式的请求参数(直接传入JSON字符串)
     * @return è¿œç¨‹èµ„源的响应结果
     */
    public static String sendPostJson(String url, String jsonParam) {
        // é‡è½½è°ƒç”¨ï¼Œé»˜è®¤ä½¿ç”¨UTF-8编码,Content-Type固定为application/json
        return sendPostJson(url, jsonParam, StandardCharsets.UTF_8.name(),null);
    }
    /**
     * å‘指定URL发送JSON格式的POST请求(自定义编码,灵活适配特殊场景)
     * @param url å‘送请求的URL
     * @param jsonParam JSON格式的请求参数(直接传入JSON字符串)
     * @param headerValue è¯·æ±‚头的值
     * @return è¿œç¨‹èµ„源的响应结果
     */
    public static String sendPostJson(String url, String jsonParam, String headerValue) {
        // é‡è½½è°ƒç”¨ï¼Œé»˜è®¤ä½¿ç”¨UTF-8编码,Content-Type固定为application/json
        return sendPostJson(url, jsonParam, StandardCharsets.UTF_8.name(),headerValue);
    }
    /**
     * å‘指定URL发送JSON格式的POST请求(自定义编码,灵活适配特殊场景)
     * @param url å‘送请求的URL
     * @param jsonParam JSON格式的请求参数(直接传入JSON字符串)
     * @param charset ç¼–码类型(如UTF-8、GBK等,建议使用StandardCharsets常量)
     * @return è¿œç¨‹èµ„源的响应结果
     */
    public static String sendPostJson(String url, String jsonParam, String charset,String headerValue) {
        PrintWriter out = null;
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        try {
            log.info("sendPostJson - {}", url);
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            // 1. è®¾ç½®è¯·æ±‚头:固定Content-Type为application/json,适配JSON传参规范
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
            conn.setRequestProperty("Content-Type", MediaType.APPLICATION_JSON_VALUE); // æ ¸å¿ƒï¼šJSON专属Content-Type
            conn.setRequestProperty("Accept-Charset", charset);
            // 1.1 è®¾ç½®è¯·æ±‚头:可选,根据实际需要设置
            if(StringUtils.isNotEmpty(headerValue)){
                conn.setRequestProperty("Authorization", headerValue);
            }
            // 2. å¼€å¯è¾“入输出流(POST请求必须)
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 3. å†™å…¥JSON参数(使用指定编码,避免中文乱码)
            out = new PrintWriter(conn.getOutputStream(), true);
            out.print(jsonParam);
            out.flush();
            // 4. è¯»å–响应结果(与请求编码一致,保证解析正确)
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            log.info("recv - {}", result);
        } catch (ConnectException e) {
            log.error("调用HttpUtils.sendPostJson ConnectException, url=" + url + ",jsonParam=" + jsonParam, e);
        } catch (SocketTimeoutException e) {
            log.error("调用HttpUtils.sendPostJson SocketTimeoutException, url=" + url + ",jsonParam=" + jsonParam, e);
        } catch (IOException e) {
            log.error("调用HttpUtils.sendPostJson IOException, url=" + url + ",jsonParam=" + jsonParam, e);
        } catch (Exception e) {
            log.error("调用HttpUtils.sendPostJson Exception, url=" + url + ",jsonParam=" + jsonParam, e);
        } finally {
            // 5. å…³é—­æµèµ„源(避免内存泄漏,与原代码finally逻辑保持一致)
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                log.error("调用流关闭异常 sendPostJson, url=" + url + ",jsonParam=" + jsonParam, ex);
            }
        }
        return result.toString();
    }
}
src/main/java/com/ruoyi/home/controller/HomeController.java
@@ -70,14 +70,14 @@
    @GetMapping("/supplierPurchaseRanking")
    @ApiOperation("供应商采购排名")
    public AjaxResult supplierPurchaseRanking(@RequestParam(value = "type", defaultValue = "0") Integer type) {
    public AjaxResult supplierPurchaseRanking(@RequestParam(value = "type", defaultValue = "1") Integer type) {
        List<SupplierPurchaseRankingDto> list = homeService.supplierPurchaseRanking(type);
        return AjaxResult.success(list);
    }
    @GetMapping("/customerRevenueAnalysis")
    @ApiOperation("客户营收贡献数值分析")
    public AjaxResult customerRevenueAnalysis(@RequestParam("customerId") Long customerId, @RequestParam(value = "type", defaultValue = "0") Integer type) {
    public AjaxResult customerRevenueAnalysis(@RequestParam("customerId") Long customerId, @RequestParam(value = "type", defaultValue = "1") Integer type) {
        CustomerRevenueAnalysisDto dto = homeService.customerRevenueAnalysis(customerId, type);
        return AjaxResult.success(dto);
    }
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -16,6 +16,7 @@
import com.ruoyi.basic.pojo.SupplierManage;
import com.ruoyi.collaborativeApproval.mapper.NoticeMapper;
import com.ruoyi.collaborativeApproval.pojo.Notice;
import com.ruoyi.common.enums.ApproveTypeEnum;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.device.mapper.DeviceRepairMapper;
import com.ruoyi.device.pojo.DeviceRepair;
@@ -32,9 +33,11 @@
import com.ruoyi.production.mapper.ProductWorkOrderMapper;
import com.ruoyi.production.pojo.ProductWorkOrder;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.domain.SysUserDept;
import com.ruoyi.project.system.mapper.SysDeptMapper;
import com.ruoyi.project.system.mapper.SysUserDeptMapper;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
import com.ruoyi.purchase.pojo.PaymentRegistration;
@@ -44,8 +47,6 @@
import com.ruoyi.sales.mapper.ReceiptPaymentMapper;
import com.ruoyi.sales.mapper.SalesLedgerMapper;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.sales.pojo.ReceiptPayment;
import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
@@ -399,6 +400,12 @@
        if (CollectionUtils.isEmpty(approveProcesses)) {
            approveProcesses = new ArrayList<>();
        }
        approveProcesses.forEach(a -> {
            if (a.getApproveType() != null) {
                a.setApproveTypeName(ApproveTypeEnum.getNameByCode(a.getApproveType()));
            }
        });
//        // æŸ¥è¯¢æœªé¢†ç”¨åŠ³ä¿è®°å½•
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//
@@ -416,6 +423,8 @@
//                approveProcesses.add(approveProcess);
//            }
//        }
        return approveProcesses;
    }
@@ -695,15 +704,15 @@
        LocalDate startDate;
        LocalDate endDate;
        switch (type) {
            case 0: // å‘¨
            case 1: // å‘¨
                startDate = today.with(DayOfWeek.MONDAY);
                endDate = today.with(DayOfWeek.SUNDAY);
                break;
            case 1: // æœˆ
            case 2: // æœˆ
                startDate = today.with(TemporalAdjusters.firstDayOfMonth());
                endDate = today.with(TemporalAdjusters.lastDayOfMonth());
                break;
            case 2: // å­£åº¦
            case 3: // å­£åº¦
                Month currentMonth = today.getMonth();
                Month firstMonthOfQuarter = currentMonth.firstMonthOfQuarter();
                Month lastMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2);
@@ -745,15 +754,15 @@
        boolean groupByMonth = false;
        switch (type) {
            case 0: // å‘¨
            case 1: // å‘¨
                start = today.with(DayOfWeek.MONDAY);
                end = today.with(DayOfWeek.SUNDAY);
                break;
            case 1: // æœˆ
            case 2: // æœˆ
                start = today.with(TemporalAdjusters.firstDayOfMonth());
                end = today.with(TemporalAdjusters.lastDayOfMonth());
                break;
            case 2: // å­£åº¦
            case 3: // å­£åº¦
                Month firstMonthOfQuarter = today.getMonth().firstMonthOfQuarter();
                start = today.withMonth(firstMonthOfQuarter.getValue()).with(TemporalAdjusters.firstDayOfMonth());
                end = today.withMonth(firstMonthOfQuarter.plus(2).getValue()).with(TemporalAdjusters.lastDayOfMonth());
@@ -814,109 +823,54 @@
        ProductCategoryDistributionDto dto = new ProductCategoryDistributionDto();
        List<ProductCategoryDistributionDto.MajorCategoryDto> majorItems = new ArrayList<>();
        //  æ‰€æœ‰çš„产品大类和小类
        List<Product> allProducts = productMapper.selectList(new LambdaQueryWrapper<Product>());
        // æŸ¥è¯¢æ‰€æœ‰çš„产品类别
        List<Product> allProducts = productMapper.selectList(new LambdaQueryWrapper<>());
        if (CollectionUtils.isEmpty(allProducts)) {
            dto.setItems(majorItems);
            return dto;
        }
        List<Product> majorCategories = allProducts.stream().filter(p -> p.getParentId() == null).collect(Collectors.toList());
        List<Product> minorCategories = allProducts.stream().filter(p -> p.getParentId() != null).collect(Collectors.toList());
        // åˆ†ç¦»å¤§ç±»å’Œå°ç±»
        List<Product> majorCategories = allProducts.stream()
                .filter(p -> p.getParentId() == null)
                .collect(Collectors.toList());
        List<Product> minorCategories = allProducts.stream()
                .filter(p -> p.getParentId() != null)
                .collect(Collectors.toList());
        //  ä»Ž sales_ledger_product æ‹¿åˆ°æ¯ä¸ªäº§å“çš„型号库存
        // éœ€åŒ…含规格型号以支持三级分布
        List<Map<String, Object>> quantityMaps = salesLedgerProductMapper.selectMaps(new QueryWrapper<SalesLedgerProduct>()
                .select("product_id", "specification_model", "type", "SUM(quantity) as sum_qty")
                .isNotNull("product_id")
                .groupBy("product_id", "specification_model", "type"));
        // æŒ‰çˆ¶ç±»ID对小类进行分组
        Map<Long, List<Product>> minorGroupMap = minorCategories.stream()
                .collect(Collectors.groupingBy(Product::getParentId));
        Map<Long, Map<String, Map<Integer, BigDecimal>>> modelStockGroups = new HashMap<>();
        for (Map<String, Object> map : quantityMaps) {
            Long productId = Long.parseLong(map.get("product_id").toString());
            String model = map.get("specification_model") != null ? map.get("specification_model").toString() : "未知型号";
            Integer type = Integer.parseInt(map.get("type").toString());
            BigDecimal sum = map.get("sum_qty") != null ? new BigDecimal(map.get("sum_qty").toString()) : BigDecimal.ZERO;
        int totalMinorCount = minorCategories.size();
            modelStockGroups.computeIfAbsent(productId, k -> new HashMap<>())
                    .computeIfAbsent(model, k -> new HashMap<>())
                    .put(type, sum);
        }
        //  åº“存并汇总
        Map<Long, List<MapDto>> productModelsMap = new HashMap<>();
        Map<Long, BigDecimal> productTotalStockMap = new HashMap<>();
        for (Long pid : modelStockGroups.keySet()) {
            Map<String, Map<Integer, BigDecimal>> models = modelStockGroups.get(pid);
            BigDecimal productStock = BigDecimal.ZERO;
            List<MapDto> modelDtos = new ArrayList<>();
            for (String modelName : models.keySet()) {
                Map<Integer, BigDecimal> types = models.get(modelName);
                BigDecimal procurement = types.getOrDefault(2, BigDecimal.ZERO);
                BigDecimal sales = types.getOrDefault(1, BigDecimal.ZERO);
                BigDecimal stock = procurement.subtract(sales);
                if (stock.compareTo(BigDecimal.ZERO) < 0) stock = BigDecimal.ZERO;
                MapDto modelDto = new MapDto();
                modelDto.setName(modelName);
                modelDto.setValue(stock.stripTrailingZeros().toPlainString());
                modelDtos.add(modelDto);
                productStock = productStock.add(stock);
            }
            productModelsMap.put(pid, modelDtos);
            productTotalStockMap.put(pid, productStock);
        }
        BigDecimal totalInventory = productTotalStockMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        //  åž‹å·å æ¯”
        if (totalInventory.compareTo(BigDecimal.ZERO) > 0) {
            for (List<MapDto> dtos : productModelsMap.values()) {
                for (MapDto m : dtos) {
                    BigDecimal val = new BigDecimal(m.getValue());
                    m.setRate(val.multiply(new BigDecimal("100"))
                            .divide(totalInventory, 2, RoundingMode.HALF_UP).toString());
                }
            }
        }
        //  åˆ†å±‚数据
        for (Product major : majorCategories) {
            ProductCategoryDistributionDto.MajorCategoryDto majorDto = new ProductCategoryDistributionDto.MajorCategoryDto();
            majorDto.setName(major.getProductName());
            List<ProductCategoryDistributionDto.MinorCategoryDto> minorDtos = new ArrayList<>();
            BigDecimal majorStock = BigDecimal.ZERO;
            List<Product> children = minorGroupMap.getOrDefault(major.getId(), new ArrayList<>());
            int childrenSize = children.size();
            // è®¾ç½®å°ç±»çš„æ€»æ•°
            majorDto.setValue(String.valueOf(childrenSize));
            for (Product minor : minorCategories) {
                if (major.getId().equals(minor.getParentId())) {
                    BigDecimal stock = productTotalStockMap.getOrDefault(minor.getId(), BigDecimal.ZERO);
                    ProductCategoryDistributionDto.MinorCategoryDto minorDto = new ProductCategoryDistributionDto.MinorCategoryDto();
                    minorDto.setName(minor.getProductName());
                    minorDto.setValue(stock.stripTrailingZeros().toPlainString());
                    if (totalInventory.compareTo(BigDecimal.ZERO) > 0) {
                        minorDto.setRate(stock.multiply(new BigDecimal("100"))
                                .divide(totalInventory, 2, RoundingMode.HALF_UP).toString());
                    } else {
                        minorDto.setRate("0.00");
                    }
                    minorDto.setChildren(productModelsMap.getOrDefault(minor.getId(), new ArrayList<>()));
                    minorDtos.add(minorDto);
                    majorStock = majorStock.add(stock);
                }
            }
            majorDto.setValue(majorStock.stripTrailingZeros().toPlainString());
            if (totalInventory.compareTo(BigDecimal.ZERO) > 0) {
                majorDto.setRate(majorStock.multiply(new BigDecimal("100"))
                        .divide(totalInventory, 2, RoundingMode.HALF_UP).toString());
            // è®¡ç®—占比
            if (totalMinorCount > 0) {
                BigDecimal rate = BigDecimal.valueOf(childrenSize)
                        .multiply(new BigDecimal("100"))
                        .divide(BigDecimal.valueOf(totalMinorCount), 2, RoundingMode.HALF_UP);
                majorDto.setRate(rate.toString());
            } else {
                majorDto.setRate("0.00");
            }
            List<ProductCategoryDistributionDto.MinorCategoryDto> minorDtos = new ArrayList<>();
            for (Product minor : children) {
                ProductCategoryDistributionDto.MinorCategoryDto minorDto = new ProductCategoryDistributionDto.MinorCategoryDto();
                minorDto.setName(minor.getProductName());
                minorDto.setValue("0");
                minorDto.setRate("0.00");
                minorDto.setChildren(new ArrayList<>());
                minorDtos.add(minorDto);
            }
            majorDto.setChildren(minorDtos);
            majorItems.add(majorDto);
@@ -932,15 +886,15 @@
        LocalDate startDate = null;
        LocalDate endDate = null;
        switch (type) {
            case 0:
            case 1:
                startDate = today.with(DayOfWeek.MONDAY);
                endDate = today.with(DayOfWeek.SUNDAY);
                break;
            case 1:
            case 2:
                startDate = today.with(TemporalAdjusters.firstDayOfMonth());
                endDate = today.with(TemporalAdjusters.lastDayOfMonth());
                break;
            case 2:
            case 3:
                Month currentMonth = today.getMonth();
                Month firstMonthOfQuarter = currentMonth.firstMonthOfQuarter();
                Month lastMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2);
src/main/java/com/ruoyi/http/service/RealTimeEnergyConsumptionService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
package com.ruoyi.http.service;
/**
 * @author :yys
 * @date : 2026/1/27 16:02
 */
public interface RealTimeEnergyConsumptionService {
}
src/main/java/com/ruoyi/http/service/impl/RealTimeEnergyConsumptionServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,130 @@
package com.ruoyi.http.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.http.service.RealTimeEnergyConsumptionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @author :yys
 * @date : 2026/1/27 16:02
 */
@Service
@Slf4j
public class RealTimeEnergyConsumptionServiceImpl implements RealTimeEnergyConsumptionService {
    private static final String URL = "https://new.e-elitech.cn/api/data-api";
    private static final String TOKEN_URL = "/elitechAccess/getToken";
    private static final String REAL_TIME_URL = "/elitechAccess/v2/getRealTimeData"; //获取设备实时数据
    private static final String KET_ID = "75804708";
    private static final String KEY_SECRET = "xTUGToozKpYgUPqTsZzB";
    private static final String USER_NAME = "用户30773662";
    private static final String PASS_WORD = "y17775163675";
    private static final String DEVICE_GUID = "90444196515214284663";
    /**
     * æ ¹æ®paramCode提取探头参数
     * @param paramList è®¾å¤‡å‚数数组
     * @param targetCode ç›®æ ‡æŽ¢å¤´ç¼–码
     * @return æŽ¢å¤´å‚数对象(包含name/value/unit)
     */
    private static JSONObject getProbeParam(JSONArray paramList, String targetCode) {
        for (int i = 0; i < paramList.size(); i++) {
            JSONObject paramObj = paramList.getJSONObject(i);
            if (targetCode.equals(paramObj.getString("paramCode"))) {
                return paramObj;
            }
        }
        return new JSONObject(); // æœªåŒ¹é…åˆ°è¿”回空对象,避免空指针
    }
    /**
     * å®žæ—¶èŽ·å–æ¸©æ¹¿åº¦ï¼ŒäºŒæ°§åŒ–ç¢³æ•°æ®
     */
    public static void main(String[] args) {
        String realTimeData = getRealTimeData(getToken());
        Map<String, Object> map = JSON.parseObject(realTimeData, Map.class);
        if(map.get("code").equals(0)){
            // 1. è§£æžå¤–层data为JSON数组(接口返回的设备列表)
            JSONArray deviceList = JSON.parseArray(map.get("data").toString());
            // 2. éåŽ†è®¾å¤‡åˆ—è¡¨ï¼ˆæ­¤å¤„ä»…å–ç¬¬ä¸€ä¸ªè®¾å¤‡ï¼Œè‹¥æœ‰å¤šä¸ªè®¾å¤‡å¯å¾ªçŽ¯å¤„ç†ï¼‰
            if (!deviceList.isEmpty()) {
                JSONObject deviceObj = deviceList.getJSONObject(0);
                // 3. è§£æžè®¾å¤‡å†…的参数数组(所有paramCode对应的参数)
                JSONArray paramList = deviceObj.getJSONArray("data");
                // 4. å®šä¹‰ç›®æ ‡æŽ¢å¤´çš„paramCode,按需扩展
                String[] targetCodes = {"0100", "0110", "0120", "0130"};
                for (String code : targetCodes) {
                    // 5. éåŽ†å‚æ•°æ•°ç»„ï¼ŒåŒ¹é…ç›®æ ‡paramCode
                    for (int i = 0; i < paramList.size(); i++) {
                        JSONObject paramObj = paramList.getJSONObject(i);
                        String currentCode = paramObj.getString("paramCode");
                        if (code.equals(currentCode)) {
                            // 6. æå–核心字段(值、单位、探头名称)
                            String paramName = paramObj.getString("paramName"); // æŽ¢å¤´1/探头2...
                            String value = paramObj.getString("value");       // æ•°å€¼ï¼ˆ345.80/24.90...)
                            String unitCode = paramObj.getString("unitCode"); // å•位(Lux/℃/%RH/ppm)
                            // 7. ä¸šåŠ¡å¤„ç†ï¼šæ‰“å°/赋值/存储等(按需修改)
                            System.out.println(paramName + ":" + value + " " + unitCode);
                            // åŒ¹é…åˆ°åŽç›´æŽ¥è·³å‡ºå†…层循环,提升效率
                            break;
                        }
                    }
                }
            }
        }
        System.out.println();
    }
    public static String getToken(){
        Map<String, String> param = new HashMap<>();
        param.put("keyId", KET_ID);
        param.put("keySecret", KEY_SECRET);
        param.put("userName", USER_NAME);
        param.put("password", PASS_WORD);
        log.info("请求参数:{}", JSON.toJSONString( param));
        String result = HttpUtils.sendPostJson(URL + TOKEN_URL, JSON.toJSONString(param));
        log.info("返回结果:{}", result);
        Map<String, Object> map = JSON.parseObject(result, Map.class);
        if (map.get("code").equals(0)) {
            Object token = map.get("data");
            log.info("token:{}", token);
            return token.toString();
        }
        return result;
    }
    public static String getRealTimeData(String  token){
        Map<String, Object> param = new HashMap<>();
        param.put("keyId", KET_ID);
        param.put("keySecret", KEY_SECRET);
        param.put("deviceGuids", Collections.singletonList(DEVICE_GUID));
        log.info("请求参数:{}", JSON.toJSONString( param));
        String result = HttpUtils.sendPostJson(URL + REAL_TIME_URL, JSON.toJSONString(param),token);
        log.info("返回结果:{}", result);
        return result;
    }
}