liusheng
昨天 b57304d9917beab4671442a0018c1c3a2d681640
提交
已修改7个文件
已添加19个文件
1998 ■■■■■ 文件已修改
ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/ServiceSubtaskController.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/WebServiceClient/MessagingInsert.asmx 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/WebServiceClient/MessagingInsert.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/WebServiceClient/MessagingInsertLocator.java 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/WebServiceClient/MessagingInsertSoap12Stub.java 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/WebServiceClient/MessagingInsertSoap_BindingStub.java 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/WebServiceClient/MessagingInsertSoap_PortType.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/WebServiceClient/MessagingInsertTestCase.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserDeptMapper.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysUserDeptMapper.xml 279 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/common/enums/InhospStateEnum.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/common/exception/StateTransitionException.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/domain/ServiceSubtaskCountReq.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/domain/ServiceSubtaskStatistic.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/domain/entity/ServiceSubtaskEntity.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/service/impl/SubtaskSmsServiceImpl.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/statemachine/InhospStateMachine.java 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/statemachine/InhospStateMachineExample.java 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/statemachine/InhospStateMachineService.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/statemachine/handler/InhospStateHandler.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/statemachine/handler/impl/DischargeHandler.java 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/statemachine/handler/impl/InHospitalHandler.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/statemachine/handler/impl/PreAdmissionHandler.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/ServiceSubtaskController.java
@@ -515,17 +515,23 @@
    @ApiOperation("获取随访统计比例")
    @AddOrgId(field = "orgid", paramIndex = 0, campusField = "campusid")
    @PostMapping("/getSfStatistics")
    public AjaxResult getSfStatistics(@RequestBody ServiceSubtaskCountReq serviceSubtaskCountReq) {
    public Map<String, Object> getSfStatistics(@RequestBody ServiceSubtaskCountReq serviceSubtaskCountReq) {
        if (CollectionUtils.isEmpty(serviceSubtaskCountReq.getServiceType())) {
            return error("服务类型不能为空");
        }
        Integer offset = PageUtils.getOffset(serviceSubtaskCountReq.getPageNum(), serviceSubtaskCountReq.getPageSize());
        serviceSubtaskCountReq.setPageNum(offset);
        String followUpCountStyle = configService.selectConfigByKey("followUpCountStyle", serviceSubtaskCountReq.getOrgid());
        if (ObjectUtils.isNotEmpty(followUpCountStyle)) {
            serviceSubtaskCountReq.setFollowUpCountStyle(followUpCountStyle);
        } else {
            serviceSubtaskCountReq.setFollowUpCountStyle("1");
        }
        return success(serviceSubtaskService.getSfStatistics(serviceSubtaskCountReq));
        serviceSubtaskCountReq.setPageNum(null);
        serviceSubtaskCountReq.setPageSize(null);
        List<ServiceSubtaskStatistic> sfStatistics = serviceSubtaskService.getSfStatistics(serviceSubtaskCountReq);
        return getDataTable4(CollectionUtils.isEmpty(sfStatistics) ? sfStatistics.size() : 0, serviceSubtaskService.getSfStatistics(serviceSubtaskCountReq));
    }
    /**
@@ -589,7 +595,6 @@
    }
    /**
     * å»¶ç»­æŠ¤ç†ç»Ÿè®¡
     */
@@ -607,9 +612,6 @@
        }
        return success(serviceSubtaskService.getContinueNurseCount(serviceSubtaskCotinueCountVO));
    }
    /**
ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
@@ -105,6 +105,14 @@
        rspData.put("total", total);
        return rspData;
    }
    protected Map<String, Object> getDataTable4(long total, Object object) {
        Map<String, Object> rspData = new TreeMap<>();
        rspData.put("code", HttpStatus.SUCCESS);
        rspData.put("msg", "查询成功");
        rspData.put("data", object);
        rspData.put("total", total);
        return rspData;
    }
    /**
     * è¿”回成功
ruoyi-system/src/main/java/WebServiceClient/MessagingInsert.asmx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
      <s:element name="SMSMessageAccept">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="xmlReq" type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="SMSMessageAcceptResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="1" maxOccurs="1" name="SMSMessageAcceptResult" type="s:int" />
            <s:element minOccurs="0" maxOccurs="1" name="xmlResp" type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
    </s:schema>
  </wsdl:types>
  <wsdl:message name="SMSMessageAcceptSoapIn">
    <wsdl:part name="parameters" element="tns:SMSMessageAccept" />
  </wsdl:message>
  <wsdl:message name="SMSMessageAcceptSoapOut">
    <wsdl:part name="parameters" element="tns:SMSMessageAcceptResponse" />
  </wsdl:message>
  <wsdl:portType name="MessagingInsertSoap">
    <wsdl:operation name="SMSMessageAccept">
      <wsdl:input message="tns:SMSMessageAcceptSoapIn" />
      <wsdl:output message="tns:SMSMessageAcceptSoapOut" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="MessagingInsertSoap" type="tns:MessagingInsertSoap">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="SMSMessageAccept">
      <soap:operation soapAction="http://tempuri.org/SMSMessageAccept" style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:binding name="MessagingInsertSoap12" type="tns:MessagingInsertSoap">
    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="SMSMessageAccept">
      <soap12:operation soapAction="http://tempuri.org/SMSMessageAccept" style="document" />
      <wsdl:input>
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap12:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="MessagingInsert">
    <wsdl:port name="MessagingInsertSoap" binding="tns:MessagingInsertSoap">
      <soap:address location="http://218.108.11.29:8081/MessagingInsert.asmx" />
    </wsdl:port>
    <wsdl:port name="MessagingInsertSoap12" binding="tns:MessagingInsertSoap12">
      <soap12:address location="http://218.108.11.29:8081/MessagingInsert.asmx" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>
ruoyi-system/src/main/java/WebServiceClient/MessagingInsert.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
/**
 * MessagingInsert.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */
package WebServiceClient;
public interface MessagingInsert extends javax.xml.rpc.Service {
    public String getMessagingInsertSoap12Address();
    public MessagingInsertSoap_PortType getMessagingInsertSoap12() throws javax.xml.rpc.ServiceException;
    public MessagingInsertSoap_PortType getMessagingInsertSoap12(java.net.URL portAddress) throws javax.xml.rpc.ServiceException;
    public String getMessagingInsertSoapAddress();
    public MessagingInsertSoap_PortType getMessagingInsertSoap() throws javax.xml.rpc.ServiceException;
    public MessagingInsertSoap_PortType getMessagingInsertSoap(java.net.URL portAddress) throws javax.xml.rpc.ServiceException;
}
ruoyi-system/src/main/java/WebServiceClient/MessagingInsertLocator.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,202 @@
/**
 * MessagingInsertLocator.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */
