From e3270141db2dd6c755e6a7b40930dcfa24585cb4 Mon Sep 17 00:00:00 2001
From: liurunyu <lry9898@163.com>
Date: 星期二, 08 七月 2025 15:01:14 +0800
Subject: [PATCH] Merge branch 'master' of http://8.140.179.55:20000/r/pipIrr-SV

---
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/PipIrrIrrigateApplication.java          |    2 
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/ValveOpen.java              |   32 
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/IrrigateGroupSv.java      |   10 
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/dto/IrrigateSchedule.java  |   32 
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/dto/PlanSimple.java        |   28 
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/DtoBase.java                |   31 
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigation/IrrigationSv.java            |  176 ++++
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/IrrigatePlanCtrl.java      |  212 +++++
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/qo/QoIrrigatePlan.java     |   41 +
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/IrrigatePlanSv.java        |  756 ++++++++++++++++++
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/enums/OperateTypeENUM.java |   25 
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/CommandSv.java                  |  861 +++++++++++++++++++++
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/AutomaticClose.java         |   46 +
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/resources/application-self.yml                                     |   11 
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/dto/IrrigatePlan.java      |   55 +
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/ValveClose.java             |   53 +
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/qo/QoGroup.java           |    5 
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigation/IrrigationCtrl.java          |   45 +
 pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/IrrigateGroupCtrl.java    |   20 
 19 files changed, 2,440 insertions(+), 1 deletions(-)

diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/PipIrrIrrigateApplication.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/PipIrrIrrigateApplication.java
index 297f1a0..1dadaee 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/PipIrrIrrigateApplication.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/PipIrrIrrigateApplication.java
@@ -18,7 +18,7 @@
                 })
         }
 )