package WebServiceClient;
public class MessagingInsertLocator extends org.apache.axis.client.Service implements MessagingInsert {
    public MessagingInsertLocator() {
    }
    public MessagingInsertLocator(org.apache.axis.EngineConfiguration config) {
        super(config);
    }
    public MessagingInsertLocator(String wsdlLoc, javax.xml.namespace.QName sName) throws javax.xml.rpc.ServiceException {
        super(wsdlLoc, sName);
    }
    // Use to get a proxy class for MessagingInsertSoap12
    private String MessagingInsertSoap12_address = "http://218.108.11.29:8081/MessagingInsert.asmx";
    public String getMessagingInsertSoap12Address() {
        return MessagingInsertSoap12_address;
    }
    // The WSDD service name defaults to the port name.
    private String MessagingInsertSoap12WSDDServiceName = "MessagingInsertSoap12";
    public String getMessagingInsertSoap12WSDDServiceName() {
        return MessagingInsertSoap12WSDDServiceName;
    }
    public void setMessagingInsertSoap12WSDDServiceName(String name) {
        MessagingInsertSoap12WSDDServiceName = name;
    }
    public MessagingInsertSoap_PortType getMessagingInsertSoap12() throws javax.xml.rpc.ServiceException {
       java.net.URL endpoint;
        try {
            endpoint = new java.net.URL(MessagingInsertSoap12_address);
        }
        catch (java.net.MalformedURLException e) {
            throw new javax.xml.rpc.ServiceException(e);
        }
        return getMessagingInsertSoap12(endpoint);
    }
    public MessagingInsertSoap_PortType getMessagingInsertSoap12(java.net.URL portAddress) throws javax.xml.rpc.ServiceException {
        try {
            MessagingInsertSoap12Stub _stub = new MessagingInsertSoap12Stub(portAddress, this);
            _stub.setPortName(getMessagingInsertSoap12WSDDServiceName());
            return _stub;
        }
        catch (org.apache.axis.AxisFault e) {
            return null;
        }
    }
    public void setMessagingInsertSoap12EndpointAddress(String address) {
        MessagingInsertSoap12_address = address;
    }
    // Use to get a proxy class for MessagingInsertSoap
    private String MessagingInsertSoap_address = "http://218.108.11.29:8081/MessagingInsert.asmx";
    public String getMessagingInsertSoapAddress() {
        return MessagingInsertSoap_address;
    }
    // The WSDD service name defaults to the port name.
    private String MessagingInsertSoapWSDDServiceName = "MessagingInsertSoap";
    public String getMessagingInsertSoapWSDDServiceName() {
        return MessagingInsertSoapWSDDServiceName;
    }
    public void setMessagingInsertSoapWSDDServiceName(String name) {
        MessagingInsertSoapWSDDServiceName = name;
    }
    public MessagingInsertSoap_PortType getMessagingInsertSoap() throws javax.xml.rpc.ServiceException {
       java.net.URL endpoint;
        try {
            endpoint = new java.net.URL(MessagingInsertSoap_address);
        }
        catch (java.net.MalformedURLException e) {
            throw new javax.xml.rpc.ServiceException(e);
        }
        return getMessagingInsertSoap(endpoint);
    }
    public MessagingInsertSoap_PortType getMessagingInsertSoap(java.net.URL portAddress) throws javax.xml.rpc.ServiceException {
        try {
            MessagingInsertSoap_BindingStub _stub = new MessagingInsertSoap_BindingStub(portAddress, this);
            _stub.setPortName(getMessagingInsertSoapWSDDServiceName());
            return _stub;
        }
        catch (org.apache.axis.AxisFault e) {
            return null;
        }
    }
    public void setMessagingInsertSoapEndpointAddress(String address) {
        MessagingInsertSoap_address = address;
    }
    /**
     * For the given interface, get the stub implementation.
     * If this service has no port for the given interface,
     * then ServiceException is thrown.
     * This service has multiple ports for a given interface;
     * the proxy implementation returned may be indeterminate.
     */
    public java.rmi.Remote getPort(Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException {
        try {
            if (MessagingInsertSoap_PortType.class.isAssignableFrom(serviceEndpointInterface)) {
                MessagingInsertSoap12Stub _stub = new MessagingInsertSoap12Stub(new java.net.URL(MessagingInsertSoap12_address), this);
                _stub.setPortName(getMessagingInsertSoap12WSDDServiceName());
                return _stub;
            }
            if (MessagingInsertSoap_PortType.class.isAssignableFrom(serviceEndpointInterface)) {
                MessagingInsertSoap_BindingStub _stub = new MessagingInsertSoap_BindingStub(new java.net.URL(MessagingInsertSoap_address), this);
                _stub.setPortName(getMessagingInsertSoapWSDDServiceName());
                return _stub;
            }
        }
        catch (Throwable t) {
            throw new javax.xml.rpc.ServiceException(t);
        }
        throw new javax.xml.rpc.ServiceException("There is no stub implementation for the interface:  " + (serviceEndpointInterface == null ? "null" : serviceEndpointInterface.getName()));
    }
    /**
     * For the given interface, get the stub implementation.
     * If this service has no port for the given interface,
     * then ServiceException is thrown.
     */
    public java.rmi.Remote getPort(javax.xml.namespace.QName portName, Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException {
        if (portName == null) {
            return getPort(serviceEndpointInterface);
        }
        String inputPortName = portName.getLocalPart();
        if ("MessagingInsertSoap12".equals(inputPortName)) {
            return getMessagingInsertSoap12();
        }
        else if ("MessagingInsertSoap".equals(inputPortName)) {
            return getMessagingInsertSoap();
        }
        else  {
            java.rmi.Remote _stub = getPort(serviceEndpointInterface);
            ((org.apache.axis.client.Stub) _stub).setPortName(portName);
            return _stub;
        }
    }
    public javax.xml.namespace.QName getServiceName() {
        return new javax.xml.namespace.QName("http://tempuri.org/", "MessagingInsert");
    }
    private java.util.HashSet ports = null;
    public java.util.Iterator getPorts() {
        if (ports == null) {
            ports = new java.util.HashSet();
            ports.add(new javax.xml.namespace.QName("http://tempuri.org/", "MessagingInsertSoap12"));
            ports.add(new javax.xml.namespace.QName("http://tempuri.org/", "MessagingInsertSoap"));
        }
        return ports.iterator();
    }
    /**
    * Set the endpoint address for the specified port name.
    */
    public void setEndpointAddress(String portName, String address) throws javax.xml.rpc.ServiceException {
if ("MessagingInsertSoap12".equals(portName)) {
            setMessagingInsertSoap12EndpointAddress(address);
        }
        else
if ("MessagingInsertSoap".equals(portName)) {
            setMessagingInsertSoapEndpointAddress(address);
        }
        else
{ // Unknown Port Name
            throw new javax.xml.rpc.ServiceException(" Cannot set Endpoint Address for Unknown Port" + portName);
        }
    }
    /**
    * Set the endpoint address for the specified port name.
    */
    public void setEndpointAddress(javax.xml.namespace.QName portName, String address) throws javax.xml.rpc.ServiceException {
        setEndpointAddress(portName.getLocalPart(), address);
    }
}
ruoyi-system/src/main/java/WebServiceClient/MessagingInsertSoap12Stub.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,136 @@
/**
 * MessagingInsertSoap12Stub.java
 * <p>
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */
package WebServiceClient;
public class MessagingInsertSoap12Stub extends org.apache.axis.client.Stub implements MessagingInsertSoap_PortType {
    private java.util.Vector cachedSerClasses = new java.util.Vector();
    private java.util.Vector cachedSerQNames = new java.util.Vector();
    private java.util.Vector cachedSerFactories = new java.util.Vector();
    private java.util.Vector cachedDeserFactories = new java.util.Vector();
    static org.apache.axis.description.OperationDesc[] _operations;
    static {
        _operations = new org.apache.axis.description.OperationDesc[1];
        _initOperationDesc1();
    }
    private static void _initOperationDesc1() {
        org.apache.axis.description.OperationDesc oper;
        org.apache.axis.description.ParameterDesc param;
        oper = new org.apache.axis.description.OperationDesc();
        oper.setName("SMSMessageAccept");
        param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("http://tempuri.org/", "xmlReq"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"), String.class, false, false);
        param.setOmittable(true);
        oper.addParameter(param);
        param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("http://tempuri.org/", "SMSMessageAcceptResult"), org.apache.axis.description.ParameterDesc.OUT, new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "int"), int.class, false, false);
        oper.addParameter(param);
        param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("http://tempuri.org/", "xmlResp"), org.apache.axis.description.ParameterDesc.OUT, new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"), String.class, false, false);
        param.setOmittable(true);
        oper.addParameter(param);
        oper.setReturnType(org.apache.axis.encoding.XMLType.AXIS_VOID);
        oper.setStyle(org.apache.axis.constants.Style.WRAPPED);
        oper.setUse(org.apache.axis.constants.Use.LITERAL);
        _operations[0] = oper;
    }
    public MessagingInsertSoap12Stub() throws org.apache.axis.AxisFault {
        this(null);
    }
    public MessagingInsertSoap12Stub(java.net.URL endpointURL, javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {
        this(service);
        super.cachedEndpoint = endpointURL;
    }
    public MessagingInsertSoap12Stub(javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {
        if (service == null) {
            super.service = new org.apache.axis.client.Service();
        } else {
            super.service = service;
        }
        ((org.apache.axis.client.Service) super.service).setTypeMappingVersion("1.1");
    }
    protected org.apache.axis.client.Call createCall() throws java.rmi.RemoteException {
        try {
            org.apache.axis.client.Call _call = super._createCall();
            if (super.maintainSessionSet) {
                _call.setMaintainSession(super.maintainSession);
            }
            if (super.cachedUsername != null) {
                _call.setUsername(super.cachedUsername);
            }
            if (super.cachedPassword != null) {
                _call.setPassword(super.cachedPassword);
            }
            if (super.cachedEndpoint != null) {
                _call.setTargetEndpointAddress(super.cachedEndpoint);
            }
            if (super.cachedTimeout != null) {
                _call.setTimeout(super.cachedTimeout);
            }
            if (super.cachedPortName != null) {
                _call.setPortName(super.cachedPortName);
            }
            java.util.Enumeration keys = super.cachedProperties.keys();
            while (keys.hasMoreElements()) {
                String key = (String) keys.nextElement();
                _call.setProperty(key, super.cachedProperties.get(key));
            }
            return _call;
        } catch (Throwable _t) {
            throw new org.apache.axis.AxisFault("Failure trying to get the Call object", _t);
        }
    }
    public Integer SMSMessageAccept(String xmlReq, javax.xml.rpc.holders.IntHolder SMSMessageAcceptResult, javax.xml.rpc.holders.StringHolder xmlResp) throws java.rmi.RemoteException {
        Integer success = null;
        if (super.cachedEndpoint == null) {
            throw new org.apache.axis.NoEndPointException();
        }
        org.apache.axis.client.Call _call = createCall();
        _call.setOperation(_operations[0]);
        _call.setUseSOAPAction(true);
        _call.setSOAPActionURI("http://tempuri.org/SMSMessageAccept");
        _call.setEncodingStyle(null);
        _call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, Boolean.FALSE);
        _call.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);
        _call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP12_CONSTANTS);
        _call.setOperationName(new javax.xml.namespace.QName("http://tempuri.org/", "SMSMessageAccept"));
        setRequestHeaders(_call);
        setAttachments(_call);
        try {
            Object _resp = _call.invoke(new Object[]{xmlReq});
            if (_resp instanceof java.rmi.RemoteException) {
                throw (java.rmi.RemoteException) _resp;
            } else {
                extractAttachments(_call);
                java.util.Map _output;
                _output = _call.getOutputParams();
                try {
                    success = ((Integer) _output.get(new javax.xml.namespace.QName("http://tempuri.org/", "SMSMessageAcceptResult"))).intValue();
                } catch (Exception _exception) {
                    success = ((Integer) org.apache.axis.utils.JavaUtils.convert(_output.get(new javax.xml.namespace.QName("http://tempuri.org/", "SMSMessageAcceptResult")), int.class)).intValue();
                }
                try {
                    xmlResp.value = (String) _output.get(new javax.xml.namespace.QName("http://tempuri.org/", "xmlResp"));
                } catch (Exception _exception) {
                    xmlResp.value = (String) org.apache.axis.utils.JavaUtils.convert(_output.get(new javax.xml.namespace.QName("http://tempuri.org/", "xmlResp")), String.class);
                }
            }
        } catch (org.apache.axis.AxisFault axisFaultException) {
            throw axisFaultException;
        }
        return success;
    }
}
ruoyi-system/src/main/java/WebServiceClient/MessagingInsertSoap_BindingStub.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,138 @@
/**
 * MessagingInsertSoap_BindingStub.java
 * <p>
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */
package WebServiceClient;
import org.apache.axis.client.Stub;
public class MessagingInsertSoap_BindingStub extends Stub implements MessagingInsertSoap_PortType {
    private java.util.Vector cachedSerClasses = new java.util.Vector();
    private java.util.Vector cachedSerQNames = new java.util.Vector();
    private java.util.Vector cachedSerFactories = new java.util.Vector();
    private java.util.Vector cachedDeserFactories = new java.util.Vector();
    static org.apache.axis.description.OperationDesc[] _operations;
    static {
        _operations = new org.apache.axis.description.OperationDesc[1];
        _initOperationDesc1();
    }
    private static void _initOperationDesc1() {
        org.apache.axis.description.OperationDesc oper;
        org.apache.axis.description.ParameterDesc param;
        oper = new org.apache.axis.description.OperationDesc();
        oper.setName("SMSMessageAccept");
        param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("http://tempuri.org/", "xmlReq"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"), String.class, false, false);
        param.setOmittable(true);
        oper.addParameter(param);
        param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("http://tempuri.org/", "SMSMessageAcceptResult"), org.apache.axis.description.ParameterDesc.OUT, new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "int"), int.class, false, false);
        oper.addParameter(param);
        param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("http://tempuri.org/", "xmlResp"), org.apache.axis.description.ParameterDesc.OUT, new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"), String.class, false, false);
        param.setOmittable(true);
        oper.addParameter(param);
        oper.setReturnType(org.apache.axis.encoding.XMLType.AXIS_VOID);
        oper.setStyle(org.apache.axis.constants.Style.WRAPPED);
        oper.setUse(org.apache.axis.constants.Use.LITERAL);
        _operations[0] = oper;
    }
    public MessagingInsertSoap_BindingStub() throws org.apache.axis.AxisFault {
        this(null);
    }
    public MessagingInsertSoap_BindingStub(java.net.URL endpointURL, javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {
        this(service);
        super.cachedEndpoint = endpointURL;
    }
    public MessagingInsertSoap_BindingStub(javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {
        if (service == null) {
            super.service = new org.apache.axis.client.Service();
        } else {
            super.service = service;
        }
        ((org.apache.axis.client.Service) super.service).setTypeMappingVersion("1.1");
    }
    protected org.apache.axis.client.Call createCall() throws java.rmi.RemoteException {
        try {
            org.apache.axis.client.Call _call = super._createCall();
            if (super.maintainSessionSet) {
                _call.setMaintainSession(super.maintainSession);
            }
            if (super.cachedUsername != null) {
                _call.setUsername(super.cachedUsername);
            }
            if (super.cachedPassword != null) {
                _call.setPassword(super.cachedPassword);
            }
            if (super.cachedEndpoint != null) {
                _call.setTargetEndpointAddress(super.cachedEndpoint);
            }
            if (super.cachedTimeout != null) {
                _call.setTimeout(super.cachedTimeout);
            }
            if (super.cachedPortName != null) {
                _call.setPortName(super.cachedPortName);
            }
            java.util.Enumeration keys = super.cachedProperties.keys();
            while (keys.hasMoreElements()) {
                String key = (String) keys.nextElement();
                _call.setProperty(key, super.cachedProperties.get(key));
            }
            return _call;
        } catch (Throwable _t) {
            throw new org.apache.axis.AxisFault("Failure trying to get the Call object", _t);
        }
    }
    public Integer SMSMessageAccept(String xmlReq, javax.xml.rpc.holders.IntHolder SMSMessageAcceptResult, javax.xml.rpc.holders.StringHolder xmlResp) throws java.rmi.RemoteException {
        Integer success = null;
        if (super.cachedEndpoint == null) {
            throw new org.apache.axis.NoEndPointException();
        }
        org.apache.axis.client.Call _call = createCall();
        _call.setOperation(_operations[0]);
        _call.setUseSOAPAction(true);
        _call.setSOAPActionURI("http://tempuri.org/SMSMessageAccept");
        _call.setEncodingStyle(null);
        _call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, Boolean.FALSE);
        _call.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);
        _call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS);
        _call.setOperationName(new javax.xml.namespace.QName("http://tempuri.org/", "SMSMessageAccept"));
        setRequestHeaders(_call);
        setAttachments(_call);
        try {
            Object _resp = _call.invoke(new Object[]{xmlReq});
            if (_resp instanceof java.rmi.RemoteException) {
                throw (java.rmi.RemoteException) _resp;
            } else {
                extractAttachments(_call);
                java.util.Map _output;
                _output = _call.getOutputParams();
                try {
                    success = ((Integer) _output.get(new javax.xml.namespace.QName("http://tempuri.org/", "SMSMessageAcceptResult"))).intValue();
                } catch (Exception _exception) {
                    success = ((Integer) org.apache.axis.utils.JavaUtils.convert(_output.get(new javax.xml.namespace.QName("http://tempuri.org/", "SMSMessageAcceptResult")), int.class)).intValue();
                }
                try {
                    xmlResp.value = (String) _output.get(new javax.xml.namespace.QName("http://tempuri.org/", "xmlResp"));
                } catch (Exception _exception) {
                    xmlResp.value = (String) org.apache.axis.utils.JavaUtils.convert(_output.get(new javax.xml.namespace.QName("http://tempuri.org/", "xmlResp")), String.class);
                }
            }
        } catch (org.apache.axis.AxisFault axisFaultException) {
            throw axisFaultException;
        }
        return success;
    }
}
ruoyi-system/src/main/java/WebServiceClient/MessagingInsertSoap_PortType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
/**
 * MessagingInsertSoap_PortType.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */
package WebServiceClient;
public interface MessagingInsertSoap_PortType extends java.rmi.Remote {
    public Integer SMSMessageAccept(String xmlReq, javax.xml.rpc.holders.IntHolder SMSMessageAcceptResult, javax.xml.rpc.holders.StringHolder xmlResp) throws java.rmi.RemoteException;
}
ruoyi-system/src/main/java/WebServiceClient/MessagingInsertTestCase.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,65 @@
///**
// * MessagingInsertTestCase.java
// * <p>
// * This file was auto-generated from WSDL
// * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
// */
//
//package WebServiceClient;
//
//public class MessagingInsertTestCase extends junit.framework.TestCase {
//    public MessagingInsertTestCase(String name) {
//        super(name);
//    }
//
//    public void testMessagingInsertSoap12WSDL() throws Exception {
//        javax.xml.rpc.ServiceFactory serviceFactory = javax.xml.rpc.ServiceFactory.newInstance();
//        java.net.URL url = new java.net.URL(new MessagingInsertLocator().getMessagingInsertSoap12Address() + "?WSDL");
//        javax.xml.rpc.Service service = serviceFactory.createService(url, new MessagingInsertLocator().getServiceName());
//        assertTrue(service != null);
//    }
//
//    public void test1MessagingInsertSoap12SMSMessageAccept() throws Exception {
//        MessagingInsertSoap12Stub binding;
//        try {
//            binding = (MessagingInsertSoap12Stub) new MessagingInsertLocator().getMessagingInsertSoap12();
//        } catch (javax.xml.rpc.ServiceException jre) {
//            if (jre.getLinkedCause() != null) jre.getLinkedCause().printStackTrace();
//            throw new junit.framework.AssertionFailedError("JAX-RPC ServiceException caught: " + jre);
//        }
//        assertNotNull("binding is null", binding);
//
//        // Time out after a minute
//        binding.setTimeout(60000);
//
//        // Test operation
//        binding.SMSMessageAccept(new String(), new javax.xml.rpc.holders.IntHolder(), new javax.xml.rpc.holders.StringHolder());
//        // TBD - validate results
//    }
//
//    public void testMessagingInsertSoapWSDL() throws Exception {
//        javax.xml.rpc.ServiceFactory serviceFactory = javax.xml.rpc.ServiceFactory.newInstance();
//        java.net.URL url = new java.net.URL(new MessagingInsertLocator().getMessagingInsertSoapAddress() + "?WSDL");
//        javax.xml.rpc.Service service = serviceFactory.createService(url, new MessagingInsertLocator().getServiceName());
//        assertTrue(service != null);
//    }
//
//    public void test2MessagingInsertSoapSMSMessageAccept() throws Exception {
//        MessagingInsertSoap_BindingStub binding;
//        try {
//            binding = (MessagingInsertSoap_BindingStub) new MessagingInsertLocator().getMessagingInsertSoap();
//        } catch (javax.xml.rpc.ServiceException jre) {
//            if (jre.getLinkedCause() != null) jre.getLinkedCause().printStackTrace();
//            throw new junit.framework.AssertionFailedError("JAX-RPC ServiceException caught: " + jre);
//        }
//        assertNotNull("binding is null", binding);
//
//        // Time out after a minute
//        binding.setTimeout(60000);
//
//        // Test operation
//        binding.SMSMessageAccept(new String(), new javax.xml.rpc.holders.IntHolder(), new javax.xml.rpc.holders.StringHolder());
//        // TBD - validate results
//    }
//
//}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserDeptMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,78 @@
package com.ruoyi.system.mapper;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUserDept;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘Mapper接口
 *
 * @author lihu
 * @date 2024-08-29
 */