-@MapperScan({"com.dy.pipIrrGlobal.daoIr", "com.dy.pipIrrGlobal.daoIr","com.dy.pipIrrGlobal.daoFi"})
+@MapperScan({"com.dy.pipIrrGlobal.daoRm", "com.dy.pipIrrGlobal.daoPr", "com.dy.pipIrrGlobal.daoSe", "com.dy.pipIrrGlobal.daoBa", "com.dy.pipIrrGlobal.daoIr", "com.dy.pipIrrGlobal.daoIr","com.dy.pipIrrGlobal.daoFi"})
 public class PipIrrIrrigateApplication {
 
     public static void main(String[] args) {
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/CommandSv.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/CommandSv.java
new file mode 100644
index 0000000..9a32004
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/CommandSv.java
@@ -0,0 +1,861 @@
+package com.dy.pipIrrIrrigate.command;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.dy.common.multiDataSource.DataSourceContext;
+import com.dy.common.mw.protocol.Command;
+import com.dy.common.mw.protocol.p206V1.CodeV1;
+import com.dy.common.mw.protocol.p206V1.ProtocolConstantV206V1;
+import com.dy.common.mw.protocol.p206V1.downVos.Com97Vo;
+import com.dy.common.mw.protocol.p206V1.downVos.Com98Vo;
+import com.dy.common.mw.protocol.p206V1.downVos.ComA1Vo;
+import com.dy.common.mw.protocol.p206V2.ProtocolConstantV206V2;
+import com.dy.common.mw.protocol.p206V202404.CodeV202404;
+import com.dy.common.mw.protocol.p206V202404.ProtocolConstantV206V202404;
+import com.dy.common.mw.protocol.p206V202404.downVos.ComCd92_A2Vo;
+import com.dy.common.mw.protocol.p206V202404.downVos.ComCd93_A3Vo;
+import com.dy.common.util.IDLongGenerator;
+import com.dy.common.webUtil.BaseResponse;
+import com.dy.common.webUtil.QueryResultVo;
+import com.dy.pipIrrGlobal.command.ComSupport;
+import com.dy.pipIrrGlobal.command.dto.Param;
+import com.dy.pipIrrGlobal.daoIr.IrIntakeOperateMapper;
+import com.dy.pipIrrGlobal.daoPr.PrIntakeControllerMapper;
+import com.dy.pipIrrGlobal.daoPr.PrIntakeMapper;
+import com.dy.pipIrrGlobal.daoPr.PrIntakeVcMapper;
+import com.dy.pipIrrGlobal.daoPr.PrWaterPriceMapper;
+import com.dy.pipIrrGlobal.daoRm.RmCommandHistoryMapper;
+import com.dy.pipIrrGlobal.daoRm.RmIrrigateProfileMapper;
+import com.dy.pipIrrGlobal.daoRm.RmOpenCloseValveLastMapper;
+import com.dy.pipIrrGlobal.daoSe.SeClientCardMapper;
+import com.dy.pipIrrGlobal.daoSe.SeVirtualCardMapper;
+import com.dy.pipIrrGlobal.pojoIr.IrIntakeOperate;
+import com.dy.pipIrrGlobal.pojoRm.RmCommandHistory;
+import com.dy.pipIrrGlobal.pojoSe.SeClientCard;
+import com.dy.pipIrrGlobal.voRm.VoIrrigaterProfile;
+import com.dy.pipIrrGlobal.voRm.VoRtuAndVc;
+import com.dy.pipIrrGlobal.voRm.VoUnclosedValve;
+import com.dy.pipIrrGlobal.voSe.VoVirtualCard;
+import com.dy.pipIrrIrrigate.command.dto.AutomaticClose;
+import com.dy.pipIrrIrrigate.command.dto.ValveClose;
+import com.dy.pipIrrIrrigate.command.dto.ValveOpen;
+import com.dy.pipIrrIrrigate.irrigation.IrrigationSv;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-07-02 9:10
+ * @LastEditTime 2025-07-02 9:10
+ * @Description
+ */
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class CommandSv extends ComSupport {
+    private final RmCommandHistoryMapper rmCommandHistoryMapper;
+    private final SeVirtualCardMapper seVirtualCardMapper;
+    private final PrIntakeMapper prIntakeMapper;
+    private final PrWaterPriceMapper prWaterPriceMapper;
+    private final PrIntakeVcMapper prIntakeVcMapper;
+    private final SeClientCardMapper seClientCardMapper;
+    private final RmIrrigateProfileMapper rmIrrigateProfileMapper;
+    private final RmOpenCloseValveLastMapper rmOpenCloseValveLastMapper;
+    //private final PrCommonIntakesMapper prCommonIntakesMapper;
+    private final IrIntakeOperateMapper irIntakeOperateMapper;
+    //private final IrrigatePlanSv irrigatePlanSv;
+    private final IrrigationSv irrigationSv;
+    private final PrIntakeControllerMapper prIntakeControllerMapper;
+
+    //@Value("${mw.rtuCallbackUrl_wx}")
+    //private String rtuCallbackUrl_wx;
+
+    @Value("${mw.rtuCallbackUrl_rm}")
+    private String rtuCallbackUrl_rm;
+
+    /**
+     * pro_mw锛氬睘鎬�
+     * tag浠庢帶鍒跺櫒涓幏鍙�
+     * key_mw锛歶rl鐨刱ey
+     */
+    private Environment env = null;
+    private String pro_mw = "mw";
+    private String key_mw = "comSendUrl";
+
+    @Autowired
+    public CommandSv(RmCommandHistoryMapper rmCommandHistoryMapper, RmOpenCloseValveLastMapper rmOpenCloseValveLastMapper, SeVirtualCardMapper seVirtualCardMapper, PrIntakeMapper prIntakeMapper, PrWaterPriceMapper prWaterPriceMapper, PrIntakeVcMapper prIntakeVcMapper, SeClientCardMapper seClientCardMapper, RmIrrigateProfileMapper rmIrrigateProfileMapper, Environment env, IrIntakeOperateMapper irIntakeOperateMapper, IrrigationSv irrigationSv, PrIntakeControllerMapper prIntakeControllerMapper) {
+        this.rmCommandHistoryMapper = rmCommandHistoryMapper;
+        this.rmOpenCloseValveLastMapper = rmOpenCloseValveLastMapper;
+        //this.prCommonIntakesMapper = prCommonIntakesMapper;
+        this.seVirtualCardMapper = seVirtualCardMapper;
+        this.prIntakeMapper = prIntakeMapper;
+        this.prWaterPriceMapper = prWaterPriceMapper;
+        this.prIntakeVcMapper = prIntakeVcMapper;
+        this.seClientCardMapper = seClientCardMapper;
+        this.rmIrrigateProfileMapper = rmIrrigateProfileMapper;
+        this.env = env;
+        this.irIntakeOperateMapper = irIntakeOperateMapper;
+        this.irrigationSv = irrigationSv;
+        this.prIntakeControllerMapper = prIntakeControllerMapper;
+    }
+
+    /**
+     * 铏氭嫙鍗D鎹㈣櫄鎷熷崱瀵硅薄
+     *
+     * @param vcId
+     * @return
+     */
+    public VoVirtualCard getVcById(Long vcId) {
+        return seVirtualCardMapper.getVcById(vcId);
+    }
+
+    /**
+     * 鑾峰彇姘翠环
+     *
+     * @return
+     */
+    public Double getPrice() {
+        return prWaterPriceMapper.getPrice();
+    }
+
+    /**
+     * 鏍规嵁鎿嶄綔鍛業D鑾峰彇鏈叧闃�璁板綍锛堝寘鍚湪绾挎儏鍐碉級
+     *
+     * @param operator
+     * @return
+     */
+    public List<VoUnclosedValve> getUnclosedValves(Long operator) {
+        Command com = new Command();
+        com.id = Command.defaultId;
+        com.code = "LCD0001";
+        com.type = "innerCommand";
+        comSendUrl = env.getProperty(pro_mw + "." + DataSourceContext.get() + "." + key_mw);
+        JSONObject response = (JSONObject) JSON.toJSON(sendCom2Mw(com));
+        String aa = response.toJSONString();
+
+        JSONArray jsonArray = new JSONArray();
+        if (response != null && response.getString("code").equals("0001")) {
+            JSONObject attachment = response.getJSONObject("content").getJSONObject("attachment");
+            if (attachment != null) {
+                attachment.forEach((key, value) -> {
+                    JSONObject jsonObject = new JSONObject();
+                    jsonObject.put("rtuAddr", key);
+                    jsonObject.put("isOnLine", value);
+                    jsonArray.add(jsonObject);
+                });
+            }
+            //System.out.println(jsonArray.toJSONString());
+        }
+
+        /**
+         * 鑾峰彇鏈叧闃�鐨凴TU鍦板潃鍜岃櫄鎷熷崱缂栧彿瀵规暟缁�
+         * 閬嶅巻鏁扮粍鑾峰彇鏈�鍚庡懡浠ゆ棩蹇桰D闆嗗悎
+         */
+        List<VoRtuAndVc> rtus = rmCommandHistoryMapper.getUnclosedRtus(operator);
+        String comIds = "";
+        if (rtus != null && rtus.size() > 0) {
+            for (int i = 0; i < rtus.size(); i++) {
+                Long comId = rmCommandHistoryMapper.getLastComId(rtus.get(i).getRtuAddr(), rtus.get(i).getVcNum());
+                if (comId > 0) {
+                    comIds = comIds + "\"" + comId + "\",";
+                }
+            }
+        }
+
+        if (comIds.length() > 0) {
+            comIds = comIds.substring(0, comIds.length() - 1);
+            List<VoUnclosedValve> res = rmCommandHistoryMapper.getUnclosedValves(jsonArray.toJSONString(), comIds);
+            if (res != null) {
+                return res;
+            }
+        }
+        return new ArrayList<>();
+    }
+
+    /**
+     * 涓烘寚瀹氾紙闃�鎺у櫒鍦板潃銆佹按鍗$紪鍙枫�佹棤鍏抽榾璁板綍锛夊紑鍏抽榾鏈�鏂拌褰曟坊鍔犲叧闃�鏃堕棿锛屼娇涔嬩笉鍦ㄦ湭鍏抽榾璁板綍涓樉绀�
+     *
+     * @param rtuAddr
+     * @param icCardNo
+     * @return
+     */
+    public Integer addClostTime(String rtuAddr, String icCardNo) {
+        return rmOpenCloseValveLastMapper.addCloseTime(rtuAddr, icCardNo);
+    }
+
+    /**
+     * 鏍规嵁鍙栨按鍙D鑾峰彇涓庝箣缁戝畾铏氭嫙鍗D
+     *
+     * @param intakeId
+     * @return
+     */
+    public Long getVcIdByIntakeId(Long intakeId) {
+        return prIntakeVcMapper.getVcIdByIntakeId(intakeId);
+    }
+
+    /**
+     * 鏍规嵁姘村崱缂栧彿鑾峰彇姘村崱瀵硅薄锛岃繙绋嬪厖鍊间娇鐢�
+     *
+     * @param cardId
+     * @return
+     */
+    public SeClientCard geClientCardByCardId(Long cardId) {
+        return seClientCardMapper.selectByPrimaryKey(cardId);
+    }
+
+    /**
+     * 娣诲姞鍛戒护鏃ュ織
+     *
+     * @param po 鍛戒护鏃ュ織瀵硅薄
+     * @return 瀛楃涓茬被鍨嬬殑涓婚敭
+     */
+    public Long insert(RmCommandHistory po) {
+        rmCommandHistoryMapper.insert(po);
+        return po.getComId();
+    }
+
+    /**
+     * 淇敼鍛戒护鏃ュ織淇℃伅
+     *
+     * @param po 鍛戒护鏃ュ織瀵硅薄
+     * @return 褰卞搷璁板綍鏁伴噺
+     */
+    public Integer update(RmCommandHistory po) {
+        return rmCommandHistoryMapper.updateByPrimaryKeySelective(po);
+    }
+
+    /**
+     * 鍙栨按鍙e悕绉版崲鍙栨按鍙D锛屾壂鐮佸紑闃�浣跨敤
+     *
+     * @param intakeName
+     * @return
+     */
+    public Long getIntakeIdByName(String intakeName) {
+        return prIntakeMapper.getIntakeIdByName(intakeName);
+    }
+
+    /**
+     * 鏍规嵁閰嶇疆绫诲瀷鑾峰彇閰嶇疆鍊�
+     *
+     * @param type
+     * @return
+     */
+    QueryResultVo<List<VoIrrigaterProfile>> getIrrPro(Integer type) {
+        QueryResultVo<List<VoIrrigaterProfile>> rsVo = new QueryResultVo<>();
+        rsVo.obj = rmIrrigateProfileMapper.getIrrPro(type);
+        return rsVo;
+    }
+
+    /**
+     * 娣诲姞鍙栨按鍙f搷浣滆褰曪紝杞亴杩囩▼鍛戒护涓嬪彂鏃朵娇鐢�
+     *
+     * @param po
+     * @return
+     */
+    public Long addIntakeOperate(IrIntakeOperate po) {
+        irIntakeOperateMapper.insert(po);
+        return po.getId();
+    }
+
+    /**
+     * 瀹氭椂鍏抽榾寮忚鍒掑紑闃�
+     *
+     * @param automaticClose
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Map planedOpenTimedClose(AutomaticClose automaticClose, Long planId, Byte operatetype, Date startTime, Integer duration) {
+        Long intakeId = automaticClose.getIntakeId();
+        Long vcId = automaticClose.getVcId();
+        Date plannedOpenTime = automaticClose.getPlannedOpenTime();
+        Integer minutes = automaticClose.getMinutes();
+        Long operator = automaticClose.getOperator();
+        Byte openType = automaticClose.getOpenType();
+        Long comId = new IDLongGenerator().generate();
+        String intakeName = Optional.ofNullable(prIntakeControllerMapper.getIntakeNameById(intakeId)).orElse("");
+
+        // 濡傛灉鏄疆鐏�
+        Long operateId = null;
+        if (openType != null && openType == 1) {
+            IrIntakeOperate irIntakeOperate = new IrIntakeOperate();
+            irIntakeOperate.setPlanId(planId);
+            irIntakeOperate.setOperateType(operatetype);
+            irIntakeOperate.setCommandId(comId);
+            irIntakeOperate.setIntakeId(intakeId);
+            irIntakeOperate.setStartTime(startTime);
+            irIntakeOperate.setDuration(duration);
+
+            operateId = addIntakeOperate(irIntakeOperate);
+            if (operateId == null) {
+                Map map = new HashMap<>();
+                map.put("success", false);
+                map.put("msg", "娣诲姞鍙栨按鍙f搷浣滆褰曞け璐�");
+                map.put("content", null);
+                return map;
+            }
+        }
+
+        Integer year = Integer.parseInt(String.format("%tY", plannedOpenTime));
+        Integer month = Integer.parseInt(String.format("%tm", plannedOpenTime));
+        Integer day = Integer.parseInt(String.format("%td", plannedOpenTime));
+        Integer hour = Integer.parseInt(String.format("%tH", plannedOpenTime));
+        Integer minute = Integer.parseInt(String.format("%tM", plannedOpenTime));
+
+        /**
+         * 濡傛灉鍐滄埛閫夋嫨浜嗚櫄鎷熷崱锛屽垯浣跨敤璇ヨ櫄鎷熷崱
+         * 濡傛灉鍐滄埛鏈�夋嫨铏氭嫙鍗★紝鍒欐牴鎹彇姘村彛ID鑾峰彇涓庝箣缁戝畾鐨勮櫄鎷熷崱
+         * 濡傛灉鍙栨按鍙f病鏈変笌涔嬬粦瀹氱殑铏氭嫙鍗★紝鍒欐彁绀哄啘鎴烽�夋嫨涓�寮犺櫄鎷熷崱
+         */
+        if (vcId == null) {
+            vcId = getVcIdByIntakeId(intakeId);
+            if (vcId == null) {
+                irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "璇烽�夋嫨涓�寮犺櫄鎷熷崱(" + intakeId + ")");
+
+                Map map = new HashMap<>();
+                map.put("success", false);
+                map.put("msg", "璇烽�夋嫨涓�寮犺櫄鎷熷崱(" + intakeName + ")");
+                map.put("content", null);
+                return map;
+            }
+        }
+
+        // 铏氭嫙鍗D鎹㈣櫄鎷熷崱瀵硅薄
+        VoVirtualCard vc = getVcById(vcId);
+        if (vc == null) {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "璇烽�夋嫨涓�寮犺櫄鎷熷崱(" + intakeId + ")");
+
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "璇烽�夋嫨涓�寮犺櫄鎷熷崱(" + intakeName + ")");
+            map.put("content", null);
+            return map;
+        }
+        String vcNum = vc.getVcNum().toString();
+        Double moneyRemain = vc.getMoney();
+        if (moneyRemain < 100) {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "铏氭嫙鍗′綑棰濅笉瓒筹紝璇峰厖鍊�" + "(" + intakeName + ")");
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "铏氭嫙鍗′綑棰濅笉瓒筹紝璇峰厖鍊�");
+            map.put("content", null);
+            return map;
+        }
+
+        // 鑾峰彇姘翠环
+        Double waterPrice = getPrice();
+        if (waterPrice == null) {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "鏈彇鍒版按浠�(" + intakeName + ")");
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "鏈彇鍒版按浠�");
+            map.put("content", null);
+            return map;
+        }
+
+        // 鍙栨按鍙D鎹㈤榾鎺у櫒鍦板潃鍙婇�氳鍗忚
+        JSONObject job_rtu = getRtu(intakeId, null);
+        if (job_rtu == null) {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "闃�鎺у櫒涓嶅瓨鍦�(" + intakeName + ")");
+
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "闃�鎺у櫒涓嶅瓨鍦�");
+            map.put("content", null);
+            return map;
+        }
+        String rtuAddr = job_rtu.getString("rtuAddr");
+        String protocol = job_rtu.getString("protocol");
+
+        comSendUrl = env.getProperty(pro_mw + "." + DataSourceContext.get() + "." + key_mw);
+
+        // 鐢熸垚璁㈠崟鍙�
+        String orderNo = generateOrderNo();
+        if (orderNo == null) {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "鏈敓鎴愯鍗曞彿(" + intakeName + ")");
+
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "鏈敓鎴愯鍗曞彿");
+            map.put("content", null);
+            return map;
+        }
+
+        // 鍒ゆ柇闃�鎺у櫒鏄惁宸茬粡寮�闃�
+        Boolean isOpen = irrigationSv.getOpenCloseStatus(rtuAddr);
+        if (isOpen) {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, intakeName + " 闃�闂ㄤ负鎵撳紑鐘舵��");
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", intakeName + " 闃�闂ㄤ负鎵撳紑鐘舵��");
+            map.put("content", null);
+            return map;
+        }
+
+        String commandCode = null;
+        if (protocol.equals(ProtocolConstantV206V202404.protocolName)) {
+            Map map = new HashMap<>();
+            map.put("success", true);
+            map.put("msg", "寮�闃�鎴愬姛");
+            map.put("content", null);
+            return map;
+        } else if (protocol.equals(ProtocolConstantV206V1.protocolName) || protocol.equals(ProtocolConstantV206V2.protocolName)) {
+            // 鑾峰彇鍔熻兘鐮�
+            commandCode = CodeV1.cd_A1;
+
+            // 鍒涘缓瑙嗗浘
+            ComA1Vo param = new ComA1Vo();
+            param.setIcCardNo(vcNum);
+            param.setMoneyRemain(moneyRemain);
+            param.setWaterPrice(waterPrice);
+            param.setMinutes(minutes);
+            param.setYear(year);
+            param.setMonth(month);
+            param.setDay(day);
+            param.setHour(hour);
+            param.setMinute(minute);
+            param.setOrderNo(orderNo);
+
+            /**
+             * 鏋勯�犲懡浠ゃ�佸彂閫佸懡浠ゅ苟澶勭悊璇锋眰缁撴灉鍙婃墽琛岀粨鏋�
+             * 1 鍑嗗鍙傛暟
+             * 2 璋冪敤鍏叡鏂规硶
+             */
+            Param myParam = new Param();
+            myParam.setComId(comId);
+            myParam.setComType((byte) 1);
+            myParam.setCommandCode(commandCode);
+            myParam.setCommandName(CodeV1.getCodeName(commandCode));
+            myParam.setIntakeId(intakeId);
+            myParam.setRtuAddr(rtuAddr);
+            myParam.setProtocol(protocol);
+            myParam.setVcId(vcId);
+            myParam.setParam(param);
+            myParam.setRtuResultSendWebUrl(rtuCallbackUrl_rm);
+            myParam.setOperator(operator);
+            myParam.setOpenType(openType);
+
+            BaseResponse<Boolean> result = dealWithCommandResult(myParam);
+            // 濡傛灉鍛戒护鎵ц澶辫触锛屽垯鍐嶆鎵ц鍛戒护
+            if (!result.isSuccess()) {
+                Long newComId = new IDLongGenerator().generate();
+                myParam.setComId(newComId);
+                result = dealWithCommandResult(myParam);
+
+                // 鏍规嵁operateId淇敼鍙栨按鍙f搷浣滆褰曚腑鐨刢ommandId
+                irIntakeOperateMapper.updateCommandId(newComId, operateId);
+            }
+
+            Map map = new HashMap<>();
+            map.put("success", result.isSuccess());
+            map.put("msg", result.getMsg());
+            map.put("content", result.getContent());
+            return map;
+        } else {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "绯荤粺鏆備笉鏀寔璇ュ崗璁�" + "(" + intakeId + ")");
+
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "绯荤粺鏆備笉鏀寔璇ュ崗璁�");
+            map.put("content", null);
+            return map;
+        }
+    }
+
+    /**
+     * 灏忕▼搴忚繙绋嬪紑闃�
+     *
+     * @param valve
+     * @param planId
+     * @param operatetype
+     * @return
+     */
+    public Map openWx(ValveOpen valve, Long planId, Byte operatetype) {
+        Long intakeId = valve.getIntakeId();
+        String intakeName = valve.getIntakeName();
+        Long vcId = valve.getVcId();
+        Boolean forceOpen = valve.getForceOpen();
+        Long operator = valve.getOperator();
+        Byte openType = valve.getOpenType();
+        Long comId = new IDLongGenerator().generate();
+
+        // 濡傛灉鏄疆鐏�
+        if (openType != null && openType == 1) {
+            IrIntakeOperate irIntakeOperate = new IrIntakeOperate();
+            irIntakeOperate.setPlanId(planId);
+            irIntakeOperate.setOperateType(operatetype);
+            irIntakeOperate.setCommandId(comId);
+            irIntakeOperate.setIntakeId(intakeId);
+
+            Long id = addIntakeOperate(irIntakeOperate);
+            if (id == null) {
+                Map map = new HashMap<>();
+                map.put("success", false);
+                map.put("msg", "娣诲姞鍙栨按鍙f搷浣滆褰曞け璐�");
+                map.put("content", null);
+                return map;
+            }
+        }
+
+        if (intakeId == null && intakeName == null) {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "璇烽�夋嫨涓�涓彇姘村彛(" + intakeId + ")");
+
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "璇烽�夋嫨涓�涓彇姘村彛(" + intakeId + ")");
+            map.put("content", null);
+            return map;
+            //return BaseResponseUtils.buildErrorMsg(WechatResultCode.PLEASE_SELECT_A_INTAKE.getMessage());
+        }
+
+        // intakeName鎹ntakeId
+        if (intakeId == null) {
+            intakeId = getIntakeIdByName(intakeName);
+            if (intakeId == null) {
+                irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "璇烽�夋嫨涓�涓彇姘村彛(" + intakeId + ")");
+
+                Map map = new HashMap<>();
+                map.put("success", false);
+                map.put("msg", "璇烽�夋嫨涓�涓彇姘村彛(" + intakeId + ")");
+                map.put("content", null);
+                return map;
+                //return BaseResponseUtils.buildErrorMsg(WechatResultCode.PLEASE_SELECT_A_INTAKE.getMessage());
+            }
+        }
+
+        /**
+         * 濡傛灉鍐滄埛閫夋嫨浜嗚櫄鎷熷崱锛屽垯浣跨敤璇ヨ櫄鎷熷崱
+         * 濡傛灉鍐滄埛鏈�夋嫨铏氭嫙鍗★紝鍒欐牴鎹彇姘村彛ID鑾峰彇涓庝箣缁戝畾鐨勮櫄鎷熷崱
+         * 濡傛灉鍙栨按鍙f病鏈変笌涔嬬粦瀹氱殑铏氭嫙鍗★紝鍒欐彁绀哄啘鎴烽�夋嫨涓�寮犺櫄鎷熷崱
+         */
+        if (vcId == null) {
+            vcId = getVcIdByIntakeId(intakeId);
+            if (vcId == null) {
+                irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "璇烽�夋嫨涓�寮犺櫄鎷熷崱(" + intakeId + ")");
+
+                Map map = new HashMap<>();
+                map.put("success", false);
+                map.put("msg", "璇烽�夋嫨涓�寮犺櫄鎷熷崱(" + intakeId + ")");
+                map.put("content", null);
+                return map;
+                //return BaseResponseUtils.buildErrorMsg(WechatResultCode.PLEASE_SELECT_A_VC.getMessage());
+            }
+        }
+
+        // 铏氭嫙鍗D鎹㈣櫄鎷熷崱瀵硅薄
+        VoVirtualCard vc = getVcById(vcId);
+        if (vc == null) {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "璇烽�夋嫨涓�寮犺櫄鎷熷崱(" + intakeId + ")");
+
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "璇烽�夋嫨涓�寮犺櫄鎷熷崱(" + intakeId + ")");
+            map.put("content", null);
+            return map;
+            //return BaseResponseUtils.buildErrorMsg(WechatResultCode.PLEASE_SELECT_A_VC.getMessage());
+        }
+
+        // 铏氭嫙鍗$姸鎬佷负浣跨敤涓紝涓斾笉鏄己鍒跺紑闃�鏃舵彁绀�
+        if (vc.getInUse() && !forceOpen) {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "浣跨敤涓櫄鎷熷崱涓嶈兘鐢ㄦ潵寮�闃�(" + intakeId + ")");
+
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "浣跨敤涓櫄鎷熷崱涓嶈兘鐢ㄦ潵寮�闃�(" + intakeId + ")");
+            map.put("content", null);
+            return map;
+            //return BaseResponseUtils.buildCodeMsg(WechatResultCode.IN_USE_VC_CANNOT_OPEN_VALVE.getCode(), WechatResultCode.IN_USE_VC_CANNOT_OPEN_VALVE.getMessage());
+        }
+
+        // 鑾峰彇姘翠环
+        Double waterPrice = getPrice();
+        if (waterPrice == null) {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "鏈彇鍒版按浠�(" + intakeId + ")");
+
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "鏈彇鍒版按浠�(" + intakeId + ")");
+            map.put("content", null);
+            return map;
+            //return BaseResponseUtils.buildErrorMsg(WechatResultCode.NO_WATER_PRICE.getMessage());
+        }
+
+        // 鍙栨按鍙D鎹㈤榾鎺у櫒鍦板潃鍙婇�氳鍗忚
+        JSONObject job_rtu = getRtu(intakeId, null);
+        if (job_rtu == null) {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "闃�鎺у櫒涓嶅瓨鍦�(" + intakeId + ")");
+
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "闃�鎺у櫒涓嶅瓨鍦�(" + intakeId + ")");
+            map.put("content", null);
+            return map;
+            //return BaseResponseUtils.buildErrorMsg(WechatResultCode.RTU_NOT_EXIST.getMessage());
+        }
+        String rtuAddr = job_rtu.getString("rtuAddr");
+        String protocol = job_rtu.getString("protocol");
+
+        comSendUrl = env.getProperty(pro_mw + "." + DataSourceContext.get() + "." + key_mw);
+
+        // 鐢熸垚璁㈠崟鍙�
+        String orderNo = generateOrderNo();
+        if (orderNo == null) {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "鏈敓鎴愯鍗曞彿(" + intakeId + ")");
+
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "鏈敓鎴愯鍗曞彿(" + intakeId + ")");
+            map.put("content", null);
+            return map;
+            //return BaseResponseUtils.buildErrorMsg(WechatResultCode.NO_ORDER_NUMBER.getMessage());
+        }
+
+        String commandCode = null;
+        if (protocol.equals(ProtocolConstantV206V202404.protocolName)) {
+            // 鑾峰彇鍔熻兘鐮�
+            commandCode = CodeV202404.cd_A2;
+
+            // 鍒涘缓瑙嗗浘
+            ComCd92_A2Vo param = new ComCd92_A2Vo();
+            param.controllerType = controllerType;
+            param.projectNo = projectNo;
+            param.icCardNo = vc.getVcNum().toString();
+            param.waterRemain = 0.0;
+            param.moneyRemain = vc.getMoney();
+            param.waterPrice = waterPrice;
+            param.elePrice = 0.0;
+            param.orderNo = orderNo;
+
+            /**
+             * 鏋勯�犲懡浠ゃ�佸彂閫佸懡浠ゅ苟澶勭悊璇锋眰缁撴灉鍙婃墽琛岀粨鏋�
+             * 1 鍑嗗鍙傛暟
+             * 2 璋冪敤鍏叡鏂规硶
+             */
+            Param myParam = new Param();
+            myParam.setComId(comId);
+            myParam.setComType((byte) 1);
+            myParam.setCommandCode(commandCode);
+            myParam.setCommandName(CodeV202404.getCodeName(commandCode));
+            myParam.setIntakeId(intakeId);
+            myParam.setRtuAddr(rtuAddr);
+            myParam.setProtocol(protocol);
+            myParam.setVcId(vcId);
+            myParam.setParam(param);
+            myParam.setRtuResultSendWebUrl(rtuCallbackUrl_rm);
+            myParam.setOperator(operator);
+            //BaseResponse<Boolean> result = dealWithCommandResult(myParam);
+
+            BaseResponse<Boolean> result = dealWithCommandResult(myParam);
+            // 濡傛灉鍛戒护鎵ц澶辫触锛屽垯鍐嶆鎵ц鍛戒护
+            if (!result.isSuccess()) {
+                myParam.setComId(new IDLongGenerator().generate());
+                result = dealWithCommandResult(myParam);
+            }
+
+            Map map = new HashMap<>();
+            map.put("success", result.isSuccess());
+            map.put("msg", result.getMsg());
+            map.put("content", result.getContent());
+            return map;
+
+        } else if (protocol.equals(ProtocolConstantV206V1.protocolName) || protocol.equals(ProtocolConstantV206V2.protocolName)) {
+            // 鑾峰彇鍔熻兘鐮�
+            commandCode = CodeV1.cd_97;
+
+            // 鍒涘缓瑙嗗浘
+            Com97Vo param = new Com97Vo();
+            param.icCardNo = vc.getVcNum().toString();
+            param.moneyRemain = vc.getMoney();
+            param.waterPrice = waterPrice;
+            param.orderNo = orderNo;
+
+            /**
+             * 鏋勯�犲懡浠ゃ�佸彂閫佸懡浠ゅ苟澶勭悊璇锋眰缁撴灉鍙婃墽琛岀粨鏋�
+             * 1 鍑嗗鍙傛暟
+             * 2 璋冪敤鍏叡鏂规硶
+             */
+            Param myParam = new Param();
+            myParam.setComId(comId);
+            myParam.setComType((byte) 1);
+            myParam.setCommandCode(commandCode);
+            myParam.setCommandName(CodeV1.getCodeName(commandCode));
+            myParam.setIntakeId(intakeId);
+            myParam.setRtuAddr(rtuAddr);
+            myParam.setProtocol(protocol);
+            myParam.setVcId(vcId);
+            myParam.setParam(param);
+            myParam.setRtuResultSendWebUrl(rtuCallbackUrl_rm);
+            myParam.setOperator(operator);
+            //return dealWithCommandResult(myParam);
+            BaseResponse<Boolean> result = dealWithCommandResult(myParam);
+
+            Map map = new HashMap<>();
+            map.put("success", result.isSuccess());
+            map.put("msg", result.getMsg());
+            map.put("content", result.getContent());
+            return map;
+        } else {
+            //return BaseResponseUtils.buildErrorMsg("绯荤粺鏆備笉鏀寔璇ュ崗璁�");
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "绯荤粺鏆備笉鏀寔璇ュ崗璁�" + "(" + intakeId + ")");
+
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "绯荤粺鏆備笉鏀寔璇ュ崗璁�");
+            map.put("content", null);
+            return map;
+        }
+    }
+
+    /**
+     * 灏忕▼搴忚繙绋嬪叧闃�
+     *
+     * @param valve
+     * @param planId
+     * @param operatetype
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Map closeWx(ValveClose valve, Long planId, Byte operatetype) {
+        String rtuAddr = valve.getRtuAddr();
+        String vcNum = valve.getVcNum();
+        Long vcId = Optional.ofNullable(seVirtualCardMapper.getVcIdByNum(vcNum)).orElse(0L);
+        String orderNo = valve.getOrderNo();
+        Long operator = valve.getOperator();
+        Byte openType = valve.getOpenType();
+        Long comId = new IDLongGenerator().generate();
+
+        // 闃�鎺у櫒鍦板潃鎹㈠彇姘村彛ID鍜岄�氳鍗忚
+        JSONObject job_rtu = getRtu(null, rtuAddr);
+        if (job_rtu == null) {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "闃�鎺у櫒涓嶅瓨鍦�");
+
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "闃�鎺у櫒涓嶅瓨鍦�");
+            map.put("content", null);
+            return map;
+            //return BaseResponseUtils.buildErrorMsg(WechatResultCode.RTU_NOT_EXIST.getMessage());
+        }
+        Long intakeId = job_rtu.getLong("intakeId");
+        String protocol = job_rtu.getString("protocol");
+
+        // 濡傛灉鏄疆鐏�
+        if (openType != null && openType == 1) {
+            IrIntakeOperate irIntakeOperate = new IrIntakeOperate();
+            irIntakeOperate.setPlanId(planId);
+            irIntakeOperate.setOperateType(operatetype);
+            irIntakeOperate.setCommandId(comId);
+            irIntakeOperate.setIntakeId(intakeId);
+            irIntakeOperate.setCommandResult((byte) 1);
+
+            Long id = addIntakeOperate(irIntakeOperate);
+            if (id == null) {
+                Map map = new HashMap<>();
+                map.put("success", false);
+                map.put("msg", "娣诲姞鍙栨按鍙f搷浣滆褰曞け璐�");
+                map.put("content", null);
+                return map;
+            }
+        }
+
+        comSendUrl = env.getProperty(pro_mw + "." + DataSourceContext.get() + "." + key_mw);
+
+        String commandCode = null;
+        if (protocol.equals(ProtocolConstantV206V202404.protocolName)) {
+            // 鑾峰彇鍔熻兘鐮�
+            commandCode = CodeV202404.cd_A3;
+
+            // 鍒涘缓瑙嗗浘
+            ComCd93_A3Vo param = new ComCd93_A3Vo();
+            param.controllerType = controllerType;
+            param.projectNo = projectNo;
+            param.icCardNo = vcNum;
+            param.orderNo = orderNo;
+
+            /**
+             * 鏋勯�犲懡浠ゃ�佸彂閫佸懡浠ゅ苟澶勭悊璇锋眰缁撴灉鍙婃墽琛岀粨鏋�
+             * 1 鍑嗗鍙傛暟
+             * 2 璋冪敤鍏叡鏂规硶
+             */
+            Param myParam = new Param();
+            myParam.setComId(comId);
+            myParam.setComType((byte) 2);
+            myParam.setCommandCode(commandCode);
+            myParam.setCommandName(CodeV202404.getCodeName(commandCode));
+            myParam.setIntakeId(intakeId);
+            myParam.setRtuAddr(rtuAddr);
+            myParam.setProtocol(protocol);
+            myParam.setVcId(vcId);
+            myParam.setParam(param);
+            myParam.setRtuResultSendWebUrl(rtuCallbackUrl_rm);
+            myParam.setOperator(operator);
+            //return dealWithCommandResult(myParam);
+            BaseResponse<Boolean> result = dealWithCommandResult(myParam);
+
+            Map map = new HashMap<>();
+            map.put("success", result.isSuccess());
+            map.put("msg", result.getMsg());
+            map.put("content", result.getContent());
+            return map;
+        } else if (protocol.equals(ProtocolConstantV206V1.protocolName) || protocol.equals(ProtocolConstantV206V2.protocolName)) {
+            // 鑾峰彇鍔熻兘鐮�
+            commandCode = CodeV1.cd_98;
+
+            // 鍒涘缓瑙嗗浘
+            Com98Vo param = new Com98Vo();
+            param.icCardNo = vcNum;
+            param.orderNo = orderNo;
+
+            /**
+             * 鏋勯�犲懡浠ゃ�佸彂閫佸懡浠ゅ苟澶勭悊璇锋眰缁撴灉鍙婃墽琛岀粨鏋�
+             * 1 鍑嗗鍙傛暟
+             * 2 璋冪敤鍏叡鏂规硶
+             */
+            Param myParam = new Param();
+            myParam.setComId(comId);
+            myParam.setComType((byte) 2);
+            myParam.setCommandCode(commandCode);
+            myParam.setCommandName(CodeV1.getCodeName(commandCode));
+            myParam.setIntakeId(intakeId);
+            myParam.setRtuAddr(rtuAddr);
+            myParam.setProtocol(protocol);
+            myParam.setVcId(vcId);
+            myParam.setParam(param);
+            myParam.setRtuResultSendWebUrl(rtuCallbackUrl_rm);
+            myParam.setOperator(operator);
+            //return dealWithCommandResult(myParam);
+
+            BaseResponse<Boolean> result = dealWithCommandResult(myParam);
+            // 濡傛灉鍛戒护鎵ц澶辫触锛屽垯鍐嶆鎵ц鍛戒护
+            if (!result.isSuccess()) {
+                myParam.setComId(new IDLongGenerator().generate());
+                result = dealWithCommandResult(myParam);
+            }
+
+            Map map = new HashMap<>();
+            map.put("success", result.isSuccess());
+            map.put("msg", result.getMsg());
+            map.put("content", result.getContent());
+            return map;
+
+        } else {
+            irIntakeOperateMapper.updateByCommandId(comId, (byte) 2, "绯荤粺鏆備笉鏀寔璇ュ崗璁�" + "(" + intakeId + ")");
+
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "绯荤粺鏆備笉鏀寔璇ュ崗璁�");
+            map.put("content", null);
+            return map;
+            //return BaseResponseUtils.buildErrorMsg("绯荤粺鏆備笉鏀寔璇ュ崗璁�");
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/AutomaticClose.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/AutomaticClose.java
new file mode 100644
index 0000000..7444067
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/AutomaticClose.java
@@ -0,0 +1,46 @@
+package com.dy.pipIrrIrrigate.command.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-07-02 8:52
+ * @LastEditTime 2025-07-02 8:52
+ * @Description
+ */
+
+@Data
+@EqualsAndHashCode(callSuper=false)
+public class AutomaticClose extends DtoBase {
+    public static final long serialVersionUID = 202507020853001L;
+
+    /**
+     * 铏氭嫙鍗D
+     */
+    private Long vcId;
+
+    /**
+     * 璁″垝寮�闃�鏃堕棿
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date plannedOpenTime;
+
+    /**
+     * 鐢ㄦ按鏃堕暱锛屾嫢鏈夊畾鏃跺叧闃�
+     */
+    private Integer minutes;
+
+    /**
+     * 棰勭敤姘撮噺锛屾嫢鏈夊畾閲忓叧闃�
+     */
+    private Integer waterAmount;
+
+    /**
+     * 寮�闃�绫诲瀷锛�1-杞亴
+     */
+    private Byte openType;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/DtoBase.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/DtoBase.java
new file mode 100644
index 0000000..900a2d3
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/DtoBase.java
@@ -0,0 +1,31 @@
+package com.dy.pipIrrIrrigate.command.dto;
+
+import lombok.Data;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-07-02 8:54
+ * @LastEditTime 2025-07-02 8:54
+ * @Description 璁剧疆鍛戒护鍩虹被
+ */
+
+@Data
+public class DtoBase {
+    public static final long serialVersionUID = 202507020904001L;
+
+    /**
+     * 鍙栨按鍙D
+     */
+    private Long intakeId;
+
+    /**
+     * 鍙栨按鍙e悕绉�
+     */
+    private String intakeName;
+
+    /**
+     * 鎿嶄綔浜�
+     */
+    //@NotNull(message = "鎿嶄綔浜轰笉鑳戒负绌�")
+    private Long operator;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/ValveClose.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/ValveClose.java
new file mode 100644
index 0000000..e90e707
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/ValveClose.java
@@ -0,0 +1,53 @@
+package com.dy.pipIrrIrrigate.command.dto;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-07-02 9:42
+ * @LastEditTime 2025-07-02 9:42
+ * @Description 璁剧疆鍛戒护瀛愮被-杩滅▼鍏抽榾浼犺緭瀵硅薄
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class ValveClose {
+    public static final long serialVersionUID = 202507020943001L;
+
+    /**
+     * 闃�鎺у櫒鍦板潃
+     */
+    @NotBlank(message = "闃�鎺у櫒鍦板潃涓嶈兘涓虹┖")
+    private String rtuAddr;
+    /**
+     * 铏氭嫙鍗$紪鍙�
+     */
+    @NotBlank(message = "铏氭嫙鍗$紪鍙蜂笉鑳戒负绌�")
+    private String vcNum;
+
+    /**
+     * 寮�闃�鏃剁敓鎴愮殑璁㈠崟鍙�
+     */
+    @NotBlank(message = "璁㈠崟鍙蜂笉鑳戒负绌�")
+    private String orderNo;
+
+    /**
+     * 鐢ㄦ埛绫诲瀷 1-骞冲彴锛�2-APP
+     */
+    //@NotNull(message = "鎿嶄綔绫诲瀷涓嶈兘涓虹┖")
+    //private Integer userType;
+
+    /**
+     * 鎿嶄綔浜�
+     */
+    @NotNull(message = "鎿嶄綔浜轰笉鑳戒负绌�")
+    private Long operator;
+
+    /**
+     * 寮�闃�绫诲瀷锛�1-杞亴
+     */
+    private Byte openType;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/ValveOpen.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/ValveOpen.java
new file mode 100644
index 0000000..86731bc
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/command/dto/ValveOpen.java
@@ -0,0 +1,32 @@
+package com.dy.pipIrrIrrigate.command.dto;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-07-02 9:23
+ * @LastEditTime 2025-07-02 9:23
+ * @Description 璁剧疆鍛戒护瀛愮被-杩滅▼寮�闃�浼犺緭瀵硅薄
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class ValveOpen extends DtoBase {
+    public static final long serialVersionUID = 202507020924001L;
+
+    /**
+     * 铏氭嫙鍗D
+     */
+    private Long vcId;
+
+    /**
+     * 寮哄埗寮�闃�
+     */
+    private Boolean forceOpen = false;
+
+    /**
+     * 寮�闃�绫诲瀷锛�1-杞亴
+     */
+    private Byte openType;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/IrrigateGroupCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/IrrigateGroupCtrl.java
index 77706f0..64770f0 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/IrrigateGroupCtrl.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/IrrigateGroupCtrl.java
@@ -541,6 +541,26 @@
     }
 
     /**
+     * 鑾峰彇椤圭洰涓嬭疆鐏岀粍
+     * @param qo
+     * @return
+     */
+    @GetMapping(path = "/getGroupsByProjectId")
+    @SsoAop()
+    public BaseResponse<List<VoGroupSimple>> getGroupsByProjectId(QoGroup qo) {
+        if(qo.getProjectId() == null) {
+            return BaseResponseUtils.buildErrorMsg("璇烽�夋嫨椤圭洰");
+        }
+
+        try {
+            return BaseResponseUtils.buildSuccess(irrigateGroupSv.getGroupsByProjectId(qo));
+        } catch (Exception e) {
+            log.error("鑾峰彇杞亴缁勮褰曞紓甯�", e);
+            return BaseResponseUtils.buildException(e.getMessage());
+        }
+    }
+
+    /**
      * 鑾峰彇鍏ㄩ儴杞亴缁勶紝鏂颁唬鐮�
      * @return
      */
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/IrrigateGroupSv.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/IrrigateGroupSv.java
index da54d34..876239a 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/IrrigateGroupSv.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/IrrigateGroupSv.java
@@ -347,6 +347,16 @@
     }
 
     /**
+     * 鑾峰彇椤圭洰涓嬭疆鐏岀粍
+     * @param queryVo
+     * @return
+     */
+    public List<VoGroupSimple> getGroupsByProjectId(QoGroup queryVo) {
+        Map<String, Object> params = (Map<String, Object>) PojoUtils.generalize(queryVo);
+        return irIrrigateGroupMapper.getSimpleGroups(params);
+    }
+
+    /**
      * 鏌ヨ鍏ㄩ儴杞亴缁�
      * @return
      */
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/qo/QoGroup.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/qo/QoGroup.java
index c528d15..231ac19 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/qo/QoGroup.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigateGroup/qo/QoGroup.java
@@ -18,4 +18,9 @@
      * 杞亴缁勭紪鐮�
      */
     private String groupCode;
+
+    /**
+     * 椤圭洰ID
+     */
+    private Long projectId;
 }
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/IrrigatePlanCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/IrrigatePlanCtrl.java
new file mode 100644
index 0000000..f6425a2
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/IrrigatePlanCtrl.java
@@ -0,0 +1,212 @@
+package com.dy.pipIrrIrrigate.irrigatePlan;
+
+import com.dy.common.aop.SsoAop;
+import com.dy.common.webUtil.BaseResponse;
+import com.dy.common.webUtil.BaseResponseUtils;
+import com.dy.common.webUtil.QueryConditionVo;
+import com.dy.common.webUtil.QueryResultVo;
+import com.dy.pipIrrGlobal.voIr.VoPlanDetails;
+import com.dy.pipIrrGlobal.voIr.VoPlans;
+import com.dy.pipIrrIrrigate.irrigatePlan.dto.IrrigatePlan;
+import com.dy.pipIrrIrrigate.irrigatePlan.dto.PlanSimple;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-06-30 14:58
+ * @LastEditTime 2025-06-30 14:58
+ * @Description
+ */
+
+@Slf4j
+@RestController
+@RequestMapping(path = "plan")
+@RequiredArgsConstructor
+public class IrrigatePlanCtrl {
+    private final IrrigatePlanSv irrigatePlanSv;
+
+    /**
+     * 鍒涘缓鐏屾簤璁″垝
+     * @param planAndSchedule
+     * @param bindingResult
+     * @return
+     */
+    @PostMapping(path = "createPlan", consumes = MediaType.APPLICATION_JSON_VALUE)
+    @SsoAop()
+    public BaseResponse<Boolean> createPlan(@RequestBody @Valid IrrigatePlan planAndSchedule, BindingResult bindingResult){
+        if(bindingResult != null && bindingResult.hasErrors()){
+            return BaseResponseUtils.buildErrorMsg(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
+        }
+
+        Map map_result = irrigatePlanSv.createPlan(planAndSchedule);
+        if(map_result.get("success").equals(false)) {
+            return BaseResponseUtils.buildErrorMsg(map_result.get("msg").toString());
+        }
+        return BaseResponseUtils.buildSuccess() ;
+    }
+
+    /**
+     * 鍒犻櫎鐏屾簤璁″垝
+     * @param planSimple
+     * @param bindingResult
+     * @return
+     */
+    @PostMapping(path = "deletePlan")
+    @SsoAop()
+    public BaseResponse<Boolean> deletePlan(@RequestBody @Valid PlanSimple planSimple, BindingResult bindingResult) {
+        if(bindingResult != null && bindingResult.hasErrors()){
+            return BaseResponseUtils.buildErrorMsg(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
+        }
+
+        Map map_result = irrigatePlanSv.deletePlan(planSimple);
+        if(map_result.get("success").equals(false)) {
+            return BaseResponseUtils.buildErrorMsg(map_result.get("msg").toString());
+        }
+        return BaseResponseUtils.buildSuccess() ;
+    }
+
+    /**
+     * 鍙戝竷鐏屾簤璁″垝
+     * 1. 淇敼鐏屾簤璁″垝鐘舵�佷负鍙戝竷鐘舵��
+     * 2. 娣诲姞鐏屾簤璁″垝鎿嶄綔璁板綍
+     * 3. 鐢熸垚寮�闃�璁″垝
+     * @param planSimple
+     * @param bindingResult
+     * @return
+     */
+    @PostMapping(path = "publishPlan", consumes = MediaType.APPLICATION_JSON_VALUE)
+    @SsoAop()
+    public BaseResponse<Boolean> publishPlan(@RequestBody @Valid PlanSimple planSimple, BindingResult bindingResult){
+        if(bindingResult != null && bindingResult.hasErrors()){
+            return BaseResponseUtils.buildErrorMsg(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
+        }
+
+        Map map_result = irrigatePlanSv.publishPlan(planSimple);
+        if(map_result.get("success").equals(false)) {
+            return BaseResponseUtils.buildErrorMsg(map_result.get("msg").toString());
+        }
+        return BaseResponseUtils.buildSuccess() ;
+    }
+
+    /**
+     * 缁堟鐏屾簤璁″垝
+     * @param planSimple
+     * @param bindingResult
+     * @return
+     */
+    @PostMapping(path = "terminatePlan", consumes = MediaType.APPLICATION_JSON_VALUE)
+    @SsoAop()
+    public BaseResponse<Boolean> terminatePlan(@RequestBody @Valid PlanSimple planSimple, BindingResult bindingResult){
+        if(bindingResult != null && bindingResult.hasErrors()){
+            return BaseResponseUtils.buildErrorMsg(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
+        }
+
+        Map map_result = irrigatePlanSv.terminatePlan(planSimple);
+        if(map_result.get("success").equals(false)) {
+            return BaseResponseUtils.buildErrorMsg(map_result.get("msg").toString());
+        }
+        return BaseResponseUtils.buildSuccess() ;
+    }
+
+    /**
+     * 鑾峰彇鏈畬鎴愮殑璁″垝鍒楄〃锛岀亴婧夋ā鍧楄鍒掑垪琛ㄩ〉浣跨敤
+     * @return
+     */
+    @GetMapping(path = "/getNotCompletePlans")
+    @SsoAop()
+    public BaseResponse<List<VoPlans>> getNotCompletePlans() {
+        try {
+            List<VoPlans> res = irrigatePlanSv.getNotCompletePlans();
+            return BaseResponseUtils.buildSuccess(res);
+        } catch (Exception e) {
+            log.error("鑾峰彇鏈畬鐨勮鍒掑紓甯�", e);
+            return BaseResponseUtils.buildException(e.getMessage());
+        }
+    }
+
+    /**
+     * 鑾峰彇宸插畬鎴愮殑璁″垝鍒楄〃锛岀亴婧夋ā鍧楄鍒掑垪琛ㄩ〉浣跨敤
+     * @return
+     */
+    @GetMapping(path = "/getCompletedPlans")
+    @SsoAop()
+    public BaseResponse<QueryResultVo<List<VoPlans>>> getCompletedPlans(QueryConditionVo qo) {
+        try {
+            return BaseResponseUtils.buildSuccess(irrigatePlanSv.getCompletedPlans(qo));
+        } catch (Exception e) {
+            log.error("鑾峰彇椤圭洰璁板綍寮傚父", e);
+            return BaseResponseUtils.buildException(e.getMessage());
+        }
+    }
+
+    /**
+     * 鏍规嵁璁″垝ID鑾峰彇璁″垝鍙戝竷缁撴灉
+     * @param planId
+     * @return
+     */
+    @GetMapping(path = "/getPublishResults")
+    @SsoAop()
+    public BaseResponse<VoPlanDetails> getPublishResults(@RequestParam Long planId) {
+        if(planId == null) {
+            return BaseResponseUtils.buildErrorMsg("璁″垝ID涓嶈兘涓虹┖");
+        }
+
+        try {
+            VoPlanDetails res = irrigatePlanSv.getPublishResults(planId);
+            return BaseResponseUtils.buildSuccess(res);
+        } catch (Exception e) {
+            log.error("鑾峰彇璁″垝鍙戝竷缁撴灉寮傚父", e);
+            return BaseResponseUtils.buildException(e.getMessage());
+        }
+    }
+
+    /**
+     * 鏍规嵁璁″垝ID鑾峰彇璁″垝缁堟鎿嶄綔缁撴灉
+     * @param planId
+     * @return
+     */
+    @GetMapping(path = "/getTerminateResults")
+    @SsoAop()
+    public BaseResponse<VoPlanDetails> getTerminateResults(@RequestParam Long planId) {
+        if(planId == null) {
+            return BaseResponseUtils.buildErrorMsg("璁″垝ID涓嶈兘涓虹┖");
+        }
+
+        try {
+            VoPlanDetails res = irrigatePlanSv.getTerminateResults(planId);
+            return BaseResponseUtils.buildSuccess(res);
+        } catch (Exception e) {
+            log.error("鑾峰彇璁″垝鍙戝竷缁撴灉寮傚父", e);
+            return BaseResponseUtils.buildException(e.getMessage());
+        }
+    }
+
+    /**
+     * 鏍规嵁璁″垝ID鑾峰彇璁″垝鏈�鏂扮姸鎬�
+     * @param planId
+     * @return
+     */
+    @GetMapping(path = "/getPlanLatestState")
+    @SsoAop()
+    public BaseResponse<Integer> getPlanLatestState(@RequestParam Long planId) {
+        if(planId == null) {
+            return BaseResponseUtils.buildErrorMsg("璁″垝ID涓嶈兘涓虹┖");
+        }
+
+        try {
+            return BaseResponseUtils.buildSuccess(irrigatePlanSv.getPlanLatestState(planId));
+        } catch (Exception e) {
+            log.error("鑾峰彇鏈畬鐨勮鍒掑紓甯�", e);
+            return BaseResponseUtils.buildException(e.getMessage());
+        }
+    }
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/IrrigatePlanSv.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/IrrigatePlanSv.java
new file mode 100644
index 0000000..6e43aca
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/IrrigatePlanSv.java
@@ -0,0 +1,756 @@
+package com.dy.pipIrrIrrigate.irrigatePlan;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.dy.common.multiDataSource.DataSourceContext;
+import com.dy.common.mw.protocol.Command;
+import com.dy.common.mw.protocol.CommandType;
+import com.dy.common.webUtil.BaseResponse;
+import com.dy.common.webUtil.BaseResponseUtils;
+import com.dy.common.webUtil.QueryConditionVo;
+import com.dy.common.webUtil.QueryResultVo;
+import com.dy.pipIrrGlobal.daoIr.*;
+import com.dy.pipIrrGlobal.daoRm.RmCommandHistoryMapper;
+import com.dy.pipIrrGlobal.pojoIr.IrIrrigatePlan;
+import com.dy.pipIrrGlobal.pojoIr.IrIrrigateSchedule;
+import com.dy.pipIrrGlobal.pojoIr.IrPlanOperate;
+import com.dy.pipIrrGlobal.pojoIr.IrPlanSchedule;
+import com.dy.pipIrrGlobal.rtuMw.CodeLocal;
+import com.dy.pipIrrGlobal.voIr.*;
+import com.dy.pipIrrGlobal.voRm.VoIntakeVc;
+import com.dy.pipIrrIrrigate.command.CommandSv;
+import com.dy.pipIrrIrrigate.command.dto.AutomaticClose;
+import com.dy.pipIrrIrrigate.command.dto.ValveClose;
+import com.dy.pipIrrIrrigate.irrigatePlan.dto.IrrigatePlan;
+import com.dy.pipIrrIrrigate.irrigatePlan.dto.IrrigateSchedule;
+import com.dy.pipIrrIrrigate.irrigatePlan.dto.PlanSimple;
+import com.dy.pipIrrIrrigate.irrigatePlan.enums.OperateTypeENUM;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.common.utils.PojoUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.env.Environment;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-06-30 14:58
+ * @LastEditTime 2025-06-30 14:58
+ * @Description
+ */
+
+@Slf4j
+@Service
+public class IrrigatePlanSv {
+    @Autowired
+    private IrIrrigatePlanMapper irrigatePlanMapper;
+
+    @Autowired
+    private IrIrrigateScheduleMapper irIrrigateScheduleMapper;
+
+    @Autowired
+    private IrPlanScheduleMapper irPlanScheduleMapper;
+
+    @Autowired
+    private IrPlanOperateMapper irPlanOperateMapper;
+
+    @Autowired
+    private IrGroupIntakeMapper irGroupIntakeMapper;
+
+    @Autowired
+    private CommandSv commandSv;
+
+    @Autowired
+    private IrIntakeOperateMapper irIntakeOperateMapper;
+
+    @Autowired
+    private RmCommandHistoryMapper rmdCommandHistoryMapper;
+
+    @Autowired
+    private IrIrrigateGroupMapper irIrrigateGroupMapper;
+
+    protected String comSendUrl;
+    private String key_mw = "comSendUrl";
+
+    @Value("${irr.plan.delay:5}")
+    private Integer irrPlanDelay;//杞亴涓鍒掑紑闃�鐨勫欢杩熸椂闀�
+
+    private static final Integer irrPlanDelayDefault = 5;//杞亴涓鍒掑紑闃�鐨勯粯璁ゅ欢杩熸椂闀�
+
+    @Value("${irr.plan.preOpeningTime:10}")
+    private Integer preOpeningTime;
+
+    @Value("${irr.plan.planTerminateLimitMinutes:5}")
+    private Integer planTerminateLimitMinutes; // 璁″垝缁堟鍚庨檺鍒跺彂甯冩柊璁″垝鐨勬椂闂撮棿闅�(鍒嗛挓)
+
+    /**
+     * 娣诲姞鐏屾簤璁″垝
+     *
+     * @param po
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Long addIrrigatePlan(IrIrrigatePlan po) {
+        irrigatePlanMapper.insert(po);
+        return po.getId();
+    }
+
+    /**
+     * 娣诲姞鐏屾簤娆″簭璁板綍
+     *
+     * @param po
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Long addIrrigateSchedule(IrIrrigateSchedule po) {
+        irIrrigateScheduleMapper.insert(po);
+        return po.getId();
+    }
+
+    /**
+     * 娣诲姞璁″垝娆″簭鍏宠仈璁板綍
+     *
+     * @param po
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Long addPlanSchedule(IrPlanSchedule po) {
+        irPlanScheduleMapper.insert(po);
+        return po.getId();
+    }
+
+    /**
+     * 娣诲姞鐏屾簤璁″垝鎿嶄綔璁板綍
+     *
+     * @param po
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Long addPlanOperate(IrPlanOperate po) {
+        irPlanOperateMapper.insert(po);
+        return po.getId();
+    }
+
+    /**
+     * 鍒涘缓鐏屾簤璁″垝
+     * 1. 娣诲姞鐏屾簤璁″垝
+     * 2. 娣诲姞鐏屾簤娆″簭
+     * 3. 娣诲姞鐏屾簤璁″垝鎿嶄綔璁板綍
+     * @param planAndSchedule
+     * @return
+     */
+    public Map createPlan(IrrigatePlan planAndSchedule) {
+        Map map = new HashMap<>();
+        map.put("success", false);
+
+        Long projectId = planAndSchedule.getProjectId();
+        Long operatorId = planAndSchedule.getOperatorId();
+        Byte startupMode = planAndSchedule.getStartupMode();
+        Date planStartTime = planAndSchedule.getPlanStartTime();;
+        Date planStopTime = null;
+
+        Integer duration = 0;
+        for(IrrigateSchedule schedule : planAndSchedule.getSchedules()){
+            duration = duration + schedule.getDuration();
+        }
+
+        if(startupMode == 2){
+            if(planStartTime == null) {
+                map.put("msg", "鑷姩鍚姩妯″紡蹇呴』鎸囧畾璁″垝鍚姩鏃堕棿");
+                map.put("content", null);
+                return map;
+            }
+
+            LocalDateTime startTime = planStartTime.toInstant().atZone(ZoneId.systemDefault()) .toLocalDateTime();
+            LocalDateTime currentTime = LocalDateTime.now();
+            currentTime = currentTime.plusHours(8);
+
+            if(!startTime.isAfter(currentTime)) {
+                map.put("msg", "鍚姩鏃堕棿涓嶈兘鍦�8灏忔椂涔嬪唴");
+                map.put("content", null);
+                return map;
+            }
+        }
+
+        IrIrrigatePlan plan = new IrIrrigatePlan();
+        plan.setProjectId(projectId);
+        plan.setPlanName(planAndSchedule.getPlanName());
+        plan.setStartupMode(startupMode);
+        plan.setPlanStartTime(planStartTime);
+        plan.setDuration(duration);
+        plan.setPlanState((byte)1);
+        plan.setExecutingState((byte)1);
+        plan.setDeleted(0L);
+
+        Long planId = addIrrigatePlan(plan);
+        if(planId == null) {
+            map.put("msg", "鍒涘缓鐏屾簤璁″垝澶辫触");
+            map.put("content", null);
+            return map;
+        }
+
+        // 娣诲姞鐏屾簤娆″簭鍙婅鍒掓搴忓叧鑱旇〃
+        Integer sort = 1;
+        for(IrrigateSchedule schedule : planAndSchedule.getSchedules()){
+            IrIrrigateSchedule po = new IrIrrigateSchedule();
+            po.setGroupId(schedule.getGroupId());
+            po.setDuration(schedule.getDuration());
+            po.setCurrentState((byte)1);
+            Long scheduleId = addIrrigateSchedule(po);
+            if(scheduleId == null) {
+                map.put("msg", "鍒涘缓鐏屾簤娆″簭澶辫触");
+                map.put("content", null);
+                return map;
+            }
+
+            IrPlanSchedule planSchedule = new IrPlanSchedule();
+            planSchedule.setPlanId(planId);
+            planSchedule.setScheduleId(scheduleId);
+            planSchedule.setSort(sort++);
+            Long planScheduleId = addPlanSchedule(planSchedule);
+            if(planScheduleId == null) {
+                map.put("msg", "鍒涘缓鐏屾簤娆″簭澶辫触");
+                map.put("content", null);
+                return map;
+            }
+
+        }
+
+        // 娣诲姞鐏屾簤璁″垝鎿嶄綔璁板綍
+        IrPlanOperate planOperate  = new IrPlanOperate();
+        planOperate.setPlanId(planId);
+        planOperate.setOperator(operatorId);
+        planOperate.setOperateType(OperateTypeENUM.CREATE.getCode());
+        planOperate.setOperateTime(new Date());
+        if(addPlanOperate(planOperate) == 0){
+            map.put("msg", "娣诲姞鐏屾簤璁″垝鎿嶄綔璁板綍澶辫触");
+            map.put("content", null);
+            return map;
+        }
+
+        map.put("success", true);
+        map.put("msg", "鐏屾簤璁″垝鍒涘缓鎴愬姛");
+        map.put("content", null);
+        return map;
+    }
+
+    /**
+     * 鍒犻櫎鐏屾簤璁″垝
+     *
+     * @param planSimple
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Map deletePlan(PlanSimple planSimple) {
+        Long planId = planSimple.getPlanId();
+        Long operatorId = planSimple.getOperatorId();
+
+        Integer planState = irrigatePlanMapper.getPlanState(planId);
+        if (planState == null) {
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "鐏屾簤璁″垝涓嶅瓨鍦�");
+            map.put("content", null);
+            return map;
+        }
+        if (planState != 1) {
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "鐏屾簤璁″垝闈炶崏绋跨姸鎬侊紝涓嶅厑璁稿垹闄�");
+            map.put("content", null);
+            return map;
+        }
+
+        try {
+            irrigatePlanMapper.deleteByPrimaryKey(planId);
+            // 娣诲姞鐏屾簤璁″垝鎿嶄綔璁板綍
+            IrPlanOperate planOperate = new IrPlanOperate();
+            planOperate.setPlanId(planId);
+            planOperate.setOperator(operatorId);
+            planOperate.setOperateType(OperateTypeENUM.DELETE.getCode());
+            planOperate.setOperateTime(new Date());
+            addPlanOperate(planOperate);
+
+            Map map = new HashMap<>();
+            map.put("success", true);
+            map.put("msg", "鐏屾簤椤圭洰鍒犻櫎鎴愬姛");
+            map.put("content", null);
+            return map;
+        } catch (Exception e) {
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "鐏屾簤椤圭洰鍒犻櫎澶辫触");
+            map.put("content", null);
+            return map;
+        }
+    }
+
+    /**
+     * 鏍规嵁璁″垝ID鑾峰彇鐏屾簤娆″簭璁板綍
+     *
+     * @param planId
+     * @return
+     */
+    public List<VoIrrigateSchedule> getSchedulesByPlanId(Long planId) {
+        return irIrrigateScheduleMapper.getSchedulesByPlanId(planId);
+    }
+
+    /**
+     * 鏍规嵁鐏屾簤娆″簭ID鏇存柊娆″簭寮�濮嬫椂闂�
+     *
+     * @param scheduleId
+     * @param startTime
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Integer updateScheduleStartTime(Long scheduleId, Date startTime) {
+        return irIrrigateScheduleMapper.updateScheduleStartTime(scheduleId, startTime);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    Integer updatePlanTimes(Date planStartTime, Date planEndTime, Long planId) {
+        return irrigatePlanMapper.updatePlanTimes(planStartTime, planEndTime, planId);
+    }
+
+    /**
+     * 鏍规嵁缁処D鑾峰彇鍙栨按鍙D闆嗗悎
+     *
+     * @param groupId
+     * @return
+     */
+    public List<Long> getIntakeIdsByGroupId(Long groupId) {
+        return irGroupIntakeMapper.getIntakeIdsByGroupId(groupId);
+    }
+
+    /**
+     * 鍙戝竷鐏屾簤璁″垝
+     *
+     * @param planSimple
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Map publishPlan(PlanSimple planSimple) {
+        Long planId = planSimple.getPlanId();
+        Long operatorId = planSimple.getOperatorId();
+        Byte operateType = 1;
+
+        // 妫�鏌ュ綋鍓嶉」鐩槸鍚﹀瓨鍦ㄦ湭瀹屾垚鐨勭亴婧夎鍒�
+        if (irrigatePlanMapper.hasPlan_CurrentProject(planId) > 0) {
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "褰撳墠椤圭洰瀛樺湪鏈畬鎴愮殑鐏屾簤璁″垝");
+            map.put("content", null);
+            return map;
+        }
+
+        // 妫�鏌ュ叾浠栭」鐩腑鏄惁瀛樺湪鏈畬鎴愮殑鐏屾簤璁″垝
+        if (irrigatePlanMapper.hasPlan_OtherProject(planId) > 0) {
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "寰呭彂甯冭鍒掔殑杞亴缁勫湪鍏朵粬椤圭洰鐨勭亴婧夎鍒掍腑锛屼笖璇ヨ鍒掑皻鏈畬鎴�");
+            map.put("content", null);
+            return map;
+        }
+
+        // 妫�鏌�5鍒嗛挓鍐呮槸鍚︽湁缁堟鐨勮鍒掞紝涓旇疆鐏岀粍鏈夐噸鍙�
+        Long lastTerminatedPlanId = irPlanOperateMapper.getLastTerminatedPlanId(planTerminateLimitMinutes);
+        if (lastTerminatedPlanId != null) {
+            // 妫�鏌ュ綋鍓嶈鍒掍笌鏈�杩戠粓姝㈣鍒掔殑杞亴缁勬槸鍚︽湁閲嶅彔
+            if (irrigatePlanMapper.hasPlanOverlapWithTerminated(planId, lastTerminatedPlanId) > 0) {
+                Map map = new HashMap<>();
+                map.put("success", false);
+                map.put("msg", "涓婁竴涓鍒掔粓姝㈠悗" + planTerminateLimitMinutes + "鍒嗛挓鍐呬笉鑳藉彂甯冩柊璁″垝");
+                map.put("content", null);
+                return map;
+            }
+        }
+
+        /**
+         * 鑾峰彇鐏屾簤璁″垝淇℃伅
+         * 鏇存柊鐏屾簤璁″垝璧锋鏃堕棿鍙婅鍒掔姸鎬�
+         */
+        VoPlanSimple plan = irrigatePlanMapper.getPlanSimple(planId);
+        if (plan == null) {
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "鎮ㄨ鍙戝竷鐨勮鍒掍笉瀛樺湪锛屾垨璇ヨ鍒掑凡鍙戝竷");
+            map.put("content", null);
+            return map;
+        }
+
+        Byte startupMode = plan.getStartupMode();
+        Integer duration = plan.getDuration();
+        Date planStartTime = plan.getPlanStartTime();
+        Date planStopTime = null;
+
+        if (startupMode == 1) {
+            planStartTime = new Date();
+        }
+        LocalDateTime startTime = planStartTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+        if (startupMode == 1) {
+            if (irrPlanDelay == null || irrPlanDelay <= 0) {
+                irrPlanDelay = irrPlanDelayDefault;
+            }
+            startTime = startTime.plusMinutes(irrPlanDelay);
+        }
+        planStartTime = Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant());
+
+        // 鏇存柊姣忎釜鐏屾簤娆″簭鐨勫紑濮嬫椂闂村苟璁$畻鏈�鍚庝竴缁勫叧闃�鏃堕棿
+        List<VoIrrigateSchedule> schedules = getSchedulesByPlanId(planId);
+        Date scheduleStartTime = null;
+        LocalDateTime lastScheduleEndTime = null;
+        Integer sort = 0;
+
+        // 绗竴娆¢亶鍘嗭細鏇存柊姣忎釜鐏屾簤娆″簭鐨勫紑濮嬫椂闂�
+        for (VoIrrigateSchedule schedule : schedules) {
+            if (scheduleStartTime == null) {
+                scheduleStartTime = planStartTime;
+            }
+            this.updateScheduleStartTime(schedule.getScheduleId(), scheduleStartTime);
+
+            // 璁$畻褰撳墠娆″簭鐨勭粨鏉熸椂闂�
+            LocalDateTime currentScheduleStartTime = scheduleStartTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+            LocalDateTime currentScheduleEndTime = currentScheduleStartTime.plusMinutes(schedule.getDuration());
+
+            // 鏇存柊鏈�鍚庝竴缁勭殑缁撴潫鏃堕棿
+            lastScheduleEndTime = currentScheduleEndTime;
+
+            // 璁$畻涓嬩竴缁勭殑寮�濮嬫椂闂�
+            LocalDateTime LocalscheduleStartTime = scheduleStartTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+            LocalscheduleStartTime = LocalscheduleStartTime.plusMinutes(schedule.getDuration());
+            LocalscheduleStartTime = LocalscheduleStartTime.minusMinutes(preOpeningTime);
+            scheduleStartTime = Date.from(LocalscheduleStartTime.atZone(ZoneId.systemDefault()).toInstant());
+
+            // 纭繚涓嬩竴缁勭殑寮�濮嬫椂闂翠笉鏃╀簬璁″垝寮�濮嬫椂闂�
+            if (scheduleStartTime.before(planStartTime)) {
+                scheduleStartTime = planStartTime;
+            }
+        }
+
+        // 鏍规嵁鏈�鍚庝竴缁勫叧闃�鏃堕棿璁剧疆璁″垝缁撴潫鏃堕棿
+        if (lastScheduleEndTime != null) {
+            planStopTime = Date.from(lastScheduleEndTime.atZone(ZoneId.systemDefault()).toInstant());
+        } else {
+            // 濡傛灉娌℃湁鐏屾簤娆″簭锛屽垯浣跨敤鍘熸潵鐨勮绠楁柟寮�
+            LocalDateTime stopTime = startTime.plusMinutes(duration);
+            planStopTime = Date.from(stopTime.atZone(ZoneId.systemDefault()).toInstant());
+        }
+
+        // 鏍规嵁璁″垝ID鏇存柊璁″垝淇℃伅锛堣捣姝㈡椂闂淬�佽鍒掔姸鎬侊級
+        if (this.updatePlanTimes(planStartTime, planStopTime, planId) == 0) {
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "璁″垝淇℃伅鏇存柊澶辫触");
+            map.put("content", null);
+            return map;
+        }
+
+        // 娣诲姞鐏屾簤璁″垝鎿嶄綔璁板綍
+        IrPlanOperate planOperate = new IrPlanOperate();
+        planOperate.setPlanId(planId);
+        planOperate.setOperator(operatorId);
+        planOperate.setOperateType(OperateTypeENUM.PUBLISH.getCode());
+        planOperate.setOperateTime(new Date());
+        if (addPlanOperate(planOperate) == 0) {
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "娣诲姞鐏屾簤璁″垝鎿嶄綔璁板綍澶辫触");
+            map.put("content", null);
+            return map;
+        }
+
+        schedules = getSchedulesByPlanId(planId);
+        for (VoIrrigateSchedule schedule : schedules) {
+            Long groupId = schedule.getGroupId();
+            List<Long> intakeIds = getIntakeIdsByGroupId(groupId);
+            if(intakeIds == null || intakeIds.size() <= 0) {
+                Map map = new HashMap<>();
+                map.put("success", false);
+                map.put("msg", "褰撳墠杞亴缁勫唴娌℃湁鏈夋晥鐨勫彇姘村彛");
+                map.put("content", null);
+                return map;
+            }
+            for (Long intakeId : intakeIds) {
+                if (schedule.getDuration() > 0) {
+                    // 浠婂彂甯冪亴婧夋椂闀垮ぇ浜�0鐨�
+                    AutomaticClose automaticClose = new AutomaticClose();
+                    automaticClose.setIntakeId(intakeId);
+                    automaticClose.setPlannedOpenTime(schedule.getStartTime());
+                    automaticClose.setMinutes(schedule.getDuration());
+                    automaticClose.setOperator(operatorId);
+                    automaticClose.setOpenType(Byte.valueOf("1"));
+
+                    commandSv.planedOpenTimedClose(automaticClose, planId, operateType, schedule.getStartTime(), schedule.getDuration());
+                }
+            }
+        }
+
+        Map map = new HashMap<>();
+        map.put("success", true);
+        map.put("msg", "鐏屾簤璁″垝鍙戝竷鎴愬姛");
+        map.put("content", null);
+        return map;
+    }
+
+    /**
+     * 鏍规嵁璁″垝ID鑾峰彇寰呯粓姝㈣鍒掔殑缁撴潫鏃堕棿锛氭湭鍒犻櫎銆佹湭缁堟銆佸凡鍙戝竷銆佸綋鍓嶆椂闂村皬浜庤鍒掔粨鏉熸椂闂�
+     *
+     * @param planId
+     * @return
+     */
+    public Date getToTerminatePlan(Long planId) {
+        return irrigatePlanMapper.getToTerminatePlan(planId);
+    }
+
+    /**
+     * 鏍规嵁璁″垝ID鑾峰彇寰呯粓姝㈢殑鍙栨按鍙e垪琛紙寮�闃�鎴愬姛鐨勶級
+     *
+     * @param planId
+     * @return
+     */
+    public List<VoToTerminateIntakes> getToTerminateIntakes(Long planId) {
+        return irIntakeOperateMapper.getToTerminateIntakes(planId);
+    }
+
+    /**
+     * 鏍规嵁鍛戒护鏃ュ織ID鑾峰彇鍙栨按鍙e強铏氭嫙鍗′俊鎭紝缁堟鐏屾簤璁″垝鏃朵娇鐢紝鐢ㄦ潵鎵ц杩滅▼鍏抽榾
+     *
+     * @param commandId
+     * @return
+     */
+    public VoIntakeVc getValveOpen(Long commandId) {
+        return rmdCommandHistoryMapper.getValveOpen(commandId);
+    }
+
+    /**
+     * 淇敼鐏屾簤璁″垝
+     *
+     * @param po
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Integer updatePlan(IrIrrigatePlan po) {
+        return irrigatePlanMapper.updateByPrimaryKeySelective(po);
+    }
+
+    /**
+     * 鏍规嵁璁″垝ID缁堟鐏屾簤娆″簭锛屽皢鐏屾簤娆″簭鐨勫綋鍓嶇姸鎬佹敼涓哄凡缁堟
+     *
+     * @param planId
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Integer terminateSchedule(Long planId) {
+        return irIrrigateScheduleMapper.terminateSchedule(planId);
+    }
+
+    /**
+     * 缁堟鐏屾簤璁″垝
+     * @param planSimple
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Map terminatePlan(PlanSimple planSimple) {
+        Map map = new HashMap<>();
+        map.put("success", false);
+        map.put("content", null);
+
+        Long planId = planSimple.getPlanId();
+        Long operatorId = planSimple.getOperatorId();
+
+        // 鐢熸垚缁堟寮�濮嬫椂闂淬�佺粓姝㈢亴婧夋椂闀�
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        String terminateStartTimeStr = LocalDate.now().getYear() + "-01-01 00:00:00";
+        Date terminateStartTime = Date.from(LocalDateTime.parse(terminateStartTimeStr, formatter).atZone(ZoneId.systemDefault()).toInstant());
+        Integer terminateDuration = 0;
+
+        // 鍒ゆ柇璇ヨ鍒掓槸鍚﹀彲鎵ц缁堟鎿嶄綔锛氭湭鍒犻櫎銆佹湭缁堟銆佸凡鍙戝竷銆佸綋鍓嶆椂闂村皬浜庤鍒掔粨鏉熸椂闂�
+        Date planStartTime = getToTerminatePlan(planId);
+        if(planStartTime == null){
+            map.put("msg", "璇ヨ鍒掍笉瀛樺湪鎴栦笉鏀寔缁堟鎿嶄綔");
+            return map;
+        }
+
+        List<VoToTerminateIntakes> toTerminateIntakes = getToTerminateIntakes(planId);
+        if(toTerminateIntakes != null && toTerminateIntakes.size() > 0){
+            for(VoToTerminateIntakes toTerminateIntake : toTerminateIntakes){
+                Long intakeId = toTerminateIntake.getIntakeId();
+                Long commandId = toTerminateIntake.getCommandId();
+                Date startTime = toTerminateIntake.getStartTime();
+                Date currentTime = new Date();
+                if(currentTime.before(startTime)){
+                    // 鍙栨秷锛堣鐩栧紑闃�璁″垝锛�
+                    AutomaticClose automaticClose = new AutomaticClose();
+                    automaticClose.setIntakeId(intakeId);
+                    automaticClose.setPlannedOpenTime(terminateStartTime);
+                    automaticClose.setMinutes(terminateDuration);
+                    automaticClose.setOperator(operatorId);
+                    automaticClose.setOpenType(Byte.valueOf("1"));
+
+                    commandSv.planedOpenTimedClose(automaticClose, planId, (byte)2, terminateStartTime, terminateDuration);
+                }else {
+                    // 缁堟锛堣繙绋嬪叧闃�锛�
+                    VoIntakeVc intakeVc = getValveOpen(commandId);
+                    String rtuAddr = intakeVc.getRtuAddr();
+                    String vcNum = intakeVc.getVcNum();
+                    String orderNo = intakeVc.getOrderNo();
+
+                    ValveClose valveClose = new ValveClose();
+                    valveClose.setRtuAddr(rtuAddr);
+                    valveClose.setVcNum(vcNum);
+                    valveClose.setOrderNo(orderNo);
+                    valveClose.setOperator(operatorId);
+                    valveClose.setOpenType(Byte.valueOf("1"));
+                    commandSv.closeWx(valveClose, planId, (byte)3);
+                }
+            }
+        }
+
+        // 缁堟璁″垝
+        IrIrrigatePlan iIrrigatePlan = new IrIrrigatePlan();
+        iIrrigatePlan.setId(planId);
+        iIrrigatePlan.setExecutingState((byte)3);
+        if(updatePlan(iIrrigatePlan) == 0){
+            map.put("msg", "缁堟璁″垝澶辫触");
+            return map;
+        }
+
+        // 缁堟鐏屾簤娆″簭
+        if(terminateSchedule(planId) == 0){
+            map.put("msg", "缁堟鐏屾簤娆″簭澶辫触");
+            return map;
+        }
+
+        // 娣诲姞缁堟鎿嶄綔璁板綍
+        IrPlanOperate planOperate  = new IrPlanOperate();
+        planOperate.setPlanId(planId);
+        planOperate.setOperator(operatorId);
+        planOperate.setOperateType(OperateTypeENUM.TERMINATE.getCode());
+        planOperate.setOperateTime(new Date());
+        if(addPlanOperate(planOperate) == 0){
+            map.put("msg", "娣诲姞缁堟鎿嶄綔璁板綍澶辫触");
+            return map;
+        }
+        map.put("success", true);
+        map.put("msg", "缁堟鐏屾簤璁″垝鎴愬姛");
+        return map;
+    }
+
+    /**
+     * 鑾峰彇鏈畬鎴愮殑璁″垝鍒楄〃锛岀亴婧夋ā鍧楄鍒掑垪琛ㄩ〉浣跨敤
+     *
+     * @return
+     */
+    public List<VoPlans> getNotCompletePlans() {
+        return irrigatePlanMapper.getNotCompletePlans();
+    }
+
+    /**
+     * 鑾峰彇宸插畬鎴愮殑璁″垝鍒楄〃锛岀亴婧夋ā鍧楄鍒掑垪琛ㄩ〉浣跨敤
+     *
+     * @return
+     */
+    public QueryResultVo<List<VoPlans>> getCompletedPlans(QueryConditionVo queryVo) {
+        Map<String, Object> params = (Map<String, Object>) PojoUtils.generalize(queryVo);
+
+        Long itemTotal = (long) irrigatePlanMapper.getCompletedPlansCount(params);
+        QueryResultVo<List<VoPlans>> rsVo = new QueryResultVo<>();
+        rsVo.pageSize = queryVo.pageSize;
+        rsVo.pageCurr = queryVo.pageCurr;
+
+        rsVo.calculateAndSet(itemTotal, params);
+        rsVo.obj = irrigatePlanMapper.getCompletedPlans(params);
+
+        return rsVo;
+    }
+
+    /**
+     * 鏍规嵁璁″垝ID鑾峰彇璁″垝鍙戝竷缁撴灉
+     *
+     * @param planId
+     * @return
+     */
+    public VoPlanDetails getPublishResults(Long planId) {
+        VoPlanDetails planDetails = irrigatePlanMapper.getPlanDetails(planId);
+        if (planDetails == null) {
+            return null;
+        }
+        Integer failureCount = Optional.ofNullable(irIntakeOperateMapper.getFailureCount(planId)).orElse(0);
+        planDetails.setFailureCount(failureCount);
+
+        Date terminateTime = Optional.ofNullable(irPlanOperateMapper.getTerminateTime(planId)).orElse(null);
+
+        List<VoGroupResult> groupResults = irIrrigateGroupMapper.getGroupResult(planId);
+        if (groupResults == null || groupResults.size() == 0) {
+            return null;
+        }
+
+        for (VoGroupResult groupResult : groupResults) {
+            List<VoIntakeResult> intakeResults = irIntakeOperateMapper.getIntakeResult(planId, groupResult.getGroupId());
+            if (intakeResults != null) {
+                groupResult.setPublishResult(intakeResults);
+            }
+        }
+
+        planDetails.setGroups(groupResults);
+        return planDetails;
+
+    }
+
+    /**
+     * 鏍规嵁璁″垝ID鑾峰彇璁″垝缁堟鎿嶄綔缁撴灉
+     *
+     * @param planId
+     * @return
+     */
+    public VoPlanDetails getTerminateResults(Long planId) {
+        // 鑾峰彇璁″垝缁堟鏃堕棿
+        Date terminateTime = Optional.ofNullable(irPlanOperateMapper.getTerminateTime(planId)).orElse(null);
+
+        VoPlanDetails planDetails = irrigatePlanMapper.getPlanDetails_terminate(planId, terminateTime);
+        if (planDetails == null) {
+            return null;
+        }
+        Integer failureCount = Optional.ofNullable(irIntakeOperateMapper.getFailureCount(planId)).orElse(0);
+        planDetails.setFailureCount(failureCount);
+
+        List<VoGroupResult> groupResults = irIrrigateGroupMapper.getGroupResult_terminate(planId, terminateTime);
+        if (groupResults == null || groupResults.size() == 0) {
+            return null;
+        }
+
+        for (VoGroupResult groupResult : groupResults) {
+            List<VoIntakeResult> intakeResults = irIntakeOperateMapper.getIntakeResult(planId, groupResult.getGroupId());
+            if (intakeResults != null) {
+                groupResult.setPublishResult(intakeResults);
+            }
+        }
+
+        planDetails.setGroups(groupResults);
+        return planDetails;
+
+    }
+
+    /**
+     * 鏍规嵁璁″垝ID鑾峰彇璁″垝鏈�鏂扮姸鎬�
+     *
+     * @param planId
+     * @return
+     */
+    public Integer getPlanLatestState(Long planId) {
+        return irrigatePlanMapper.getPlanLatestState(planId);
+    }
+}
\ No newline at end of file
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/dto/IrrigatePlan.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/dto/IrrigatePlan.java
new file mode 100644
index 0000000..d43197a
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/dto/IrrigatePlan.java
@@ -0,0 +1,55 @@
+package com.dy.pipIrrIrrigate.irrigatePlan.dto;
+
+import jakarta.validation.constraints.*;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-06-30 15:15
+ * @LastEditTime 2025-06-30 15:15
+ * @Description 鐏屾簤璁″垝瀵硅薄
+ */
+
+@Data
+public class IrrigatePlan {
+    public static final long serialVersionUID = 202506301516001L;
+
+    /**
+     * 椤圭洰ID
+     */
+    private Long projectId;
+
+    /**
+     * 璁″垝鍚嶇О
+     */
+    @NotBlank(message = "璁″垝鍚嶇О涓嶈兘涓虹┖")
+    private String planName;
+
+    /**
+     * 璁″垝鍚姩妯″紡锛�1-鎵嬪伐鍚姩锛�2-鑷姩鍚姩
+     */
+    @NotNull(message = "璁″垝鍚姩妯″紡涓嶈兘涓虹┖")
+    @Min(value = 1, message = "璁″垝鍚姩妯″紡涓嶈兘灏忎簬1")
+    @Max(value = 2, message = "璁″垝鍚姩妯″紡涓嶈兘澶т簬2")
+    private Byte startupMode;
+
+    /**
+     * 璁″垝鍚姩鏃堕棿
+     */
+    private Date planStartTime;
+
+    /**
+     * 鎿嶄綔浜篒D
+     */
+    @NotNull(message = "鎿嶄綔浜篒D涓嶈兘涓虹┖")
+    private Long operatorId;
+
+    /**
+     * 鐏屾簤娆″簭
+     */
+    @NotEmpty(message = "鐏屾簤娆″簭涓嶈兘涓虹┖")
+    private List<IrrigateSchedule> schedules;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/dto/IrrigateSchedule.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/dto/IrrigateSchedule.java
new file mode 100644
index 0000000..75867bc
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/dto/IrrigateSchedule.java
@@ -0,0 +1,32 @@
+package com.dy.pipIrrIrrigate.irrigatePlan.dto;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-06-30 15:17
+ * @LastEditTime 2025-06-30 15:17
+ * @Description 鐏屾簤娆″簭瀵硅薄琛�
+ */
+
+@Data
+public class IrrigateSchedule {
+    public static final long serialVersionUID = 202506301518001L;
+
+    /**
+     * 杞亴缁処D
+     */
+    private Long groupId;
+
+    /**
+     * 鐏屾簤寮�濮嬫椂闂�
+     */
+    private Date startTime;
+
+    /**
+     * 璇ヨ疆鐏岀粍鐏屾簤鏃堕暱
+     */
+    private Integer duration;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/dto/PlanSimple.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/dto/PlanSimple.java
new file mode 100644
index 0000000..6681d9a
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/dto/PlanSimple.java
@@ -0,0 +1,28 @@
+package com.dy.pipIrrIrrigate.irrigatePlan.dto;
+
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-07-01 17:23
+ * @LastEditTime 2025-07-01 17:23
+ * @Description 鐏屾簤璁″垝绠�鍗曞璞�
+ */
+
+@Data
+public class PlanSimple {
+    public static final long serialVersionUID = 202507011724001L;
+
+    /**
+     * 鐏屾簤璁″垝
+     */
+    @NotNull(message = "璁″垝ID涓嶈兘涓虹┖")
+    private Long planId;
+
+    /**
+     * 鎿嶄綔浜篒D
+     */
+    @NotNull(message = "鎿嶄綔浜篒D涓嶈兘涓虹┖")
+    private Long operatorId;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/enums/OperateTypeENUM.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/enums/OperateTypeENUM.java
new file mode 100644
index 0000000..be17436
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/enums/OperateTypeENUM.java
@@ -0,0 +1,25 @@
+package com.dy.pipIrrIrrigate.irrigatePlan.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-06-30 15:31
+ * @LastEditTime 2025-06-30 15:31
+ * @Description 鐏屾簤璁″垝鎿嶄綔绫诲瀷鏋氫妇
+ */
+
+@Getter
+@AllArgsConstructor
+public enum OperateTypeENUM {
+    CREATE((byte)1, "鍒涘缓"),
+    PUBLISH((byte)2, "鍙戝竷"),
+    EXECUTE((byte)3, "鎵ц"),
+    SUSPEND((byte)4, "鏆傚仠"),
+    TERMINATE((byte)5, "缁堟"),
+    DELETE((byte)6, "鍒犻櫎");
+
+    private final Byte code;
+    private final String message;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/qo/QoIrrigatePlan.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/qo/QoIrrigatePlan.java
new file mode 100644
index 0000000..679ddd8
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigatePlan/qo/QoIrrigatePlan.java
@@ -0,0 +1,41 @@
+package com.dy.pipIrrIrrigate.irrigatePlan.qo;
+
+import com.dy.common.webUtil.QueryConditionVo;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-07-03 10:43
+ * @LastEditTime 2025-07-03 10:43
+ * @Description 鐏屾簤璁″垝鏌ヨ瀵硅薄
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class QoIrrigatePlan extends QueryConditionVo {
+    /**
+     * 椤圭洰鍚嶇О
+     */
+    private String projectName;
+
+    /**
+     * 璁″垝鍚嶇О
+     */
+    private String planName;
+
+    /**
+     * 璁″垝鍚姩妯″紡锛�1-鎵嬪姩鍚姩锛�2-鑷姩鍚姩
+     */
+    private Byte startupMode;
+
+    /**
+     * 璁″垝鐘舵�侊紱1-鑽夌锛�2-宸插彂甯�
+     */
+    private Byte planState;
+
+    /**
+     * 鎵ц鐘舵�侊紱1-鏈墽琛岋紝2-鎵ц涓紝3-宸叉殏鍋滐紝4-宸茬粓姝紝5-宸插畬鎴�
+     */
+    private Byte executingState;
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigation/IrrigationCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigation/IrrigationCtrl.java
new file mode 100644
index 0000000..03549ee
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigation/IrrigationCtrl.java
@@ -0,0 +1,45 @@
+package com.dy.pipIrrIrrigate.irrigation;
+
+import com.dy.common.webUtil.BaseResponse;
+import com.dy.common.webUtil.BaseResponseUtils;
+import com.dy.pipIrrGlobal.voIr.VoGroupIntakes;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-07-03 10:58
+ * @LastEditTime 2025-07-03 10:58
+ * @Description
+ */
+
+@Slf4j
+@RestController
+@RequestMapping(path = "irrigation")
+@RequiredArgsConstructor
+public class IrrigationCtrl {
+    private final IrrigationSv irrigationSv;
+
+    /**
+     * 鏍规嵁杞亴缁処D鑾峰彇杞亴缁勮鎯�
+     * @param groupId
+     * @return
+     */
+    @GetMapping(path = "/getGroupDetails")
+    public BaseResponse<VoGroupIntakes> getGroupDetails(@RequestParam Long groupId) {
+        if(groupId == null) {
+            return BaseResponseUtils.buildErrorMsg("杞亴缁処D涓嶈兘涓虹┖");
+        }
+
+        try {
+            return BaseResponseUtils.buildSuccess(irrigationSv.getGroupDetails(groupId).get("content"));
+        } catch (Exception e) {
+            log.error("鑾峰彇杞亴缁勮鎯呭紓甯�", e);
+            return BaseResponseUtils.buildException(e.getMessage());
+        }
+    }
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigation/IrrigationSv.java b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigation/IrrigationSv.java
new file mode 100644
index 0000000..f6788f1
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/java/com/dy/pipIrrIrrigate/irrigation/IrrigationSv.java
@@ -0,0 +1,176 @@
+package com.dy.pipIrrIrrigate.irrigation;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.dy.common.multiDataSource.DataSourceContext;
+import com.dy.common.mw.protocol.Command;
+import com.dy.common.mw.protocol.CommandType;
+import com.dy.common.webUtil.BaseResponse;
+import com.dy.common.webUtil.BaseResponseUtils;
+import com.dy.pipIrrGlobal.daoIr.IrIrrigateGroupMapper;
+import com.dy.pipIrrGlobal.rtuMw.CodeLocal;
+import com.dy.pipIrrGlobal.voIr.VoGroupIntakes;
+import com.dy.pipIrrGlobal.voIr.VoIntake;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author ZhuBaoMin
+ * @date 2025-07-02 11:08
+ * @LastEditTime 2025-07-02 11:08
+ * @Description
+ */
+
+@Slf4j
+@Service
+public class IrrigationSv {
+    @Autowired
+    private IrIrrigateGroupMapper irIrrigateGroupMapper;
+
+    @Autowired
+    private Environment env;
+
+    @Autowired
+    private RestTemplate restTemplate;
+
+    private static final String pro_mw = "mw";
+    private String key_mw = "comSendUrl";
+
+    public Boolean getOnlineStatus(String rtuAdd) {
+        Command com = new Command();
+        com.id = Command.defaultId;
+        com.code = CodeLocal.onLinePart;
+        com.type = CommandType.innerCommand;
+        com.setRtuAddr(rtuAdd);
+        com.setParam(rtuAdd);
+        JSONObject response = (JSONObject) JSON.toJSON(sendCom2Mw(com));
+
+        if (response == null || !response.getString("code").equals("0001") || response.getJSONObject("content").getJSONObject("attachment").size() == 0) {
+            return false;
+        }
+
+        if(response.getJSONObject("content").getJSONObject("attachment").getBoolean(rtuAdd)) {
+            return true;
+        }
+        else {
+            return false;
+        }
+    }
+
+    public Boolean getOpenCloseStatus(String rtuAdd) {
+        Command com = new Command();
+        com.id = Command.defaultId;
+        com.code = CodeLocal.oneRtuStates;
+        com.type = CommandType.innerCommand;
+        com.setRtuAddr(rtuAdd);
+        com.setParam(rtuAdd);
+        JSONObject response = (JSONObject) JSON.toJSON(sendCom2Mw(com));
+
+        if (response == null || !response.getString("code").equals("0001") || response.getJSONObject("content").getJSONObject("attachment") == null) {
+            return false;
+        }
+
+        // if(response.getJSONObject("content").getJSONObject("attachment").get("valveOpenTrueCloseFalse").equals("true")) {
+        if(response.getJSONObject("content").getJSONObject("attachment").getBoolean("valveOpenTrueCloseFalse")) {
+            return true;
+        }
+        else {
+            return false;
+        }
+    }
+
+    /**
+     * 鍙戦�佸懡浠�
+     *
+     * @return
+     */
+    protected BaseResponse sendCom2Mw(Command com) {
+        String url = UriComponentsBuilder.fromUriString(env.getProperty(pro_mw + "." + DataSourceContext.get() + "." + key_mw))
+                .build()
+                .toUriString();
+        HttpHeaders headers = new HttpHeaders();
+        HttpEntity<Command> httpEntity = new HttpEntity<>(com, headers);
+        ResponseEntity<BaseResponse> response = null;
+        try {
+            // 閫氳繃Post鏂瑰紡璋冪敤鎺ュ彛
+            response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, BaseResponse.class);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        if(response == null) {
+            return BaseResponseUtils.buildErrorMsg("涓棿浠惰皟鐢ㄥけ璐�");
+        }
+
+        return response.getBody();
+    }
+
+    /**
+     * 鏍规嵁杞亴缁処D鑾峰彇杞亴缁勮鎯�
+     * @param groupId
+     * @return
+     */
+    public Map getGroupDetails(Long groupId) {
+        try {
+            // 鐢熸垚椤圭洰淇℃伅鍙婅疆鐏岀粍淇℃伅
+            VoGroupIntakes voGroupIntakes = new VoGroupIntakes();
+            String projectName = "";
+            String groupName = "";
+            List<VoGroupIntakes> groupIntakes = irIrrigateGroupMapper.getGroupIntakes(groupId);
+            if (groupIntakes == null) {
+                Map map = new HashMap<>();
+                map.put("success", false);
+                map.put("msg", "杞亴缁勪笉瀛樺湪");
+                map.put("content", null);
+                return map;
+            }
+            for(VoGroupIntakes groupIntake : groupIntakes) {
+                projectName = projectName + groupIntake.getProjectName() + "銆�";
+                groupName = groupIntake.getGroupName();
+            }
+            voGroupIntakes.setProjectName(projectName.substring(0, projectName.length() - 1));
+            voGroupIntakes.setGroupName(groupName);
+
+            // 琛ュ叏鍙栨按鍙d俊鎭紙鍦ㄧ嚎鎯呭喌锛�
+            List<VoIntake> intakes = irIrrigateGroupMapper.getGroupIntakesList(groupId);
+            if(intakes == null) {
+                Map map = new HashMap<>();
+                map.put("success", false);
+                map.put("msg", "璇ヨ疆鐏岀粍鏈粦瀹氬彇姘村彛");
+                map.put("content", null);
+                return map;
+            }
+            for (VoIntake intake : intakes) {
+                Boolean isOnLine = getOnlineStatus(intake.getRtuAddr());
+                intake.setIsOnLine(isOnLine);
+                Boolean isOpen = getOpenCloseStatus(intake.getRtuAddr());
+                intake.setIsOpen(isOpen);
+            }
+            voGroupIntakes.setIntakes(intakes);
+
+            Map map = new HashMap<>();
+            map.put("success", true);
+            map.put("msg", "鑾峰彇杞亴缁勮鎯呮垚鍔�");
+            map.put("content", voGroupIntakes);
+            return map;
+        } catch (Exception e) {
+            Map map = new HashMap<>();
+            map.put("success", false);
+            map.put("msg", "鑾峰彇杞亴缁勮鎯呭け璐�");
+            map.put("content", null);
+            return map;
+        }
+    }
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/resources/application-self.yml b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/resources/application-self.yml
index 5d05fe4..1349e7a 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/resources/application-self.yml
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-irrigate/src/main/resources/application-self.yml
@@ -16,3 +16,14 @@
     context-parameters:
       #GenerateIdSetSuffixListener涓簲鐢紝鍙栧�艰寖鍥存槸0-99
       idSuffix: ${pipIrr.irrigate.idSuffix}
+irr:
+  plan:
+    delay: 5 #杞亴涓鍒掑紑闃�鐨勫欢杩熸椂闀�(鍒嗛挓)
+    preOpeningTime: 10 #鎻愬墠鏃堕棿(鍒嗛挓)
+    planTerminateLimitMinutes: 5 #璁″垝缁堟鍚庨檺鍒跺彂甯冩柊璁″垝鐨勬椂闂撮棿闅�(鍒嗛挓)
+logging:
+  level:
+    com:
+      dy:
+        pipIrrGlobal:
+          daoIr: trace
\ No newline at end of file

--
Gitblit v1.8.0