@Mapper
@Component("sysUserDeptSystemMapper")
public interface SysUserDeptMapper {
    /**
     * æŸ¥è¯¢ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘
     *
     * @param id ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘ä¸»é”®
     * @return ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘
     */
    public SysUserDept selectSysUserDeptById(Long id);
    /**
     * æŸ¥è¯¢ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘åˆ—è¡¨
     *
     * @param sysUserDept ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘
     * @return ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘é›†åˆ
     */
    public List<SysUserDept> selectSysUserDeptList(SysUserDept sysUserDept);
    /**
     * æ–°å¢žã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘
     *
     * @param sysUserDept ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘
     * @return ç»“æžœ
     */
    public int insertSysUserDept(SysUserDept sysUserDept);
    /**
     * ä¿®æ”¹ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘
     *
     * @param sysUserDept ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘
     * @return ç»“æžœ
     */
    public int updateSysUserDept(SysUserDept sysUserDept);
    /**
     * åˆ é™¤ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘
     *
     * @param id ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘ä¸»é”®
     * @return ç»“æžœ
     */
    public int deleteSysUserDeptById(Long id);
    /**
     * æ ¹æ®ç”¨æˆ·ID查询部门信息
     *
     * @param id
     * @return
     */
    public List<SysDept> selectDeptListByUserId(Long id);
    /**
     * æ‰¹é‡åˆ é™¤ã€è¯·å¡«å†™åŠŸèƒ½åç§°ã€‘
     *
     * @param ids éœ€è¦åˆ é™¤çš„æ•°æ®ä¸»é”®é›†åˆ
     * @return ç»“æžœ
     */
    public int deleteSysUserDeptByIds(Long[] ids);
    public int deleteSysUserDeptByCode(SysUserDept sysUserDept);
    public int updateSysUserDeptForSync(SysUserDept sysUserDept);
}
ruoyi-system/src/main/resources/mapper/system/SysUserDeptMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,279 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.SysUserDeptMapper">
    <resultMap type="com.ruoyi.common.core.domain.entity.SysUserDept" id="SysUserDeptResult">
        <result property="id" column="id"/>
        <result property="orgid" column="orgid"/>
        <result property="userId" column="user_id"/>
        <result property="deptId" column="dept_id"/>
        <result property="delFlag" column="del_flag"/>
        <result property="deptCode" column="dept_code"/>
        <result property="deptName" column="dept_name"/>
        <result property="deptType" column="dept_type"/>
        <result property="createTime" column="create_time"/>
        <result property="updateTime" column="update_time"/>
        <result property="campusid" column="campusid"/>
    </resultMap>
    <resultMap id="deptResult" type="com.ruoyi.common.core.domain.entity.SysDept">
        <id property="deptId" column="dept_id"/>
        <result property="parentId" column="parent_id"/>
        <result property="deptName" column="dept_name"/>
        <result property="ancestors" column="ancestors"/>
        <result property="orderNum" column="order_num"/>
        <result property="leader" column="leader"/>
        <result property="status" column="dept_status"/>
        <result property="campusid" column="campusid"/>
    </resultMap>
    <sql id="selectSysUserDeptVo">
        select id,
               user_id,
               dept_id,
               del_flag,
               campusid,
               orgid,
               create_time,
               update_time,
               dept_code,
               dept_name,
               dept_type
        from sys_user_dept
    </sql>
    <select id="selectSysUserDeptList" parameterType="com.ruoyi.common.core.domain.entity.SysUserDept"
            resultMap="SysUserDeptResult">
        <include refid="selectSysUserDeptVo"/>
        where 1=1
            and del_flag = 0
            and orgid=#{orgid}
            <if test="userId != null ">
                and user_id = #{userId}
            </if>
            <if test="deptId != null ">
                and dept_id = #{deptId}
            </if>
            <if test="delFlag != null ">
                and del_flag = #{delFlag}
            </if>
            <if test="createTime != null ">
                and create_time = #{createTime}
            </if>
            <if test="updateTime != null ">
                and update_time = #{updateTime}
            </if>
            <if test="deptType != null ">
                and dept_type = #{deptType}
            </if>
            <if test="deptCode != null ">
                and dept_code = #{deptCode}
            </if>
            <if test="campusid != null ">
                and campusid = #{campusid}
            </if>
    </select>
    <select id="selectSysUserDeptById" parameterType="Long"
            resultMap="SysUserDeptResult">
        <include refid="selectSysUserDeptVo"/>
        where id = #{id}
    </select>
    <insert id="insertSysUserDept" parameterType="com.ruoyi.common.core.domain.entity.SysUserDept"
            useGeneratedKeys="true" keyProperty="id">
        insert into sys_user_dept
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="userId != null">user_id,
            </if>
            <if test="deptId != null">dept_id,
            </if>
            <if test="delFlag != null ">
                del_flag,
            </if>
            <if test="createTime != null ">
                create_time,
            </if>
            <if test="updateTime != null ">
                update_time,
            </if>
            <if test="deptType != null ">
                dept_type,
            </if>
            <if test="deptCode != null ">
                dept_code,
            </if>
            <if test="deptName != null ">
                dept_name,
            </if>
            <if test="orgid != null ">
                orgid,
            </if>
            <if test="userCode != null ">
                user_code,
            </if>
            <if test="campusid != null ">
                campusid,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="userId != null">#{userId},
            </if>
            <if test="deptId != null">#{deptId},
            </if>
            <if test="delFlag != null ">
                #{delFlag},
            </if>
            <if test="createTime != null ">
                #{createTime},
            </if>
            <if test="updateTime != null ">
                #{updateTime},
            </if>
            <if test="deptType != null ">
                #{deptType},
            </if>
            <if test="deptCode != null ">
                #{deptCode},
            </if>
            <if test="deptName != null ">
                #{deptName},
            </if>
            <if test="orgid != null ">
                #{orgid},
            </if>
            <if test="userCode != null ">
                #{userCode},
            </if>
            <if test="campusid != null ">
                #{campusid},
            </if>
        </trim>
    </insert>
    <update id="updateSysUserDept" parameterType="com.ruoyi.common.core.domain.entity.SysUserDept">
        update sys_user_dept
        <trim prefix="SET" suffixOverrides=",">
            <if test="userId != null">user_id =
                #{userId},
            </if>
            <if test="deptId != null">dept_id =
                #{deptId},
            </if>
            <if test="delFlag != null ">
                del_flag = #{delFlag},
            </if>
            <if test="createTime != null ">
                create_time = #{createTime},
            </if>
            <if test="updateTime != null ">
                update_time = #{updateTime},
            </if>
            <if test="deptType != null ">
                dept_type = #{deptType},
            </if>
            <if test="deptCode != null ">
                dept_code = #{deptCode},
            </if>
            <if test="deptName != null ">
                dept_name = #{deptName},
            </if>
            <if test="orgid != null ">
                orgid = #{orgid},
            </if>
            <if test="campusid != null ">
                campusid = #{campusid},
            </if>
        </trim>
        where id = #{id}
    </update>
    <update id="deleteSysUserDeptById" parameterType="Long">
        update sys_user_dept
        <trim prefix="SET" suffixOverrides=",">
            del_flag =1
        </trim>
        where id = #{id}
    </update>
    <select id="selectDeptListByUserId" resultMap="deptResult">
        select d.dept_id,
               d.dept_name,
               d.parent_id,
               d.ancestors,
               d.dept_name,
               d.order_num,
               d.campusid,
               d.leader,
               d.orgid,
               d.status as dept_status
        from sys_dept d
                 left join sys_user_dept ud on d.dept_code = ud.dept_code
        where ud.user_id = #{userId}
          and ud.del_flag = 0
          and d.del_flag = 0
    </select>
    <update id="deleteSysUserDeptByIds" parameterType="String">
        update sys_user_dept
        <trim prefix="SET" suffixOverrides=",">
            del_flag =1,
            update_time = sysdate()
        </trim>
        where user_id in
        <foreach item="id" collection="array" open="(" separator="," close=")">
            #{id}
        </foreach>
    </update>
    <update id="deleteSysUserDeptByCode" parameterType="String">
        update sys_user_dept
        <trim prefix="SET" suffixOverrides=",">
            del_flag =1,
            update_time = sysdate()
        </trim>
        where user_id =#{userId} and dept_code=#{deptCode}
    </update>
    <update id="updateSysUserDeptForSync" parameterType="com.ruoyi.common.core.domain.entity.SysUserDept">
        update sys_user_dept
        <trim prefix="SET" suffixOverrides=",">
            <if test="deptId != null">dept_id =
                #{deptId},
            </if>
            <if test="delFlag != null ">
                del_flag = #{delFlag},
            </if>
            <if test="createTime != null ">
                create_time = #{createTime},
            </if>
            <if test="updateTime != null ">
                update_time = #{updateTime},
            </if>
            <if test="deptType != null ">
                dept_type = #{deptType},
            </if>
            <if test="deptCode != null ">
                dept_code = #{deptCode},
            </if>
            <if test="deptName != null ">
                dept_name = #{deptName},
            </if>
            <if test="orgid != null ">
                orgid = #{orgid},
            </if>
            <if test="campusid != null ">
                campusid = #{campusid},
            </if>
        </trim>
        where user_id =#{userId}
        <if test="orgid != null and orgid != ''">
            and orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            and campusid = #{campusid}
        </if>
    </update>
</mapper>
smartor/src/main/java/com/smartor/common/enums/InhospStateEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,112 @@
package com.smartor.common.enums;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
 * ä½é™¢çŠ¶æ€æžšä¸¾
 *
 * @author smartor
 */
public enum InhospStateEnum {
    /**
     * é¢„入院状态
     */
    PRE_ADMISSION("3", "预入院", new String[]{"0"}),
    /**
     * åœ¨é™¢çŠ¶æ€
     */
    IN_HOSPITAL("0", "在院", new String[]{"1"}),
    /**
     * å‡ºé™¢çŠ¶æ€
     */
    DISCHARGED("1", "出院", new String[]{});
    /**
     * çŠ¶æ€ç 
     */
    private final String code;
    /**
     * çŠ¶æ€æè¿°
     */
    private final String description;
    /**
     * å…è®¸è½¬æ¢çš„下一状态码集合
     */
    private final Set<String> allowedNextStates;
    InhospStateEnum(String code, String description, String[] allowedNextStates) {
        this.code = code;
        this.description = description;
        this.allowedNextStates = new HashSet<>(Arrays.asList(allowedNextStates));
    }
    public String getCode() {
        return code;
    }
    public String getDescription() {
        return description;
    }
    /**
     * åˆ¤æ–­æ˜¯å¦å…è®¸è½¬æ¢åˆ°ç›®æ ‡çŠ¶æ€
     *
     * @param targetStateCode ç›®æ ‡çŠ¶æ€ç 
     * @return æ˜¯å¦å…è®¸è½¬æ¢
     */
    public boolean canTransitionTo(String targetStateCode) {
        return allowedNextStates.contains(targetStateCode);
    }
    /**
     * æ ¹æ®çŠ¶æ€ç èŽ·å–æžšä¸¾
     *
     * @param code çŠ¶æ€ç 
     * @return å¯¹åº”的枚举,如果不存在返回null
     */
    public static InhospStateEnum fromCode(String code) {
        for (InhospStateEnum state : values()) {
            if (state.getCode().equals(code)) {
                return state;
            }
        }
        return null;
    }
    /**
     * éªŒè¯çŠ¶æ€è½¬æ¢æ˜¯å¦åˆæ³•
     *
     * @param currentStateCode å½“前状态码
     * @param targetStateCode ç›®æ ‡çŠ¶æ€ç 
     * @return æ˜¯å¦å…è®¸è½¬æ¢
     */
    public static boolean isValidTransition(String currentStateCode, String targetStateCode) {
        if (currentStateCode == null) {
            // åˆå§‹çŠ¶æ€ï¼Œåªå…è®¸åˆ›å»ºé¢„å…¥é™¢æˆ–åœ¨é™¢
            return "3".equals(targetStateCode) || "0".equals(targetStateCode);
        }
        InhospStateEnum currentState = fromCode(currentStateCode);
        if (currentState == null) {
            return false;
        }
        return currentState.canTransitionTo(targetStateCode);
    }
    /**
     * èŽ·å–æ‰€æœ‰å…è®¸çš„ä¸‹ä¸€çŠ¶æ€
     *
     * @return å…è®¸çš„下一状态集合
     */
    public Set<String> getAllowedNextStates() {
        return new HashSet<>(allowedNextStates);
    }
}
smartor/src/main/java/com/smartor/common/exception/StateTransitionException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package com.smartor.common.exception;
/**
 * çŠ¶æ€è½¬æ¢å¼‚å¸¸
 *
 * @author smartor
 */
public class StateTransitionException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    public StateTransitionException(String message) {
        super(message);
    }
    public StateTransitionException(String message, Throwable cause) {
        super(message, cause);
    }
    public StateTransitionException(String currentState, String targetState) {
        super(String.format("非法的状态转换: ä»Ž [%s] åˆ° [%s]", currentState, targetState));
    }
}
smartor/src/main/java/com/smartor/domain/ServiceSubtaskCountReq.java
@@ -26,6 +26,12 @@
    private Integer visitCount;
    /**
     * rateDay ä»£è¡¨å‡ å¤©åŠæ—¶çއ
     */
    @ApiModelProperty(value = "几天及时率")
    private Integer rateDay;
    private Integer isVisitAgain;
    @ApiModelProperty(value = "异常预警:0绿色;1红色;2黄色")
smartor/src/main/java/com/smartor/domain/ServiceSubtaskStatistic.java
@@ -167,6 +167,10 @@
    @Excel(name = " åŠæ—¶çއ ")
    private Double rate = 0.0;
    @ApiModelProperty(value = "完成率")
    @Excel(name = " å®Œæˆçއ ")
    private Double finishRate = 0.0;
    @ApiModelProperty(value = "首次随访率")
    @Excel(name = " é¦–次随访率 ")
    private String followUpRate;
smartor/src/main/java/com/smartor/domain/entity/ServiceSubtaskEntity.java
@@ -97,6 +97,14 @@
    @ApiModelProperty(value = "服务类型(1、监测评估;2、出院随访;3、门诊随访;4、宣教关怀;5、复诊管理;6、满意度调查;7、患者报告; 8、其他通知 9体检随访 10.医技随访  11,影像专科随访  12、心电专科随访, 13专科随访)")
    private String serviceType;
    @ApiModelProperty(value = "服务类型集合")
    private List<Long> serviceTypeList;
    /**
     * rateDay ä»£è¡¨å‡ å¤©åŠæ—¶çއ
     */
    @ApiModelProperty(value = "几天及时率")
    private Integer rateDay;
    /**
     * æ€§åˆ«
     */
@@ -773,9 +781,4 @@
    @ApiModelProperty(value = "分组code集合")
    private List<String> groupKeyList;
//    /**
//     * æ—¥æœŸé™åˆ¶ ç›®å‰ç”±å‰ç«¯æŽ§åˆ¶
//     */
//    @ApiModelProperty(value = "日期限制:0全部服务    1截止当前日期")
//    private String dateLimit;
}
smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskServiceImpl.java
@@ -2461,11 +2461,13 @@
        ssRate.setStarttime(serviceSubtaskCountReq.getStartTime());
        ssRate.setEndtime(serviceSubtaskCountReq.getEndTime());
        ssRate.setVisitCount(serviceSubtaskCountReq.getVisitCount());
        ssRate.setServiceTypeList(serviceSubtaskCountReq.getServiceType());
        if (serviceSubtaskCountReq.getEndTime() != null && new Date().before(serviceSubtaskCountReq.getEndTime())) {
            ssRate.setEndtime(new Date());
        }
        ssRate.setGroupKey(groupKey);
        ssRate.setGroupKeyList(groupKeyList);
        ssRate.setRateDay(serviceSubtaskCountReq.getRateDay());
        Map<String, Map<String, Object>> jsRates = new HashMap<>();
        if (!collect.isEmpty()) {
            jsRates = serviceSubtaskMapper.selectTimelyRateBatch(ssRate);
smartor/src/main/java/com/smartor/service/impl/SubtaskSmsServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
package com.smartor.service.impl;
import com.ruoyi.common.core.service.ISubtaskSmsService;
import com.smartor.common.LSHospTokenUtil;
import com.smartor.domain.ServiceSubtask;
import com.smartor.mapper.ServiceSubtaskMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * çŸ­ä¿¡å‘送跨模块服务实现(供 ruoyi-system é€šè¿‡ SpringUtils è°ƒç”¨ï¼‰
 */
@Service
public class SubtaskSmsServiceImpl implements ISubtaskSmsService {
    @Autowired
    private ServiceSubtaskMapper serviceSubtaskMapper;
    @Override
    public void updateSubtaskVisitNotice(Long subId, Integer visitNotice) {
        ServiceSubtask serviceSubtask = new ServiceSubtask();
        serviceSubtask.setId(subId);
        serviceSubtask.setVisitNotice(visitNotice);
        serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
    }
    @Override
    public String getLSHospToken(String orgid, String tokenUrl) {
        return LSHospTokenUtil.getToken(orgid, tokenUrl);
    }
}
smartor/src/main/java/com/smartor/statemachine/InhospStateMachine.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,202 @@
 package com.smartor.statemachine;
import com.ruoyi.common.utils.StringUtils;
import com.smartor.common.enums.InhospStateEnum;
import com.smartor.common.exception.StateTransitionException;
import com.smartor.domain.PatMedInhosp;
import com.smartor.service.IPatMedInhospService;
import com.smartor.statemachine.handler.InhospStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/**
 * ä½é™¢çŠ¶æ€æœºç®¡ç†å™¨
 * è´Ÿè´£çŠ¶æ€è½¬æ¢çš„åè°ƒå’Œåˆ†å¸ƒå¼é”ç®¡ç†
 *
 * @author smartor
 */
@Slf4j
@Component
public class InhospStateMachine {
    @Autowired
    private IPatMedInhospService patMedInhospService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private List<InhospStateHandler> handlers;
    /**
     * çŠ¶æ€å¤„ç†å™¨æ˜ å°„è¡¨
     */
    private final Map<String, InhospStateHandler> handlerMap = new ConcurrentHashMap<>();
    /**
     * åˆ†å¸ƒå¼é”è¶…时时间(秒)
     */
    private static final int LOCK_TIMEOUT = 10;
    /**
     * åˆ†å¸ƒå¼é”å‰ç¼€
     */
    private static final String LOCK_KEY_PREFIX = "inhosp:state:lock:";
    @PostConstruct
    public void init() {
        // åˆå§‹åŒ–处理器映射
        if (CollectionUtils.isNotEmpty(handlers)) {
            for (InhospStateHandler handler : handlers) {
                handlerMap.put(handler.getStateCode(), handler);
                log.info("【InhospStateMachine】注册状态处理器:{} -> {}",
                        handler.getStateCode(), handler.getClass().getSimpleName());
            }
        }
    }
    /**
     * æ‰§è¡ŒçŠ¶æ€è½¬æ¢ï¼ˆå¸¦åˆ†å¸ƒå¼é”ï¼‰
     *
     * @param patMedInhosp ä½é™¢è®°å½•对象
     * @param targetState ç›®æ ‡çŠ¶æ€
     * @return æ˜¯å¦æˆåŠŸ
     */
    public boolean transitionState(PatMedInhosp patMedInhosp, String targetState) {
        String serialnum = StringUtils.trim(patMedInhosp.getSerialnum());
        String orgid = StringUtils.trim(patMedInhosp.getOrgid());
        if (StringUtils.isEmpty(serialnum) || StringUtils.isEmpty(orgid)) {
            log.error("【InhospStateMachine】serialnum或orgid为空,无法执行状态转换");
            return false;
        }
        // ç”Ÿæˆåˆ†å¸ƒå¼é”key(不包含state,锁住整个患者记录)
        String lockKey = LOCK_KEY_PREFIX + serialnum + ":" + orgid;
        Boolean locked = false;
        try {
            // å°è¯•获取分布式锁
            locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", LOCK_TIMEOUT, TimeUnit.SECONDS);
            if (locked == null) {
                log.warn("【InhospStateMachine】Redis不可用,降级为无锁执行,serialnum={}, orgid={}", serialnum, orgid);
                return executeStateTransition(patMedInhosp, targetState);
            }
            if (!Boolean.TRUE.equals(locked)) {
                log.warn("【InhospStateMachine】获取分布式锁失败,其他线程正在处理,serialnum={}, orgid={}", serialnum, orgid);
                return false;
            }
            // èŽ·å–é”æˆåŠŸï¼Œæ‰§è¡ŒçŠ¶æ€è½¬æ¢
            return executeStateTransition(patMedInhosp, targetState);
        } catch (Exception e) {
            log.error("【InhospStateMachine】状态转换异常:serialnum={}, orgid={}, targetState={}, é”™è¯¯ï¼š{}",
                    serialnum, orgid, targetState, e.getMessage(), e);
            return false;
        } finally {
            // é‡Šæ”¾é”
            if (Boolean.TRUE.equals(locked)) {
                try {
                    redisTemplate.delete(lockKey);
                    log.debug("【InhospStateMachine】释放分布式锁成功,lockKey={}", lockKey);
                } catch (Exception e) {
                    log.warn("【InhospStateMachine】释放分布式锁失败:lockKey={}, é”™è¯¯ï¼š{}", lockKey, e.getMessage());
                }
            }
        }
    }
    /**
     * æ‰§è¡ŒçŠ¶æ€è½¬æ¢é€»è¾‘
     *
     * @param patMedInhosp ä½é™¢è®°å½•对象
     * @param targetState ç›®æ ‡çŠ¶æ€
     * @return æ˜¯å¦æˆåŠŸ
     */
    private boolean executeStateTransition(PatMedInhosp patMedInhosp, String targetState) {
        String serialnum = patMedInhosp.getSerialnum();
        String orgid = patMedInhosp.getOrgid();
        log.info("【InhospStateMachine】开始执行状态转换:serialnum={}, orgid={}, targetState={}",
                serialnum, orgid, targetState);
        // 1. æŸ¥è¯¢å½“前状态
        PatMedInhosp query = new PatMedInhosp();
        query.setSerialnum(StringUtils.trim(serialnum));
        query.setOrgid(StringUtils.trim(orgid));
        query.setPatno(StringUtils.trim(patMedInhosp.getPatno()));
        query.setInhospstate(null); // æŸ¥è¯¢æ‰€æœ‰çŠ¶æ€
        List<PatMedInhosp> existingRecords = patMedInhospService.selectPatMedInhosp(query);
        String currentState = null;
        if (CollectionUtils.isNotEmpty(existingRecords)) {
            // å¦‚果存在多条记录,取最新的一条(理论上经过状态机后不应该有多条)
            currentState = existingRecords.get(0).getInhospstate();
            log.info("【InhospStateMachine】当前状态:{}", currentState);
        }
        // 2. éªŒè¯çŠ¶æ€è½¬æ¢æ˜¯å¦åˆæ³•
        if (!InhospStateEnum.isValidTransition(currentState, targetState)) {
            log.error("【InhospStateMachine】非法的状态转换:从 [{}] åˆ° [{}],serialnum={}, orgid={}",
                    currentState, targetState, serialnum, orgid);
            throw new StateTransitionException(currentState, targetState);
        }
        // 3. èŽ·å–å¯¹åº”çš„çŠ¶æ€å¤„ç†å™¨
        InhospStateHandler handler = handlerMap.get(targetState);
        if (handler == null) {
            log.error("【InhospStateMachine】未找到状态处理器:targetState={}", targetState);
            return false;
        }
        // 4. æ‰§è¡ŒçŠ¶æ€å¤„ç†
        boolean result = handler.handle(patMedInhosp);
        if (result) {
            log.info("【InhospStateMachine】状态转换成功:serialnum={}, orgid={}, {} -> {}",
                    serialnum, orgid, currentState, targetState);
        } else {
            log.warn("【InhospStateMachine】状态转换失败:serialnum={}, orgid={}, {} -> {}",
                    serialnum, orgid, currentState, targetState);
        }
        return result;
    }
    /**
     * èŽ·å–å½“å‰çŠ¶æ€
     *
     * @param serialnum æµæ°´å·
     * @param orgid æœºæž„ID
     * @param patno æ‚£è€…编号
     * @return å½“前状态码,如果不存在返回null
     */
    public String getCurrentState(String serialnum, String orgid, String patno) {
        PatMedInhosp query = new PatMedInhosp();
        query.setSerialnum(StringUtils.trim(serialnum));
        query.setOrgid(StringUtils.trim(orgid));
        query.setPatno(StringUtils.trim(patno));
        query.setInhospstate(null);
        List<PatMedInhosp> records = patMedInhospService.selectPatMedInhosp(query);
        if (CollectionUtils.isEmpty(records)) {
            return null;
        }
        return records.get(0).getInhospstate();
    }
}
smartor/src/main/java/com/smartor/statemachine/InhospStateMachineExample.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,182 @@
package com.smartor.statemachine;
/**
 * ä½é™¢çŠ¶æ€æœºä½¿ç”¨ç¤ºä¾‹
 *
 * æœ¬ç±»å±•示如何在现有代码中集成状态机,仅供参考,不需要运行
 *
 * @author smartor
 */
public class InhospStateMachineExample {
    /**
     * ç¤ºä¾‹1: åœ¨ServiceSLTDHealthcareRecordServiceImpl中使用状态机
     *
     * åŽŸæ–¹æ³•ç­¾åï¼š
     * private void processPatientInhospInfo(ServiceSLTDInhospResDTO dto, PatArchive patArchive, String cry)
     *
     * æ”¹é€ æ–¹æ¡ˆï¼šç”¨çŠ¶æ€æœºæ›¿æ¢åŽŸæœ‰çš„if-else逻辑
     */
    public void exampleUsageInService() {
        /*
        // åŽŸä»£ç ï¼ˆ561-677行)改造为:
        @Autowired
        private InhospStateMachineService stateMachineService;
        private void processPatientInhospInfo(ServiceSLTDInhospResDTO dto, PatArchive patArchive, String cry) {
            // æž„建住院记录对象(保持原有逻辑)
            PatMedInhosp patMedInhosp = buildPatientInhospInfo(dto, patArchive, cry);
            // ä½¿ç”¨çŠ¶æ€æœºå¤„ç†çŠ¶æ€è½¬æ¢ï¼ˆæ›¿æ¢åŽŸæœ‰çš„å¤§æ®µif-else)
            boolean success = stateMachineService.processStateChange(patMedInhosp, cry);
            if (success) {
                log.info("【processPatientInhospInfo】状态转换成功:serialnum={}, cry={}",
                        patMedInhosp.getSerialnum(), cry);
            } else {
                log.warn("【processPatientInhospInfo】状态转换失败或跳过:serialnum={}, cry={}",
                        patMedInhosp.getSerialnum(), cry);
            }
        }
        // ä¼˜ç‚¹ï¼š
        // 1. ä»£ç ä»Ž100+行减少到10行
        // 2. çŠ¶æ€è½¬æ¢é€»è¾‘æ¸…æ™°ï¼Œæ˜“äºŽç»´æŠ¤
        // 3. è‡ªåŠ¨åŠ åˆ†å¸ƒå¼é”ï¼Œè§£å†³å¹¶å‘é—®é¢˜
        // 4. çŠ¶æ€æ ¡éªŒè§„åˆ™é›†ä¸­ç®¡ç†
        */
    }
    /**
     * ç¤ºä¾‹2: ç›´æŽ¥ä½¿ç”¨çŠ¶æ€æœºæœåŠ¡API
     */
    public void exampleDirectUsage() {
        /*
        @Autowired
        private InhospStateMachineService stateMachineService;
        // å¤„理预入院
        PatMedInhosp preAdmission = new PatMedInhosp();
        preAdmission.setSerialnum("202601290001");
        preAdmission.setOrgid("HOS001");
        preAdmission.setPatno("P001");
        // ... è®¾ç½®å…¶ä»–字段
        boolean result1 = stateMachineService.processPreAdmission(preAdmission);
        // å¤„理入院(会自动从预入院状态转换)
        PatMedInhosp inHospital = new PatMedInhosp();
        inHospital.setSerialnum("202601290001");
        inHospital.setOrgid("HOS001");
        inHospital.setPatno("P001");
        // ... è®¾ç½®å…¶ä»–字段
        boolean result2 = stateMachineService.processInHospital(inHospital);
        // å¤„理出院(会自动从入院状态转换)
        PatMedInhosp discharge = new PatMedInhosp();
        discharge.setSerialnum("202601290001");
        discharge.setOrgid("HOS001");
        discharge.setPatno("P001");
        // ... è®¾ç½®å…¶ä»–字段
        boolean result3 = stateMachineService.processDischarge(discharge);
        // æŸ¥è¯¢å½“前状态
        String currentState = stateMachineService.getCurrentState("202601290001", "HOS001", "P001");
        // currentState = "1" (出院状态)
        */
    }
    /**
     * ç¤ºä¾‹3: çŠ¶æ€è½¬æ¢æ ¡éªŒ
     */
    public void exampleStateValidation() {
        /*
        // éžæ³•转换示例1:预入院直接到出院(会抛出异常)
        try {
            PatMedInhosp discharge = new PatMedInhosp();
            discharge.setSerialnum("202601290002");
            discharge.setOrgid("HOS001");
            discharge.setPatno("P002");
            discharge.setInhospstate("3"); // å½“前是预入院
            stateMachineService.processDischarge(discharge); // å°è¯•直接出院
        } catch (StateTransitionException e) {
            log.error("状态转换失败:{}", e.getMessage());
            // è¾“出: éžæ³•的状态转换: ä»Ž [3] åˆ° [1]
        }
        // éžæ³•转换示例2:重复入院(会被handler拒绝)
        PatMedInhosp inHospital1 = new PatMedInhosp();
        inHospital1.setSerialnum("202601290003");
        inHospital1.setOrgid("HOS001");
        inHospital1.setPatno("P003");
        stateMachineService.processInHospital(inHospital1); // ç¬¬ä¸€æ¬¡å…¥é™¢ï¼šæˆåŠŸ
        boolean result = stateMachineService.processInHospital(inHospital1); // ç¬¬äºŒæ¬¡å…¥é™¢ï¼šå¤±è´¥
        // result = false,日志输出警告
        */
    }
    /**
     * çŠ¶æ€æœºæž¶æž„è¯´æ˜Ž
     *
     * 1. çŠ¶æ€æžšä¸¾ (InhospStateEnum)
     *    - å®šä¹‰æ‰€æœ‰çŠ¶æ€åŠå…è®¸çš„è½¬æ¢è§„åˆ™
     *    - PRE_ADMISSION(3) -> IN_HOSPITAL(0) -> DISCHARGED(1)
     *
     * 2. çŠ¶æ€å¤„ç†å™¨ (InhospStateHandler)
     *    - PreAdmissionHandler: å¤„理预入院逻辑
     *    - InHospitalHandler: å¤„理入院逻辑
     *    - DischargeHandler: å¤„理出院逻辑
     *
     * 3. çŠ¶æ€æœºç®¡ç†å™¨ (InhospStateMachine)
     *    - åè°ƒçŠ¶æ€è½¬æ¢
     *    - ç®¡ç†åˆ†å¸ƒå¼é”
     *    - éªŒè¯çŠ¶æ€åˆæ³•æ€§
     *
     * 4. é—¨é¢æœåŠ¡ (InhospStateMachineService)
     *    - æä¾›ä¾¿æ·API
     *    - å°è£…复杂逻辑
     *
     * 5. å¼‚常处理 (StateTransitionException)
     *    - å¤„理非法状态转换
     */
    /**
     * æ•°æ®åº“配合建议
     *
     * 1. æ·»åŠ å”¯ä¸€ç´¢å¼•ï¼ˆå»ºè®®ï¼‰
     * CREATE UNIQUE INDEX uk_serialnum_orgid_state
     * ON pat_med_inhosp(serialnum, orgid, inhospstate);
     *
     * 2. æˆ–者更严格的约束(确保一个患者只有一条记录)
     * CREATE UNIQUE INDEX uk_serialnum_orgid
     * ON pat_med_inhosp(serialnum, orgid);
     *
     * æ³¨æ„ï¼šå¦‚果使用第2种索引,需要确保:
     * - çŠ¶æ€å˜æ›´å¿…é¡»èµ°æ›´æ–°ï¼ˆä¸èƒ½æ’å…¥æ–°è®°å½•ï¼‰
     * - éœ€è¦æ¸…理历史多状态记录
     */
    /**
     * æ¸è¿›å¼é›†æˆæ–¹æ¡ˆ
     *
     * é˜¶æ®µ1:双写模式(推荐)
     * - ä¿ç•™åŽŸæœ‰ä»£ç ä¸å˜
     * - æ–°å¢žçŠ¶æ€æœºè°ƒç”¨ï¼Œè®°å½•æ—¥å¿—å¯¹æ¯”
     * - éªŒè¯çŠ¶æ€æœºé€»è¾‘æ­£ç¡®æ€§
     *
     * é˜¶æ®µ2:灰度切换
     * - éƒ¨åˆ†cry值走状态机
     * - è§‚察生产环境表现
     *
     * é˜¶æ®µ3:完全迁移
     * - å…¨éƒ¨é€»è¾‘切换到状态机
     * - ç§»é™¤åŽŸæœ‰if-else代码
     */
}
smartor/src/main/java/com/smartor/statemachine/InhospStateMachineService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,91 @@
package com.smartor.statemachine;
import com.smartor.domain.PatMedInhosp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * ä½é™¢çŠ¶æ€æœºæœåŠ¡ï¼ˆé—¨é¢æ¨¡å¼ï¼‰
 * æä¾›ä¾¿æ·çš„状态转换方法
 *
 * @author smartor
 */
@Slf4j
@Service
public class InhospStateMachineService {
    @Autowired
    private InhospStateMachine stateMachine;
    /**
     * å¤„理预入院
     *
     * @param patMedInhosp ä½é™¢è®°å½•对象
     * @return æ˜¯å¦æˆåŠŸ
     */
    public boolean processPreAdmission(PatMedInhosp patMedInhosp) {
        log.info("【InhospStateMachineService】处理预入院:serialnum={}, orgid={}",
                patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
        return stateMachine.transitionState(patMedInhosp, "3");
    }
    /**
     * å¤„理入院
     *
     * @param patMedInhosp ä½é™¢è®°å½•对象
     * @return æ˜¯å¦æˆåŠŸ
     */
    public boolean processInHospital(PatMedInhosp patMedInhosp) {
        log.info("【InhospStateMachineService】处理入院:serialnum={}, orgid={}",
                patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
        return stateMachine.transitionState(patMedInhosp, "0");
    }
    /**
     * å¤„理出院
     *
     * @param patMedInhosp ä½é™¢è®°å½•对象
     * @return æ˜¯å¦æˆåŠŸ
     */
    public boolean processDischarge(PatMedInhosp patMedInhosp) {
        log.info("【InhospStateMachineService】处理出院:serialnum={}, orgid={}",
                patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
        return stateMachine.transitionState(patMedInhosp, "1");
    }
    /**
     * æ ¹æ®cry参数处理状态转换
     *
     * @param patMedInhosp ä½é™¢è®°å½•对象
     * @param cry çŠ¶æ€ç ï¼ˆ0:入院, 1:出院, 3:预入院)
     * @return æ˜¯å¦æˆåŠŸ
     */
    public boolean processStateChange(PatMedInhosp patMedInhosp, String cry) {
        log.info("【InhospStateMachineService】根据cry处理状态变更:serialnum={}, orgid={}, cry={}",
                patMedInhosp.getSerialnum(), patMedInhosp.getOrgid(), cry);
        if ("0".equals(cry)) {
            return processInHospital(patMedInhosp);
        } else if ("1".equals(cry)) {
            return processDischarge(patMedInhosp);
        } else if ("3".equals(cry)) {
            return processPreAdmission(patMedInhosp);
        } else {
            log.error("【InhospStateMachineService】未知的cry值:{}", cry);
            return false;
        }
    }
    /**
     * èŽ·å–å½“å‰çŠ¶æ€
     *
     * @param serialnum æµæ°´å·
     * @param orgid æœºæž„ID
     * @param patno æ‚£è€…编号
     * @return å½“前状态码
     */
    public String getCurrentState(String serialnum, String orgid, String patno) {
        return stateMachine.getCurrentState(serialnum, orgid, patno);
    }
}
smartor/src/main/java/com/smartor/statemachine/handler/InhospStateHandler.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.smartor.statemachine.handler;
import com.smartor.domain.PatMedInhosp;
/**
 * ä½é™¢çŠ¶æ€å¤„ç†å™¨æŽ¥å£
 *
 * @author smartor
 */
public interface InhospStateHandler {
    /**
     * å¤„理状态变更
     *
     * @param patMedInhosp å¾…处理的住院记录对象
     * @return å¤„理结果(true:成功, false:失败)
     */
    boolean handle(PatMedInhosp patMedInhosp);
    /**
     * èŽ·å–è¯¥å¤„ç†å™¨å¯¹åº”çš„çŠ¶æ€ç 
     *
     * @return çŠ¶æ€ç 
     */
    String getStateCode();
}
smartor/src/main/java/com/smartor/statemachine/handler/impl/DischargeHandler.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,103 @@
package com.smartor.statemachine.handler.impl;
import com.ruoyi.common.utils.StringUtils;
import com.smartor.domain.PatMedInhosp;
import com.smartor.service.IPatMedInhospService;
import com.smartor.statemachine.handler.InhospStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * å‡ºé™¢çŠ¶æ€å¤„ç†å™¨
 *
 * @author smartor
 */
@Slf4j
@Component
public class DischargeHandler implements InhospStateHandler {
    @Autowired
    private IPatMedInhospService patMedInhospService;
    @Override
    public boolean handle(PatMedInhosp patMedInhosp) {
        log.info("【DischargeHandler】处理出院逻辑,serialnum={}, orgid={}",
                patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
        PatMedInhosp query = new PatMedInhosp();
        query.setPatno(StringUtils.trim(patMedInhosp.getPatno()));
        query.setSerialnum(StringUtils.trim(patMedInhosp.getSerialnum()));
        query.setOrgid(StringUtils.trim(patMedInhosp.getOrgid()));
        // 1. å…ˆæ£€æŸ¥æ˜¯å¦å·²å­˜åœ¨å‡ºé™¢è®°å½•
        query.setInhospstate("1");
        List<PatMedInhosp> dischargedRecords = patMedInhospService.selectPatMedInhosp(query);
        if (CollectionUtils.isNotEmpty(dischargedRecords)) {
            log.warn("【DischargeHandler】出院记录已存在,跳过,serialnum={}, orgid={}",
                    patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
            return false;
        }
        // 2. æ£€æŸ¥æ˜¯å¦å­˜åœ¨å…¥é™¢è®°å½•(正常流程:必须先入院才能出院)
        query.setInhospstate("0");
        List<PatMedInhosp> inHospitalRecords = patMedInhospService.selectPatMedInhosp(query);
        if (CollectionUtils.isNotEmpty(inHospitalRecords)) {
            // å­˜åœ¨å…¥é™¢è®°å½•,执行状态更新为出院
            try {
                patMedInhosp.setInhospstate("1");
                patMedInhosp.setInhospid(inHospitalRecords.get(0).getInhospid());
                int updateCount = patMedInhospService.updatePatMedInhosp(patMedInhosp);
                log.info("【DischargeHandler】更新入院记录为出院状态,serialnum={}, updateCount={}",
                        patMedInhosp.getSerialnum(), updateCount);
                return updateCount > 0;
            } catch (Exception e) {
                log.error("【DischargeHandler】更新入院记录失败:serialnum={}, orgid={}, é”™è¯¯ï¼š{}",
                        patMedInhosp.getSerialnum(), patMedInhosp.getOrgid(), e.getMessage(), e);
                return false;
            }
        }
        // 3. æ£€æŸ¥æ˜¯å¦å­˜åœ¨é¢„入院记录(异常流程:从预入院直接出院,可能是取消入院)
        query.setInhospstate("3");
        List<PatMedInhosp> preAdmissionRecords = patMedInhospService.selectPatMedInhosp(query);
        if (CollectionUtils.isNotEmpty(preAdmissionRecords)) {
            log.warn("【DischargeHandler】存在预入院记录但未入院,不允许直接出院,serialnum={}, orgid={}",
                    patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
            // æ ¹æ®ä¸šåŠ¡éœ€æ±‚å†³å®šæ˜¯å¦å…è®¸ä»Žé¢„å…¥é™¢ç›´æŽ¥å‡ºé™¢ï¼Œè¿™é‡Œæš‚æ—¶ä¸å…è®¸
            return false;
        }
        // 4. ä¸å­˜åœ¨ä»»ä½•记录,异常情况:不应该没有入院记录就出院
        log.warn("【DischargeHandler】无入院记录,不允许直接插入出院记录,serialnum={}, orgid={}",
                patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
        // å¦‚果业务允许直接插入出院记录(如数据修复场景),可以取消注释以下代码
        /*
        try {
            patMedInhosp.setInhospstate("1");
            patMedInhospService.insertPatMedInhosp(patMedInhosp);
            log.info("【DischargeHandler】成功插入出院记录(无入院记录),serialnum={}", patMedInhosp.getSerialnum());
            return true;
        } catch (org.springframework.dao.DuplicateKeyException e) {
            log.warn("【DischargeHandler】出院记录已存在(并发插入),跳过:serialnum={}, orgid={}",
                    patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
            return false;
        } catch (Exception e) {
            log.error("【DischargeHandler】插入出院记录失败:serialnum={}, orgid={}, é”™è¯¯ï¼š{}",
                    patMedInhosp.getSerialnum(), patMedInhosp.getOrgid(), e.getMessage(), e);
            return false;
        }
        */
        return false;
    }
    @Override
    public String getStateCode() {
        return "1";
    }
}
smartor/src/main/java/com/smartor/statemachine/handler/impl/InHospitalHandler.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,94 @@
package com.smartor.statemachine.handler.impl;
import com.ruoyi.common.utils.StringUtils;
import com.smartor.domain.PatMedInhosp;
import com.smartor.service.IPatMedInhospService;
import com.smartor.statemachine.handler.InhospStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * å…¥é™¢çŠ¶æ€å¤„ç†å™¨
 *
 * @author smartor
 */
@Slf4j
@Component
public class InHospitalHandler implements InhospStateHandler {
    @Autowired
    private IPatMedInhospService patMedInhospService;
    @Override
    public boolean handle(PatMedInhosp patMedInhosp) {
        log.info("【InHospitalHandler】处理入院逻辑,serialnum={}, orgid={}",
                patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
        PatMedInhosp query = new PatMedInhosp();
        query.setPatno(StringUtils.trim(patMedInhosp.getPatno()));
        query.setSerialnum(StringUtils.trim(patMedInhosp.getSerialnum()));
        query.setOrgid(StringUtils.trim(patMedInhosp.getOrgid()));
        // 1. å…ˆæ£€æŸ¥æ˜¯å¦å·²å­˜åœ¨å…¥é™¢è®°å½•
        query.setInhospstate("0");
        List<PatMedInhosp> inHospitalRecords = patMedInhospService.selectPatMedInhosp(query);
        if (CollectionUtils.isNotEmpty(inHospitalRecords)) {
            log.warn("【InHospitalHandler】入院记录已存在,跳过,serialnum={}, orgid={}",
                    patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
            return false;
        }
        // 2. æ£€æŸ¥æ˜¯å¦å­˜åœ¨é¢„入院记录
        query.setInhospstate("3");
        List<PatMedInhosp> preAdmissionRecords = patMedInhospService.selectPatMedInhosp(query);
        if (CollectionUtils.isNotEmpty(preAdmissionRecords)) {
            // å­˜åœ¨é¢„入院记录,执行状态更新
            try {
                patMedInhosp.setInhospstate("0");
                patMedInhosp.setInhospid(preAdmissionRecords.get(0).getInhospid());
                int updateCount = patMedInhospService.updatePatMedInhosp(patMedInhosp);
                log.info("【InHospitalHandler】更新预入院记录为入院状态,serialnum={}, updateCount={}",
                        patMedInhosp.getSerialnum(), updateCount);
                return updateCount > 0;
            } catch (Exception e) {
                log.error("【InHospitalHandler】更新预入院记录失败:serialnum={}, orgid={}, é”™è¯¯ï¼š{}",
                        patMedInhosp.getSerialnum(), patMedInhosp.getOrgid(), e.getMessage(), e);
                return false;
            }
        }
        // 3. æ£€æŸ¥æ˜¯å¦å·²å‡ºé™¢ï¼ˆå¦‚果已出院则不允许直接入院)
        query.setInhospstate("1");
        List<PatMedInhosp> dischargedRecords = patMedInhospService.selectPatMedInhosp(query);
        if (CollectionUtils.isNotEmpty(dischargedRecords)) {
            log.warn("【InHospitalHandler】患者已出院,不允许再次入院,serialnum={}, orgid={}",
                    patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
            return false;
        }
        // 4. ä¸å­˜åœ¨ä»»ä½•记录,直接插入入院记录
        try {
            patMedInhosp.setInhospstate("0");
            patMedInhospService.insertPatMedInhosp(patMedInhosp);
            log.info("【InHospitalHandler】成功插入入院记录,serialnum={}", patMedInhosp.getSerialnum());
            return true;
        } catch (org.springframework.dao.DuplicateKeyException e) {
            log.warn("【InHospitalHandler】入院记录已存在(并发插入),跳过:serialnum={}, orgid={}",
                    patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
            return false;
        } catch (Exception e) {
            log.error("【InHospitalHandler】插入入院记录失败:serialnum={}, orgid={}, é”™è¯¯ï¼š{}",
                    patMedInhosp.getSerialnum(), patMedInhosp.getOrgid(), e.getMessage(), e);
            return false;
        }
    }
    @Override
    public String getStateCode() {
        return "0";
    }
}
smartor/src/main/java/com/smartor/statemachine/handler/impl/PreAdmissionHandler.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
package com.smartor.statemachine.handler.impl;
import com.ruoyi.common.utils.StringUtils;
import com.smartor.domain.PatMedInhosp;
import com.smartor.service.IPatMedInhospService;
import com.smartor.statemachine.handler.InhospStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * é¢„入院状态处理器
 *
 * @author smartor
 */
@Slf4j
@Component
public class PreAdmissionHandler implements InhospStateHandler {
    @Autowired
    private IPatMedInhospService patMedInhospService;
    @Override
    public boolean handle(PatMedInhosp patMedInhosp) {
        log.info("【PreAdmissionHandler】处理预入院逻辑,serialnum={}, orgid={}",
                patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
        // æŸ¥è¯¢æ˜¯å¦å·²å­˜åœ¨ä»»ä½•状态的记录
        PatMedInhosp query = new PatMedInhosp();
        query.setPatno(StringUtils.trim(patMedInhosp.getPatno()));
        query.setSerialnum(StringUtils.trim(patMedInhosp.getSerialnum()));
        query.setOrgid(StringUtils.trim(patMedInhosp.getOrgid()));
        query.setInhospstate(null); // æŸ¥è¯¢æ‰€æœ‰çŠ¶æ€
        List<PatMedInhosp> existingRecords = patMedInhospService.selectPatMedInhosp(query);
        if (CollectionUtils.isNotEmpty(existingRecords)) {
            log.warn("【PreAdmissionHandler】记录已存在,跳过预入院插入,serialnum={}, orgid={}",
                    patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
            return false;
        }
        // ä¸å­˜åœ¨ä»»ä½•记录,执行插入
        try {
            patMedInhosp.setInhospstate("3");
            patMedInhospService.insertPatMedInhosp(patMedInhosp);
            log.info("【PreAdmissionHandler】成功插入预入院记录,serialnum={}", patMedInhosp.getSerialnum());
            return true;
        } catch (org.springframework.dao.DuplicateKeyException e) {
            log.warn("【PreAdmissionHandler】预入院记录已存在(并发插入),跳过:serialnum={}, orgid={}",
                    patMedInhosp.getSerialnum(), patMedInhosp.getOrgid());
            return false;
        } catch (Exception e) {
            log.error("【PreAdmissionHandler】插入预入院记录失败:serialnum={}, orgid={}, é”™è¯¯ï¼š{}",
                    patMedInhosp.getSerialnum(), patMedInhosp.getOrgid(), e.getMessage(), e);
            return false;
        }
    }
    @Override
    public String getStateCode() {
        return "3";
    }
}
smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml
@@ -662,25 +662,29 @@
        ) a
    </select>
    <select id="selectTimelyRateBatch" parameterType="com.smartor.domain.ServiceSubtask" resultType="map">
    <select id="selectTimelyRateBatch" parameterType="com.smartor.domain.entity.ServiceSubtaskEntity" resultType="map">
        SELECT
        <if test="groupKey != null and groupKey != ''">
            ${groupKey} as groupKey,
        </if>
        SUM(CASE WHEN DATE(visit_time) &lt; DATE(IFNULL(finishtime, NOW())) THEN 1 ELSE 0 END) / COUNT(*) as rate
        SUM(CASE WHEN finishtime IS NOT NULL AND DATE(visit_time) &lt;= DATE(finishtime) THEN 1 ELSE 0 END) / COUNT(*) AS finishRate,
        <if test="rateDay != null">
            SUM(CASE WHEN finishtime IS NOT NULL AND DATEDIFF(finishtime, endtime) &lt;= #{rateDay} THEN 1 ELSE 0 END) / COUNT(*) AS rate
        </if>
        <if test="rateDay == null">
            NULL AS rate
        </if>
        FROM service_subtask
        WHERE del_flag = 0
        AND visit_time IS NOT NULL
        AND finishtime IS NOT NULL
        <if test="orgid != null">AND orgid = #{orgid}</if>
        <if test="starttime == null and endtime==null">
            AND visit_time &lt; NOW()
            AND DATE(visit_time) &lt; DATE(NOW())
        </if>
        <if test="starttime != null and endtime!=null">
            AND visit_time >= #{starttime}
            AND visit_time &lt; DATE_ADD(#{endtime}, INTERVAL 1 DAY)
        </if>
        <if test="orgid != null  and orgid != ''">and orgid = #{orgid}</if>
        <if test="orgid != null and orgid != ''">AND orgid = #{orgid}</if>
        <if test="deptcode != null  and deptcode != ''">and deptcode = #{deptcode}</if>
        <if test="deptname != null  and deptname != ''">and deptname = #{deptname}</if>
        <if test="isabnormal != null">and isabnormal = #{isabnormal}</if>
@@ -698,6 +702,13 @@
        <if test="visitCount != null and visitCount > 1">
            AND visit_count > 1
        </if>
        <if test="serviceTypeList != null">
            AND service_type IN
            <foreach collection="serviceTypeList" item="serviceType" open="(" separator=","
                     close=")">
                #{serviceType}
            </foreach>
        </if>
        <if test="groupKey != null and groupKey != ''">
            AND ${groupKey} IN
            <foreach collection="groupKeyList" item="key" open="(" separator=","