Kaynağa Gözat

更新待办代码

Heyuan 5 ay önce
ebeveyn
işleme
c0ea940cbf

+ 1 - 1
js/deploy/easweb.ear/eas_web.war/bin/workflow/metas/js/approve.js

@@ -2872,7 +2872,7 @@ mod.definePage('workflow/metas/js/approve', function (waf, wfCommonUtil) {
                 // 检查窗口是否仍然存在,如果存在则表示没有权限
                 if (!window.closed) {
                     console.log("没有权限关闭窗口。");
-                    location.href = "/shr/dynamic.do?uipk=shr.workflow.view&inFrame=true&target=allMessageConfig";
+                    location.href = "/shr/dynamic.do?uipk=shr.workflow.view&inFrame=true";
                 }
             } catch (error) {
                 console.log("关闭窗口失败:", error.message);

BIN
patch/202500108/sp_scy_OASSO.jar


+ 3 - 3
patch/apusic/server1/config/web.xml

@@ -98,12 +98,12 @@ configurations in this file.
     </init-param>
     <init-param>
       <param-name>enableCSRFCheck</param-name>
-      <param-value>true</param-value>
+      <param-value>false</param-value>
     </init-param>
     <init-param>
       <!-- CSRF WHITE LIST,SPLIT BY , -->
       <param-name>serverNameWhiteList</param-name>
-      <param-value>yunzhijia.com,kdweibo.com,http://ehr.shichuangyi.cn:8080/shr,/shr/api/oAToSHR</param-value>
+      <param-value>yunzhijia.com,kdweibo.com,http://ehr.shichuangyi.cn:8080/shr,/shr/api/oAToSHR,http://oa.shichuangyi.cn,http://10.0.3.51,/shr/api/oAToMBos,/shr/api/batchApprove</param-value>
     </init-param>
     <init-param>
       <param-name>enableCSRFCheck_URL</param-name>
@@ -111,7 +111,7 @@ configurations in this file.
     </init-param>
     <init-param>
       <param-name>allow_URLS</param-name>
-      <param-value>/ormrpc/,/eassso/YZJCallbackServlet/,/portal/easrpc/,/plt_cm/,/plt_cm/content/,/plt_cm/content/easrpc/,/easweb/servlet/,/easportal/openapi/,/shr/api/oAToSHR</param-value>
+      <param-value>/ormrpc/,/eassso/YZJCallbackServlet/,/portal/easrpc/,/plt_cm/,/plt_cm/content/,/plt_cm/content/easrpc/,/easweb/servlet/,/easportal/openapi/,/shr/api/oAToSHR,/shr/api/oAToMBos,/shr/api/batchApprove</param-value>
     </init-param>
     <init-param>
       <param-name>enableCSRFCheck_POST</param-name>

+ 1 - 1
patch/deploy/WEB-INF/sso/ssoParamemter.properties

@@ -15,7 +15,7 @@ sso.client.serverNameFromRequest=true
 #SSO \u5ba2\u6237\u7aef\u548c\u670d\u52a1\u5668\u662f\u5426\u76f8\u540c\u4e3b\u673a\u5730\u5740
 #\u662f\u5426\u81ea\u52a8\u4ecerequest\u8bf7\u6c42\u4e2d\u83b7\u53d6\u670d\u52a1\u5668\u7684\u8bbf\u95eeurl\u5730\u5740\u7684ip\u548c\u7aef\u53e3\u53f7\uff0c\u5982\u679c\u8bbe\u7f6e\u4e3atrue\u5219cas.server.url\u53c2\u6570\u7684ip\u548c\u7aef\u53e3\u53f7\u5931\u6548
 sso.server.loginUrlFromRequest=true
-cas.client.UrlPattern=/autoLogin.jsp;/toGuiRelogin.jsp;/switchToLogin.jsp;/success.jsp;/redirectTo.jsp;/releaseWafResAjax.jsf;/logout;/web_frame/easrpc/frame.do;/jslib/;/OTP2sso.jsp;/index2sso.jsp;/OSF2sso.jsp;/shrlogin.jsp;/shrosf.jsp;/downloadFileForMulMachine.do;/orgchart;/personPhoto;/manager;/api/oAToSHR
+cas.client.UrlPattern=/autoLogin.jsp;/toGuiRelogin.jsp;/switchToLogin.jsp;/success.jsp;/redirectTo.jsp;/releaseWafResAjax.jsf;/logout;/web_frame/easrpc/frame.do;/jslib/;/OTP2sso.jsp;/index2sso.jsp;/OSF2sso.jsp;/shrlogin.jsp;/shrosf.jsp;/downloadFileForMulMachine.do;/orgchart;/personPhoto;/manager;/api/oAToSHR;/api/oAToMBos;/api/batchApprove
 
 
 

+ 234 - 160
patch/deploy/WEB-INF/web.xml

@@ -5,16 +5,13 @@
 	<context-param>
 		<param-name>contextConfigLocation</param-name>
 		<param-value>/WEB-INF/sso/applicationContext-ssoClient.xml</param-value>
-	</context-param>
-	<context-param>
+	</context-param><context-param>
 		<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
 		<param-value>client</param-value>
-	</context-param>
-	<context-param>
-		<param-name>facelets.SKIP_COMMENTS</param-name>
-		<param-value>true</param-value>
-	</context-param>
-	<context-param>
+	</context-param><context-param>
+        <param-name>facelets.SKIP_COMMENTS</param-name>
+   		 <param-value>true</param-value>
+    </context-param><context-param>
 		<param-name>
 			org.operamasks.faces.IMPLICIT_NAVIGATION
 		</param-name>
@@ -40,89 +37,96 @@
 		</param-name>
 		<param-value>/WEB-INF/attributeSetting.properties</param-value>
 	</context-param>
+
 	<!--cas 3.0 client begin-->
 	<context-param>
 		<param-name>facelets.LIBRARIES</param-name>
 		<param-value>/WEB-INF/taglib/waf.taglib.xml</param-value>
 	</context-param>
+	
 	<!-- value: development, production -->
 	<context-param>
 		<param-name>productionMode</param-name>
 		<param-value>production</param-value>
 	</context-param>
-	<!-- Light App login filter begin -->
-	<filter>
-		<filter-name>CAS Single Sign Out Filter</filter-name>
-		<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
+	<!-- Light App login filter begin --> 
+	<filter>  
+		<filter-name>CAS Single Sign Out Filter</filter-name>    
+		<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>    
 	</filter>
-	<filter>
+    <filter>
 		<filter-name>encodingFilter</filter-name>
 		<filter-class>
           org.springframework.web.filter.CharacterEncodingFilter
 		</filter-class>
-		<init-param>
+		<init-param> 
 			<param-name>encoding</param-name>
 			<param-value>UTF-8</param-value>
 		</init-param>
-		<init-param>
+		<init-param> 
 			<param-name>forceEncoding</param-name>
 			<param-value>true</param-value>
 		</init-param>
 	</filter>
-	<filter-mapping>
+	<filter-mapping> 
 		<filter-name>encodingFilter</filter-name>
 		<url-pattern>*.do</url-pattern>
 	</filter-mapping>
-	<filter-mapping>
+	<filter-mapping> 
 		<filter-name>encodingFilter</filter-name>
 		<url-pattern>*.jsp</url-pattern>
 	</filter-mapping>
+	
 	<!-- order:1  SHRRequestParamWrapFilter -->
 	<filter>
 		<filter-name>SHRRequestParamWrapFilter</filter-name>
 		<filter-class>com.kingdee.shr.base.syssetting.web.filter.SHRRequestParameterWrapFilter</filter-class>
 		<init-param>
-			<param-name>enableSHRRequestParamWrapFilter</param-name>
-			<param-value>true</param-value>
-		</init-param>
+      		<param-name>enableSHRRequestParamWrapFilter</param-name>
+      		<param-value>true</param-value>
+   		</init-param>
 	</filter>
-	<filter-mapping>
+	<filter-mapping> 
 		<filter-name>SHRRequestParamWrapFilter</filter-name>
 		<url-pattern>/*</url-pattern>
 	</filter-mapping>
+	
+	
+
 	<!-- order:2 XSSFilter -->
-	<filter>
+		<filter>
 		<filter-name>XSSFilter</filter-name>
 		<filter-class>com.kingdee.shr.base.syssetting.web.filter.XSSFilter</filter-class>
 		<init-param>
 			<!--request uipkWhiteList , if  request uipk include uipkWhiteList,then ignore filter -->
-			<param-name>uipkAndHandlerWhiteList</param-name>
-			<param-value>
+      		<param-name>uipkAndHandlerWhiteList</param-name>
+      		<param-value>
       			com.kingdee.shr.base.syssetting.app.UIView.form,
       			sourcecompare,
       			com.kingdee.shr.base.syssetting.app.PrivacyAgreement.form,
       			com.kingdee.shr.baseconfig.app.DocumentationConfig.form,
 				com.kingdee.shr.base.syssetting.app.FieldRule.form
       		</param-value>
-		</init-param>
+   		</init-param>
 	</filter>
-	<filter-mapping>
+	<filter-mapping> 
 		<filter-name>XSSFilter</filter-name>
 		<url-pattern>/*</url-pattern>
 	</filter-mapping>
+
 	<!-- order:3 SQLInjectionFilter -->
 	<filter>
 		<filter-name>SQLInjectionFilter</filter-name>
 		<filter-class>com.kingdee.shr.base.syssetting.web.filter.SQLInjectionFilter</filter-class>
 		<init-param>
-			<param-name>enableSQLInjectionFilter</param-name>
-			<!--enableSQLInjectionFilter default value is true,if need turn on,change value is : false -->
-			<param-value>true</param-value>
-		</init-param>
+      		<param-name>enableSQLInjectionFilter</param-name>
+      		<!--enableSQLInjectionFilter default value is true,if need turn on,change value is : false -->
+      		<param-value>true</param-value>
+   		</init-param>
 		<init-param>
 			<!--request uipkWhiteList , if  request uipk include uipkWhiteList,then ignore filter -->
-			<param-name>uipkWhiteList</param-name>
-			<param-value>
+      		<param-name>uipkWhiteList</param-name>
+      		<param-value>
       			com.kingdee.shr.dataplatform.app.CustomSQL.form,
       			com.kingdee.shr.dataplatform.app.DataSetConfig.form,
       			com.kingdee.shr.base.syssetting.app.UIView.form,
@@ -134,7 +138,7 @@
       			com.kingdee.shr.compensation.app.FormulaFunc.form,
       			com.kingdee.shr.compensation.app.FormulaTmpTable.form
       		</param-value>
-		</init-param>
+   		</init-param>
 		<init-param>
 			<!--sql key wrod , if  request value include drop or delete .... ,then replace -->
 			<param-name>sqlKeyWord</param-name>
@@ -149,19 +153,21 @@
 			<param-value>permItemId,personId,personID,relatedFieldId,serviceId,rootId,nodeId,billId,orgId,orgid,serviceName,uipk,sorterItems,parameters,sidx,sord,query,staffingId,staffId,uiClass,keyField,nd,objectID,proposerName,attendPeriodId,attendanceGroupID,proposerId,attendPolicyId,orgLongNum,bizManageTypeID,billIdParam,personid,positionId</param-value>
 		</init-param>
 	</filter>
-	<filter-mapping>
+	<filter-mapping> 
 		<filter-name>SQLInjectionFilter</filter-name>
 		<url-pattern>/*</url-pattern>
 	</filter-mapping>
-	<!-- Light App login filter begin -->
-	<filter>
-		<filter-name>Light App Login Filter</filter-name>
-		<filter-class>com.kingdee.shr.lightapp.filter.LightAppLoginFilter</filter-class>
+	
+    <!-- Light App login filter begin -->
+	<filter>  
+		<filter-name>Light App Login Filter</filter-name>    
+		<filter-class>com.kingdee.shr.lightapp.filter.LightAppLoginFilter</filter-class>    
 	</filter>
 	<filter-mapping>
-		<filter-name>Light App Login Filter</filter-name>
-		<url-pattern>/*</url-pattern>
+	    <filter-name>Light App Login Filter</filter-name>
+        <url-pattern>/*</url-pattern>		
 	</filter-mapping>
+		
 	<!-- AppScanAttackFilter -->
 	<filter>
 		<filter-name>AppScanAttackFilter</filter-name>
@@ -171,12 +177,13 @@
 			<param-value>true</param-value>
 		</init-param>
 	</filter>
-	<filter-mapping>
+	<filter-mapping> 
 		<filter-name>AppScanAttackFilter</filter-name>
 		<url-pattern>/*</url-pattern>
 	</filter-mapping>
+	
 	<!-- order:4 DisableUrlSessionFilter -->
-	<filter>
+    <filter>
 		<filter-name>DisableUrlSessionFilter</filter-name>
 		<filter-class>com.kingdee.shr.base.syssetting.web.filter.DisableUrlSessionFilter</filter-class>
 		<init-param>
@@ -186,14 +193,15 @@
 			</param-value>
 		</init-param>
 	</filter>
-	<filter-mapping>
+	<filter-mapping> 
 		<filter-name>DisableUrlSessionFilter</filter-name>
 		<url-pattern>*.do</url-pattern>
 	</filter-mapping>
-	<filter-mapping>
+	<filter-mapping> 
 		<filter-name>DisableUrlSessionFilter</filter-name>
 		<url-pattern>*.jsp</url-pattern>
-	</filter-mapping>
+	</filter-mapping>	
+	
 	<filter>
 		<filter-name>SHRAuthentiactionFilter</filter-name>
 		<filter-class>com.kingdee.shr.base.syssetting.web.filter.SHRAuthenticationFilter</filter-class>
@@ -203,22 +211,24 @@
 			</param-value>
 		</init-param>
 	</filter>
-	<filter-mapping>
+	<filter-mapping> 
 		<filter-name>SHRAuthentiactionFilter</filter-name>
 		<url-pattern>*.do</url-pattern>
 	</filter-mapping>
-	<filter-mapping>
+	<filter-mapping> 
 		<filter-name>SHRAuthentiactionFilter</filter-name>
 		<url-pattern>*.jsp</url-pattern>
 	</filter-mapping>
-	<filter-mapping>
+	<filter-mapping> 
 		<filter-name>SHRAuthentiactionFilter</filter-name>
 		<url-pattern>*.html</url-pattern>
 	</filter-mapping>
-	<filter-mapping>
+	<filter-mapping> 
 		<filter-name>SHRAuthentiactionFilter</filter-name>
 		<url-pattern>*.htm</url-pattern>
 	</filter-mapping>
+	
+	
 	<filter>
 		<filter-name>CAS Authentication Filter</filter-name>
 		<filter-class>
@@ -229,10 +239,12 @@
 			<param-value>casAuthenticationFilter</param-value>
 		</init-param>
 	</filter>
-	<filter-mapping>
-		<filter-name>CAS Authentication Filter</filter-name>
-		<url-pattern>/*</url-pattern>
+	
+	<filter-mapping>  
+		<filter-name>CAS Authentication Filter</filter-name>  
+		<url-pattern>/*</url-pattern>  
 	</filter-mapping>
+
 	<filter>
 		<filter-name>CAS Validation Filter</filter-name>
 		<filter-class>
@@ -243,10 +255,12 @@
 			<param-value>casTicketValidationFilter</param-value>
 		</init-param>
 	</filter>
-	<filter-mapping>
-		<filter-name>CAS Validation Filter</filter-name>
-		<url-pattern>/*</url-pattern>
+		<filter-mapping>  
+		<filter-name>CAS Validation Filter</filter-name>    
+		<url-pattern>/*</url-pattern>    
 	</filter-mapping>
+	
+	
 	<filter>
 		<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
 		<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
@@ -257,10 +271,13 @@
 			com.kingdee.bos.waf.intercepter.ExtensionFilter
 		</filter-class>
 	</filter-->
+	
 	<filter-mapping>
 		<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
 		<url-pattern>/*</url-pattern>
 	</filter-mapping>
+	
+	
 	<filter>
 		<filter-name>ContextConstructorFilter</filter-name>
 		<filter-class>com.kingdee.bos.sso.client.filter.ContextConstructorFilter</filter-class>
@@ -270,6 +287,7 @@
 		<url-pattern>/*</url-pattern>
 	</filter-mapping>
 	<!-- SSO 结束 -->
+	
 	<!-- 暂时禁用性能监控filter
 	<filter>
     	<filter-name>PerfLog Filter</filter-name>
@@ -281,15 +299,17 @@
 	    <url-pattern>*</url-pattern>
 	</filter-mapping>  
 	 -->
+	
 	<!--filter-mapping>
 		<filter-name>CAS Single Sign Out Filter</filter-name>    
 		<url-pattern>/*</url-pattern>    
 	</filter-mapping-->
+      
+
 	<filter-mapping>
 		<filter-name>CAS Validation Filter</filter-name>
 		<url-pattern>/wfdesigner/*</url-pattern>
-	</filter-mapping>
-	<filter-mapping>
+	</filter-mapping><filter-mapping>
 		<filter-name>CAS Authentication Filter</filter-name>
 		<url-pattern>/wfdesigner/*</url-pattern>
 	</filter-mapping>
@@ -311,6 +331,7 @@
 		<filter-name>CAS Authentication Filter</filter-name>
 		<url-pattern>/servlet/ListServlet</url-pattern>
 	</filter-mapping>
+
 	<filter-mapping>
 		<filter-name>CAS Validation Filter</filter-name>
 		<url-pattern>/servlet/BillServlet</url-pattern>
@@ -319,6 +340,7 @@
 		<filter-name>CAS Validation Filter</filter-name>
 		<url-pattern>/servlet/ListServlet</url-pattern>
 	</filter-mapping>
+
 	<filter-mapping>
 		<filter-name>CAS Authentication Filter</filter-name>
 		<url-pattern>/wf-portal/*</url-pattern>
@@ -331,18 +353,20 @@
 		<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
 		<url-pattern>/wf-portal/*</url-pattern>
 	</filter-mapping>
+	
 	<filter-mapping>
-		<filter-name>CAS Authentication Filter</filter-name>
-		<url-pattern>/workflow/*</url-pattern>
-	</filter-mapping>
-	<filter-mapping>
-		<filter-name>CAS Validation Filter</filter-name>
-		<url-pattern>/workflow/*</url-pattern>
-	</filter-mapping>
-	<filter-mapping>
-		<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
-		<url-pattern>/workflow/*</url-pattern>
-	</filter-mapping>
+        <filter-name>CAS Authentication Filter</filter-name>
+        <url-pattern>/workflow/*</url-pattern>
+    </filter-mapping>
+    <filter-mapping>
+        <filter-name>CAS Validation Filter</filter-name>
+        <url-pattern>/workflow/*</url-pattern>
+    </filter-mapping>
+          <filter-mapping>
+        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
+        <url-pattern>/workflow/*</url-pattern>
+    </filter-mapping>
+    
 	<filter-mapping>
 		<filter-name>CAS Authentication Filter</filter-name>
 		<url-pattern>/billdigesttools/*.jsp</url-pattern>
@@ -355,21 +379,26 @@
 		<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
 		<url-pattern>/billdigesttools/*.jsp</url-pattern>
 	</filter-mapping>
+	
+	
 	<!--filter-mapping>
 
 		<filter-name>WafFilter</filter-name>
 		<url-pattern>*.jsp</url-pattern>
 	</filter-mapping-->
+	
 	<!--cas 3.0 client end-->
+	
 	<filter>
-		<filter-name>SHRWeb RPC Filter</filter-name>
-		<filter-class>com.kingdee.shr.base.syssetting.filter.SHRWebRPCFilter</filter-class>
-	</filter>
-	<!--EASWeb RPC Filter-->
-	<filter-mapping>
-		<filter-name>SHRWeb RPC Filter</filter-name>
-		<url-pattern>/*</url-pattern>
-	</filter-mapping>
+          <filter-name>SHRWeb RPC Filter</filter-name>
+          <filter-class>com.kingdee.shr.base.syssetting.filter.SHRWebRPCFilter</filter-class>
+     </filter>
+     <!--EASWeb RPC Filter-->
+     <filter-mapping>
+         <filter-name>SHRWeb RPC Filter</filter-name>
+         <url-pattern>/*</url-pattern>
+    </filter-mapping>
+    
 	<!-- <filter-mapping>
 		<filter-name>WafFilter</filter-name>
 		<url-pattern>*.jsf</url-pattern>
@@ -390,53 +419,56 @@
 		<filter-name>WafFilter</filter-name>
 		<url-pattern>/servlet/BillListServlet</url-pattern>
 	</filter-mapping> -->
-	<filter>
-		<filter-name>User Monitor</filter-name>
-		<filter-class>com.kingdee.eas.hr.base.web.UserMonitorFilter</filter-class>
-	</filter>
-	<filter-mapping>
+	
+	<filter> 
+		<filter-name>User Monitor</filter-name> 
+		<filter-class>com.kingdee.eas.hr.base.web.UserMonitorFilter</filter-class> 
+    </filter>
+    <filter-mapping> 
 		<filter-name>User Monitor</filter-name>
 		<url-pattern>*.action</url-pattern>
-	</filter-mapping>
-	<filter-mapping>
+    </filter-mapping>
+	    <filter-mapping> 
 		<filter-name>User Monitor</filter-name>
 		<url-pattern>*.do</url-pattern>
-	</filter-mapping>
-	<filter-mapping>
+    </filter-mapping>
+	<filter-mapping> 
 		<filter-name>User Monitor</filter-name>
 		<url-pattern>*.jsp</url-pattern>
-	</filter-mapping>
-	<filter-mapping>
+    </filter-mapping>
+    <filter-mapping> 
 		<filter-name>User Monitor</filter-name>
 		<url-pattern>*.html</url-pattern>
-	</filter-mapping>
-	<filter>
-		<filter-name>HR context Filter</filter-name>
-		<filter-class>com.kingdee.shr.base.filter.HRContextFilter</filter-class>
-	</filter>
-	<filter-mapping>
+    </filter-mapping>
+    
+    <filter> 
+		<filter-name>HR context Filter</filter-name> 
+		<filter-class>com.kingdee.shr.base.filter.HRContextFilter</filter-class> 
+    </filter>
+	    <filter-mapping> 
 		<filter-name>HR context Filter</filter-name>
 		<url-pattern>*.action</url-pattern>
-	</filter-mapping>
-	<filter-mapping>
+    </filter-mapping>
+	    <filter-mapping> 
 		<filter-name>HR context Filter</filter-name>
 		<url-pattern>*.do</url-pattern>
-	</filter-mapping>
-	<filter-mapping>
+    </filter-mapping>
+	<filter-mapping> 
 		<filter-name>HR context Filter</filter-name>
 		<url-pattern>*.jsp</url-pattern>
-	</filter-mapping>
-	<filter-mapping>
+    </filter-mapping>
+    <filter-mapping> 
 		<filter-name>HR context Filter</filter-name>
 		<url-pattern>*.html</url-pattern>
-	</filter-mapping>
-	<filter>
-		<filter-name>Upgrade Monitor</filter-name>
-		<filter-class>com.kingdee.shr.base.syssetting.filter.UpgradeMonitorFilter</filter-class>
-		<init-param>
-			<!-- 升级url白名单,配置在里面的无需拦截-->
-			<param-name>urlWhiteListed</param-name>
-			<param-value>
+    </filter-mapping>
+    
+    <filter>
+        <filter-name>Upgrade Monitor</filter-name>
+        <filter-class>com.kingdee.shr.base.syssetting.filter.UpgradeMonitorFilter</filter-class>
+        <init-param>
+        	<!-- 升级url白名单,配置在里面的无需拦截-->
+        	<param-name>urlWhiteListed</param-name>
+        	<param-value>
             	/index.jsp,
             	/login.do,
             	/notUpgraded.jsp,
@@ -453,22 +485,22 @@
             	/web_frame/easrpc/frame.do,
             	/shr_loginout/logoutAndReleaseResource.do
         	</param-value>
-		</init-param>
-		<init-param>
-			<!-- 升级uipk白名单,配置在里面的无需拦截-->
-			<param-name>uipkWhiteListed</param-name>
-			<param-value>
+    	</init-param>
+    	<init-param>
+    		<!-- 升级uipk白名单,配置在里面的无需拦截-->
+        	<param-name>uipkWhiteListed</param-name>
+        	<param-value>
             	com.kingdee.eas.hr.mvdt.app.ControlDataMoveProject.form,
             	shr.org.AdminOrgUnitDataMove_list,
             	com.kingdee.eas.basedata.org.app.OrgUnitLayerType.F7,
             	shr.org.AdminOrgUnitDataMove_form,
             	com.kingdee.shr.shrimport.app.ImportTask.userList
         	</param-value>
-		</init-param>
-		<init-param>
-			<!-- 升级handler白名单,配置在里面的无需拦截-->
-			<param-name>handlerWhiteListed</param-name>
-			<param-value>
+    	</init-param>
+    	<init-param>
+    		<!-- 升级handler白名单,配置在里面的无需拦截-->
+        	<param-name>handlerWhiteListed</param-name>
+        	<param-value>
             	com.kingdee.eas.hr.mvdt.web.handler.ControlDataMoveProjectHandler,
             	com.kingdee.eas.hr.mvdt.web.handler.DataMoveProjectHandler,
             	com.kingdee.eas.hr.mvdt.web.handler.SHRMvTableListHandler,
@@ -481,33 +513,36 @@
             	com.kingdee.shr.hr.mvdt.handler.ControlCompensationDataMoveHandler,
             	com.kingdee.shr.base.syssetting.web.handler.LogJarClassInfoToolsHandler
         	</param-value>
-		</init-param>
-	</filter>
-	<filter-mapping>
+    	</init-param>
+    </filter>
+    <filter-mapping> 
 		<filter-name>Upgrade Monitor</filter-name>
 		<url-pattern>*.action</url-pattern>
-	</filter-mapping>
-	<filter-mapping>
+    </filter-mapping>
+    <filter-mapping> 
 		<filter-name>Upgrade Monitor</filter-name>
 		<url-pattern>*.do</url-pattern>
-	</filter-mapping>
-	<filter-mapping>
+    </filter-mapping>
+	<filter-mapping> 
 		<filter-name>Upgrade Monitor</filter-name>
 		<url-pattern>*.jsp</url-pattern>
-	</filter-mapping>
-	<filter-mapping>
+    </filter-mapping>
+    <filter-mapping> 
 		<filter-name>Upgrade Monitor</filter-name>
 		<url-pattern>*.html</url-pattern>
-	</filter-mapping>
+    </filter-mapping>
+	
 	<listener>
 		<listener-class>
 			org.springframework.web.context.ContextLoaderListener
 		</listener-class>
 	</listener>
-	<!-- SSO 开始 -->
+	
+		<!-- SSO 开始 -->
 	<listener>
 		<listener-class>com.kingdee.eas.cp.common.url.service.web.WebSessionListener</listener-class>
 	</listener>
+	
 	<!-- <servlet>
 		<servlet-name>WfProcessImageServlet</servlet-name>
 		<servlet-class>com.kingdee.bos.workflow.designer.servlet.ProcessImageServlet</servlet-class>
@@ -540,14 +575,7 @@
 			com.kingdee.bos.waf.security.Logout
 		</servlet-class>
 	</servlet-->
-	<servlet>
-		<servlet-name>BuffaloServlet</servlet-name>
-		<servlet-class>net.buffalo.web.servlet.ApplicationServlet</servlet-class>
-		<init-param>
-			<param-name>debug</param-name>
-			<param-value>true</param-value>
-		</init-param>
-	</servlet>
+	
 	<!-- webApi servlet-->
 	<servlet>
 		<servlet-name>OAToSHR</servlet-name>
@@ -558,11 +586,41 @@
 		<url-pattern>/api/oAToSHR</url-pattern>
 	</servlet-mapping>
 
+	<!-- webApi servlet-->
+	<servlet>
+		<servlet-name>OAToMbos</servlet-name>
+		<servlet-class>com.kingdee.eas.custom.sso.OAToMBos</servlet-class>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>OAToMbos</servlet-name>
+		<url-pattern>/api/oAToMBos</url-pattern>
+	</servlet-mapping>
+
+	<!-- BatchApprove servlet-->
+	<servlet>
+		<servlet-name>batchApprove</servlet-name>
+		<servlet-class>com.kingdee.eas.custom.sso.BatchApprove</servlet-class>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>batchApprove</servlet-name>
+		<url-pattern>/api/batchApprove</url-pattern>
+	</servlet-mapping>
+
+	<servlet>
+		<servlet-name>BuffaloServlet</servlet-name>
+		<servlet-class>net.buffalo.web.servlet.ApplicationServlet</servlet-class>
+		<init-param>
+			<param-name>debug</param-name>
+			<param-value>true</param-value>
+		</init-param>
+	</servlet>
 
+	
 	<servlet-mapping>
 		<servlet-name>BuffaloServlet</servlet-name>
 		<url-pattern>/BUFFALO/*</url-pattern>
 	</servlet-mapping>
+
 	<!-- <servlet-mapping>
 		<servlet-name>WfProcessImageServlet</servlet-name>
 		<url-pattern>/processimage/*</url-pattern>
@@ -571,6 +629,7 @@
 		<servlet-name>FlexMessageBrokerServlet</servlet-name>
 		<url-pattern>/messagebroker/*</url-pattern>
 	</servlet-mapping> -->
+
 	<!--servlet-mapping>
 		<servlet-name>Faces Servlet</servlet-name>
 		<url-pattern>*.jsf</url-pattern>
@@ -583,10 +642,12 @@
 		<servlet-name>ResourceServlet</servlet-name>
 		<url-pattern>/_global/*</url-pattern>
 	</servlet-mapping-->
-	<mime-mapping>
-		<extension>mht</extension>
-		<mime-type>message/rfc822</mime-type>
+	
+	<mime-mapping> 
+		<extension>mht</extension> 
+		<mime-type>message/rfc822</mime-type> 
 	</mime-mapping>
+	
 	<!-- pack script -->
 	<servlet>
 		<description>This is the servlet needed for cache.type servlet, returns the packed resources</description>
@@ -594,22 +655,24 @@
 		<servlet-name>PackServlet</servlet-name>
 		<servlet-class>net.sf.packtag.servlet.PackServlet</servlet-class>
 	</servlet>
+
 	<servlet-mapping>
 		<servlet-name>PackServlet</servlet-name>
 		<url-pattern>styles/combined*.css</url-pattern>
-	</servlet-mapping>
+	</servlet-mapping>	
 	<servlet-mapping>
 		<servlet-name>PackServlet</servlet-name>
 		<url-pattern>combined*.js</url-pattern>
-	</servlet-mapping>
+	</servlet-mapping>	
 	<servlet-mapping>
 		<servlet-name>PackServlet</servlet-name>
 		<url-pattern>styles/external*.css</url-pattern>
-	</servlet-mapping>
+	</servlet-mapping>	
 	<servlet-mapping>
 		<servlet-name>PackServlet</servlet-name>
 		<url-pattern>external*.js</url-pattern>
 	</servlet-mapping>
+	
 	<context-param>
 		<param-name>
 			com.kingdee.bos.webframework.SCRIPT_DEBUG
@@ -628,15 +691,17 @@
 		</param-name>
 		<param-value>L1,L2,L3</param-value>
 	</context-param>
-	<!--context-param>   
+	
+	 <!--context-param>   
 	    <param-name>webAppRootKey</param-name>   
 	    <param-value>easweb.root</param-value> 
-	 </context-param-->
-	<!--listener>   
+	 </context-param--> 
+	 <!--listener>   
 	    <listener-class>   
 	    org.springframework.web.util.WebAppRootListener   
 	    </listener-class>   
 	 </listener-->
+	
 	<filter>
 		<filter-name>WafHttpRequestFilter</filter-name>
 		<filter-class>com.kingdee.shr.base.syssetting.filter.ShrHttpRequestFilter</filter-class>
@@ -648,25 +713,27 @@
 			<param-name>RESPONSE_BUFFER_SIZE</param-name>
 			<param-value>5000</param-value>
 		</init-param>
-	</filter>
-	<filter-mapping>
-		<filter-name>CAS Authentication Filter</filter-name>
-		<url-pattern>*.do</url-pattern>
+	</filter> 
+	<filter-mapping>  
+		<filter-name>CAS Authentication Filter</filter-name>  
+		<url-pattern>*.do</url-pattern>  
 	</filter-mapping>
-	<filter-mapping>
-		<filter-name>CAS Validation Filter</filter-name>
-		<url-pattern>*.do</url-pattern>
+	<filter-mapping>  
+		<filter-name>CAS Validation Filter</filter-name>    
+		<url-pattern>*.do</url-pattern>    
 	</filter-mapping>
 	<filter-mapping>
 		<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
 		<url-pattern>*.do</url-pattern>
 	</filter-mapping>
+	
 	<filter>
 		<filter-name>Waf2ContextFilter</filter-name>
 		<filter-class>
             com.kingdee.shr.base.syssetting.filter.SHRContextFilter
 		</filter-class>
 	</filter>
+
 	<filter-mapping>
 		<filter-name>Waf2ContextFilter</filter-name>
 		<url-pattern>*.do</url-pattern>
@@ -675,15 +742,17 @@
 		<filter-name>WafHttpRequestFilter</filter-name>
 		<url-pattern>*.do</url-pattern>
 	</filter-mapping>
+	
 	<!-- order:  SHRRequestWorkPlatformFilter -->
 	<filter>
 		<filter-name>SHRRequestWorkPlatformFilter</filter-name>
 		<filter-class>com.kingdee.shr.base.syssetting.web.filter.SHRRequestWorkPlatformFilter</filter-class>
 	</filter>
-	<filter-mapping>
+	<filter-mapping> 
 		<filter-name>SHRRequestWorkPlatformFilter</filter-name>
 		<url-pattern>*.html</url-pattern>
 	</filter-mapping>
+	
 	<servlet>
 		<servlet-name>MVCServlet</servlet-name>
 		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
@@ -697,25 +766,30 @@
 		<servlet-name>MVCServlet</servlet-name>
 		<url-pattern>*.do</url-pattern>
 	</servlet-mapping>
+
 	<!-- 500错误页面 -->
 	<error-page>
-		<error-code>500</error-code>
-		<location>/500.jsp</location>
-	</error-page>
+        <error-code>500</error-code>
+        <location>/500.jsp</location>
+    </error-page>
+	
 	<!-- 404错误页面 -->
 	<error-page>
-		<error-code>404</error-code>
-		<location>/404.jsp</location>
-	</error-page>
+        <error-code>404</error-code>
+        <location>/404.jsp</location>
+    </error-page>
+	
 	<listener>
 		<listener-class>com.kingdee.shr.base.syssetting.web.listener.SHRAppListener</listener-class>
 	</listener>
 	<listener>
 		<listener-class>com.kingdee.shr.base.syssetting.web.listener.SHRSessionListener</listener-class>
-	</listener>
+	</listener>	
+	
 	<welcome-file-list>
 		<welcome-file>index.jsp</welcome-file>
 	</welcome-file-list>
+	
 	<mime-mapping>
 		<extension>docx</extension>
 		<mime-type>application/vnd.openxmlformats-officedocument.wordprocessingml.document</mime-type>

+ 151 - 65
src/com/kingdee/eas/custom/messageWebService/OAMessageWebServiceDao.java

@@ -4,16 +4,23 @@ import com.alibaba.fastjson.JSONObject;
 import com.kingdee.bos.BOSException;
 import com.kingdee.bos.Context;
 import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
+import com.kingdee.bos.metadata.IMetaDataLoader;
+import com.kingdee.bos.metadata.MetaDataLoaderFactory;
+import com.kingdee.bos.metadata.entity.EntityObjectInfo;
 import com.kingdee.bos.util.BOSUuid;
 import com.kingdee.bos.workflow.metas.AssignFactory;
 import com.kingdee.bos.workflow.metas.AssignInfo;
 import com.kingdee.bos.workflow.metas.IAssign;
 import com.kingdee.bos.workflow.metas.WfAssignmentState;
 import com.kingdee.eas.base.message.*;
+import com.kingdee.eas.base.message.util.ProcessCenterUtil;
 import com.kingdee.eas.base.message.webservice.MessageWebServiceDao;
 import com.kingdee.eas.base.message.webservice.WSMessage;
 import com.kingdee.eas.base.message.webservice.WfrAssignMessage;
 import com.kingdee.eas.base.message.webservice.WfrProcMessage;
+import com.kingdee.eas.base.permission.IUser;
+import com.kingdee.eas.base.permission.UserFactory;
+import com.kingdee.eas.base.permission.UserInfo;
 import com.kingdee.eas.basedata.person.IPerson;
 import com.kingdee.eas.basedata.person.PersonFactory;
 import com.kingdee.eas.basedata.person.PersonInfo;
@@ -29,7 +36,6 @@ import java.net.URLEncoder;
 import java.text.MessageFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
-
 import java.util.Properties;
 
 /**
@@ -43,6 +49,11 @@ public class OAMessageWebServiceDao implements MessageWebServiceDao {
     private final String MBOSURL = "https://mbos.kdeascloud.com/mbos/mbosw/getWorkflowUrl?assignId={0}&eid={1}&storeEid={2}&name=approveui.navui&billID={3}";
     //mbos流程助手首页
     private final String MBOSAPPROVECENTERURL = "https://mbos.kdeascloud.com/mbos/page/loadPage?appid=10036&eid={0}&path=lczs2&name=lczshome.navui";
+    //pc转阅地址
+    private final String PASSASSIGNMENTURL = "{0}/easweb/dynamicPage.do?event=initialize&method=doEvent&uipk=com.kingdee.bos.workflow.metas.approve&type=passComent&sourceIDs={1}&msgId={2}&assignmentId={3}&passid={4}&billID={5}";
+    //mbos传阅
+    private final String MBOSPASSASSIGNMENTURL = "https://mbos.kdeascloud.com/mbos/page/loadPage?path=lczs2&name=approveui.navui&lczstype=list&eid={0}&appid=10036&cometype=myreceivepass&billID={1}&fprocinstid={2}&fpassid={3}&msgid={4}&operateState=VIEW&storeEid={5}";
+
     String propPath = System.getProperty("EAS_HOME") + "/server/properties/scy/receiveOAConfig.properties";
 
     public OAMessageWebServiceDao() {
@@ -63,7 +74,7 @@ public class OAMessageWebServiceDao implements MessageWebServiceDao {
     @Override
     public boolean addMessage(WSMessage message) {
         logger.error("*********OAMessageWebServiceDao addMessage 消息监听开始**********");
-        return sendMessage(message, "0", "0");
+        return sendMessage(message, "0", "0", null);
     }
 
 
@@ -152,15 +163,16 @@ public class OAMessageWebServiceDao implements MessageWebServiceDao {
                 IAssign iAssign = AssignFactory.getLocalInstance(ctx);
                 IPerson iPerson = PersonFactory.getLocalInstance(ctx);
                 AssignInfo assignInfo = iAssign.getValue(new ObjectUuidPK(assignID));
+                IUser iUser = UserFactory.getLocalInstance(ctx);
                 WSMessage wsMessage = new WSMessage();
                 wsMessage.setMsgID(id);
                 wsMessage.setTitle(assignInfo.getSubject());
                 wsMessage.setBillId(assignInfo.getBizObjID());
                 wsMessage.setContext(ctx);
                 String priorPerformerID = assignInfo.getPriorPerformerID();
-                PersonInfo sender = iPerson.getPersonInfo(new ObjectUuidPK(priorPerformerID));
-                wsMessage.setSenderNumber(sender.getNumber());
-                wsMessage.setSender(sender.getName());
+                UserInfo userInfo = iUser.getUserInfo(new ObjectUuidPK(priorPerformerID));
+                wsMessage.setSenderNumber(userInfo.getNumber());
+                wsMessage.setSender(userInfo.getName());
                 String personEmpId = assignInfo.getPersonEmpID().toString();
                 PersonInfo reciever = iPerson.getPersonInfo(new ObjectUuidPK(personEmpId));
                 wsMessage.setReceivers(reciever.getName());
@@ -168,9 +180,9 @@ public class OAMessageWebServiceDao implements MessageWebServiceDao {
                 wsMessage.setRecieverID(personEmpId);
                 if (MsgStatus.READED.equals(msgStatus)) {
                     //已读
-                    return sendMessage(wsMessage, "0", "1");
+                    return sendMessage(wsMessage, "0", "1", assignID);
                 } else {
-                    return sendMessage(wsMessage, "0", "0");
+                    return sendMessage(wsMessage, "0", "0", assignID);
                 }
             } catch (Exception e) {
                 e.printStackTrace();
@@ -215,11 +227,6 @@ public class OAMessageWebServiceDao implements MessageWebServiceDao {
             } else {
                 throw new RuntimeException("未找到对应的任务阅读表  assignId: " + assignId);
             }
-//            if (WfAssignmentState.CANCELED.equals(stateEnum)) {
-//                //任务取消,删除OA待办
-//                return deleteMessage(msgId, handlerNumber);
-//            } else
-
             if (WfAssignmentState.COMPLETED.equals(stateEnum)
                     || WfAssignmentState.REJECTED.equals(stateEnum)
                     || WfAssignmentState.CANCELED.equals(stateEnum)) {
@@ -234,7 +241,7 @@ public class OAMessageWebServiceDao implements MessageWebServiceDao {
                 wsMessage.setReceivers(handler);
                 wsMessage.setRecieveNumber(handlerNumber);
                 wsMessage.setRecieverID(wfrAssignMessage.getHandlerId());
-                return sendMessage(wsMessage, "2", "1");
+                return sendMessage(wsMessage, "2", "1", assignId);
             }
         } catch (BOSException e) {
             e.printStackTrace();
@@ -248,7 +255,8 @@ public class OAMessageWebServiceDao implements MessageWebServiceDao {
      * @param viewtype 流程查看状态
      * @return
      */
-    private boolean sendMessage(WSMessage message, String isremark, String viewtype) {
+    private boolean sendMessage(WSMessage message, String isremark, String viewtype, String assignId) {
+        Context ctx = message.getContext();
         try {
             String serverName = prop.getProperty("serverName");
             String receiveOAPath = prop.getProperty("receiveOAPath");
@@ -262,24 +270,21 @@ public class OAMessageWebServiceDao implements MessageWebServiceDao {
             String now = sdf.format(date);
             params.put("syscode", syscode);//异构系统标识
             params.put("flowid", message.getMsgID());//流程实例id
-            params.put("requestname", message.getTitle());//标题
-            MsgType type = message.getType();
-            if (type != null) {
-                params.put("workflowname", type.getAlias());//流程类型名称
+            //业务类型
+            MsgBizType bizType = message.getBizType();
+            if (MsgBizType.URGENT.equals(bizType)) {
+                //催办
+                params.put("requestname", message.getBody());//标题
             } else {
-                params.put("workflowname", "任务");
+                params.put("requestname", message.getTitle());//标题
             }
             String billId = message.getBillId();
             logger.error("billId: " + billId);
-            String assignID = null;
-            if (!StringUtils.isEmpty(message.getMsgID())) {
-                IAssignRead assignReadIns = AssignReadFactory.getLocalInstance(message.getContext());
-                AssignReadInfo assignReadInfo = assignReadIns.getAssignReadInfo(new ObjectUuidPK(message.getMsgID()));
-                assignID = assignReadInfo.getAssignID().toString();
-            }
-
-            params.put("pcurl", getPcUrl(serverName, assignID));//PC地址(相对路径/开头)
-            params.put("appurl", getAppUrl(message.getContext(), serverName, assignID));//APP地址(相对路径/开头)
+            //MsgType type = message.getType();
+            String workflowname = getFlowTypeNameyBillId(ctx, message.getMsgID(), billId, assignId);
+            params.put("workflowname", workflowname);//流程类型名称
+            params.put("pcurl", getPcUrl(ctx, serverName, message, bizType, assignId));//PC地址(相对路径/开头)
+            params.put("appurl", getAppUrl(ctx, serverName, message, bizType, assignId));//APP地址(相对路径/开头)
             params.put("nodename", "sHR");//步骤名称(节点名称)
             params.put("isremark", isremark);//流程处理状态
             params.put("viewtype", viewtype);//流程查看状态
@@ -321,61 +326,103 @@ public class OAMessageWebServiceDao implements MessageWebServiceDao {
     /**
      * 获取pc待办地址
      *
+     * @param ctx
      * @param serverName
-     * @param assignID
+     * @param message
      * @return
+     * @throws UnsupportedEncodingException
      * @throws BOSException
      * @throws EASBizException
-     * @throws UnsupportedEncodingException
      */
-    private String getPcUrl(String serverName, String assignID)
-            throws UnsupportedEncodingException {
-        StringBuilder pcurl = new StringBuilder();
-        StringBuilder redirectUrl = new StringBuilder();
-        pcurl.append(serverName).append("/shr/api/oAToSHR?redirect=");
-        if (!StringUtils.isEmpty(assignID)) {
-            redirectUrl.append(serverName).append("/easweb/webviews/workflow/transferApprove.jsp?AssignmentId=")
-                    .append(assignID);
-        } else {
-            redirectUrl.append(serverName).append("/shr/dynamic.do?uipk=shr.perself.homepage");
+    private String getPcUrl(Context ctx, String serverName, WSMessage message, MsgBizType bizType, String assignId)
+            throws BOSException {
+        try {
+            String msgId = message.getMsgID();
+            String billId = message.getBillId();
+            StringBuilder pcurl = new StringBuilder();
+            pcurl.append(serverName).append("/shr/api/oAToSHR?redirect=");
+            String bosType = BOSUuid.read(msgId).getType().toString();
+            if ("9623EB51".equals(bosType)) {
+                //任务阅读表
+                StringBuilder redirectUrl = new StringBuilder();
+                if (StringUtils.isBlank(assignId)) {
+                    IAssignRead assignReadIns = AssignReadFactory.getLocalInstance(ctx);
+                    AssignReadInfo assignReadInfo = assignReadIns.getAssignReadInfo(new ObjectUuidPK(msgId));
+                    assignId = assignReadInfo.getAssignID().toString();
+                }
+                if (StringUtils.isNotBlank(assignId)) {
+                    if (StringUtils.isBlank(billId)) {
+                        URLInfo info = ProcessCenterUtil.getUrlInfos(assignId, ctx);
+                        billId = info.getBillID();
+                    }
+                    redirectUrl.append(serverName).append("/easweb/webviews/workflow/transferApprove.jsp?AssignmentId=")
+                            .append(URLEncoder.encode(assignId, "UTF-8")).append("&billID=").append(URLEncoder.encode(billId, "UTF-8"));
+                } else {
+                    redirectUrl.append(serverName).append("/shr/dynamic.do?uipk=shr.perself.homepage");
+                }
+                pcurl.append(URLEncoder.encode(redirectUrl.toString(), "UTF-8"));
+                logger.error("pcurl: " + pcurl);
+                return pcurl.toString();
+            } else {
+                throw new RuntimeException("bosType类型未找到: " + bosType);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new BOSException(e.getMessage());
         }
-        pcurl.append(URLEncoder.encode(redirectUrl.toString(), "UTF-8"));
-        return pcurl.toString();
     }
 
     /**
      * 获取app待办地址
      *
      * @param serverName
-     * @param assignID
+     * @param message
      * @return
      * @throws BOSException
      * @throws EASBizException
      * @throws UnsupportedEncodingException
      */
-    private String getAppUrl(Context ctx, String serverName, String assignID)
-            throws UnsupportedEncodingException, BOSException {
-        StringBuilder appUrl = new StringBuilder();
-        appUrl.append(serverName).append("/shr/api/oAToMBos?redirect=");
-        String eid = prop.getProperty("eid");
-        if (StringUtils.isEmpty(eid)) {
-            throw new RuntimeException("发送OA待办消息,eid不能为空! 请检查配置文件: " + propPath);
-        }
-        String redirectUrl = null;
-        if (!StringUtils.isEmpty(assignID)) {
-            IAssign iAssign = AssignFactory.getLocalInstance(ctx);
-            AssignInfo assignInfo = iAssign.getValue(new ObjectUuidPK(assignID));
-            String billId = assignInfo.getBizObjID();
-            redirectUrl = MessageFormat.format(MBOSURL,
-                    URLEncoder.encode(assignID, "UTF-8"),
-                    eid,
-                    "21231",
-                    URLEncoder.encode(billId, "UTF-8"));
-        } else {
-            redirectUrl = MessageFormat.format(MBOSAPPROVECENTERURL, eid);
+    private String getAppUrl(Context ctx, String serverName, WSMessage message, MsgBizType bizType, String assignId)
+            throws BOSException {
+        try {
+            String msgId = message.getMsgID();
+            String billId = message.getBillId();
+            StringBuilder appUrl = new StringBuilder();
+            appUrl.append(serverName).append("/shr/api/oAToMBos?redirect=");
+            String bosType = BOSUuid.read(msgId).getType().toString();
+            String eid = prop.getProperty("eid");
+            if (StringUtils.isEmpty(eid)) {
+                throw new RuntimeException("发送OA待办消息,eid不能为空! 请检查配置文件: " + propPath);
+            }
+            if ("9623EB51".equals(bosType)) {
+                //任务阅读表
+                String redirectUrl = null;
+                if (StringUtils.isBlank(assignId)) {
+                    IAssignRead assignReadIns = AssignReadFactory.getLocalInstance(ctx);
+                    AssignReadInfo assignReadInfo = assignReadIns.getAssignReadInfo(new ObjectUuidPK(msgId));
+                    assignId = assignReadInfo.getAssignID().toString();
+                }
+                if (StringUtils.isNotBlank(assignId)) {
+                    if (StringUtils.isBlank(billId)) {
+                        URLInfo info = ProcessCenterUtil.getUrlInfos(assignId, ctx);
+                        billId = info.getBillID();
+                    }
+                    redirectUrl = MessageFormat.format(MBOSURL,
+                            URLEncoder.encode(assignId, "UTF-8"),
+                            eid,
+                            "21231",
+                            URLEncoder.encode(billId, "UTF-8"));
+                } else {
+                    redirectUrl = MessageFormat.format(MBOSAPPROVECENTERURL, eid);
+                }
+                appUrl.append(URLEncoder.encode(redirectUrl, "UTF-8"));
+            }
+            logger.error("appUrl: " + appUrl);
+            return appUrl.toString();
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new BOSException(e.getMessage());
         }
-        appUrl.append(URLEncoder.encode(redirectUrl, "UTF-8"));
-        return appUrl.toString();
     }
 
 
@@ -426,4 +473,43 @@ public class OAMessageWebServiceDao implements MessageWebServiceDao {
         }
         return false;
     }
+
+    /**
+     * 根据单据id获取流程单据类型名称
+     * @param ctx
+     * @param msgId
+     * @param billId
+     * @param assignId
+     * @return
+     * @throws BOSException
+     * @throws EASBizException
+     */
+    public String getFlowTypeNameyBillId(Context ctx,
+                                         String msgId,
+                                         String billId,
+                                         String assignId)
+            throws BOSException, EASBizException {
+        String flowTypeName = "流程";
+        try {
+            if (StringUtils.isBlank(billId)) {
+                if (StringUtils.isBlank(assignId)) {
+                    IAssignRead assignReadIns = AssignReadFactory.getLocalInstance(ctx);
+                    AssignReadInfo assignReadInfo = assignReadIns.getAssignReadInfo(new ObjectUuidPK(msgId));
+                    assignId = assignReadInfo.getAssignID().toString();
+                }
+                if (StringUtils.isNotBlank(assignId)) {
+                    URLInfo info = ProcessCenterUtil.getUrlInfos(assignId, ctx);
+                    billId = info.getBillID();
+                } else {
+                    return flowTypeName;
+                }
+            }
+            IMetaDataLoader loader = MetaDataLoaderFactory.getRemoteMetaDataLoader();
+            EntityObjectInfo vo = loader.getEntity(BOSUuid.read(billId).getType());
+            flowTypeName = vo.getDisplayName();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return flowTypeName;
+    }
 }

+ 242 - 0
src/com/kingdee/eas/custom/sso/BatchApprove.java

@@ -0,0 +1,242 @@
+package com.kingdee.eas.custom.sso;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.kingdee.shr.api.Response;
+import com.kingdee.shr.api.SHRClient;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.apache.http.HttpException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.URLEncoder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @Description 批量审批单点类
+ * @Date 2024/10/30 11:22
+ * @Created by Heyuan
+ */
+public class BatchApprove extends HttpServlet {
+    private static Logger logger = Logger.getLogger(BatchApprove.class);
+    private Properties prop = new Properties();
+    private String propPath = System.getProperty("EAS_HOME") + "/server/properties/scy/OASSOConfig.properties";
+    //osf服务名称
+    private final String SERVICENAME = "batchApproveEx";
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+            throws ServletException, IOException {
+        logger.error("BatchApprove -> doGet");
+        //doPost(req, resp);
+        BufferedReader streamReader = null;
+        String resultStr = null;
+        prop.load(new FileInputStream(propPath));
+        Map result = new HashMap();
+        StringBuilder errorMsg = new StringBuilder();
+        String loginId = null;
+        //处理跨域问题
+        String origin = req.getHeader("Origin");
+        String method = req.getMethod();
+        System.out.println("method " + method);
+        logger.error("origin " + origin);
+        if (StringUtils.isBlank(origin)) {
+            resp.addHeader("Access-Control-Allow-Origin", "*");
+
+        } else {
+            resp.addHeader("Access-Control-Allow-Origin", origin);
+        }
+        resp.addHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
+        resp.addHeader("Access-Control-Allow-Headers", "Content-Type");
+        try {
+            loginId = req.getParameter("loginId");
+            if (StringUtils.isBlank(loginId)) {
+                errorMsg.append("账号不能为空!\n");
+            }
+            logger.error("BatchApprove ->loginId " + loginId);
+            String serverName = prop.getProperty("serverName");
+            if (StringUtils.isBlank(serverName)) {
+                errorMsg.append("shr地址为空,请检查配置文件: " + propPath + "\n");
+            }
+            //shr测试服务地址
+            String shrAddr = serverName + "/shr";
+            String assignmentIds = req.getParameter("assignmentIds");
+            if (StringUtils.isNotBlank(assignmentIds)) {
+                assignmentIds = URLEncoder.encode(assignmentIds, "utf-8");
+            } else {
+                errorMsg.append("工作流任务id不能为空!\n");
+            }
+            String opinion = req.getParameter("opinion");
+            if (StringUtils.isNotBlank(opinion)) {
+                opinion = URLEncoder.encode(opinion, "utf-8");
+            } else {
+                errorMsg.append("审批意见不能为空!\n");
+            }
+            if (errorMsg.length() > 0) {
+                throw new Exception(errorMsg.toString());
+            }
+            //接口调用者工号,跟OA账号一致(审批流程时会判断调用者是否为流程审批人)
+            Map<String, Object> param = new HashMap();
+            param.put("assignmentIds", assignmentIds);
+            param.put("opinion", opinion);
+            SHRClient shrClient = new SHRClient();
+            Response response = shrClient.executeServiceByName(shrAddr, SERVICENAME, param, loginId);
+            logger.error(response.getData());
+            result.put("data", JSONObject.parseArray(response.getData().toString()));
+            result.put("success", true);
+            result.put("message", "执行成功");
+            resp.setStatus(200);
+        } catch (Exception e) {
+            e.printStackTrace();
+            resp.setStatus(500);
+            String error = e.getMessage();
+            result.put("data", "");
+            result.put("success", false);
+            if (e instanceof HttpException && error.contains("login shr fail")) {
+                result.put("message", "账号不存在 " + loginId);
+            } else {
+                result.put("message", error);
+            }
+        } finally {
+            resultStr = JSON.toJSONString(result);
+            try {
+                if (streamReader != null) {
+                    streamReader.close();
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        PrintWriter writer = resp.getWriter();
+        resp.setContentType("application/json");
+        writer.write(resultStr);
+        writer.close();
+    }
+
+    @Override
+    protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        String origin = request.getHeader("Origin");
+        String method = request.getMethod();
+        System.out.println("method " + method);
+        logger.error("origin " + origin);
+        if (StringUtils.isBlank(origin)) {
+            response.setHeader("Access-Control-Allow-Origin", "*");
+        } else {
+            response.setHeader("Access-Control-Allow-Origin", origin);
+        }
+        // 设置跨域相关的响应头
+        response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
+        response.setHeader("Access-Control-Allow-Headers", "Content-Type");
+        response.setHeader("Access-Control-Max-Age", "3600"); // 缓存时间(秒)
+        response.setStatus(HttpServletResponse.SC_OK); // 返回 200 状态码
+    }
+
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+            throws ServletException, IOException {
+        logger.error("BatchApprove -> doPost");
+        BufferedReader streamReader = null;
+        String resultStr = null;
+        prop.load(new FileInputStream(propPath));
+        Map result = new HashMap();
+        StringBuilder errorMsg = new StringBuilder();
+        String loginId = null;
+        //处理跨域问题
+        String origin = req.getHeader("Origin");
+        String method = req.getMethod();
+        System.out.println("method " + method);
+        logger.error("origin " + origin);
+        if (StringUtils.isBlank(origin)) {
+            resp.addHeader("Access-Control-Allow-Origin", "*");
+
+        } else {
+            resp.addHeader("Access-Control-Allow-Origin", origin);
+        }
+        resp.addHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
+        resp.addHeader("Access-Control-Allow-Headers", "Content-Type");
+        try {
+            //接收json数据
+            streamReader = new BufferedReader(new InputStreamReader(req.getInputStream(), "UTF-8"));
+            StringBuilder responseStrBuilder = new StringBuilder();
+            String inputStr;
+            while ((inputStr = streamReader.readLine()) != null) {
+                responseStrBuilder.append(inputStr);
+            }
+            String dataStr = responseStrBuilder.toString();
+            logger.error("dataStr: " + dataStr);
+            if (StringUtils.isBlank(dataStr)) {
+                throw new Exception("参数不能为空!");
+            }
+            JSONObject params = JSON.parseObject(dataStr);
+            loginId = params.getString("loginId");
+            if (StringUtils.isBlank(loginId)) {
+                errorMsg.append("账号不能为空!\n");
+            }
+            logger.error("BatchApprove ->loginId " + loginId);
+            String serverName = prop.getProperty("serverName");
+            if (StringUtils.isBlank(serverName)) {
+                errorMsg.append("shr地址为空,请检查配置文件: " + propPath + "\n");
+            }
+            //shr测试服务地址
+            String shrAddr = serverName + "/shr";
+            String assignmentIds = params.getString("assignmentIds");
+            if (StringUtils.isNotBlank(assignmentIds)) {
+                assignmentIds = URLEncoder.encode(assignmentIds, "utf-8");
+            } else {
+                errorMsg.append("工作流任务id不能为空!\n");
+            }
+            String opinion = params.getString("opinion");
+            if (StringUtils.isNotBlank(opinion)) {
+                opinion = URLEncoder.encode(opinion, "utf-8");
+            } else {
+                errorMsg.append("审批意见不能为空!\n");
+            }
+            if (errorMsg.length() > 0) {
+                throw new Exception(errorMsg.toString());
+            }
+            //接口调用者工号,跟OA账号一致(审批流程时会判断调用者是否为流程审批人)
+            Map<String, Object> param = new HashMap();
+            param.put("assignmentIds", assignmentIds);
+            param.put("opinion", opinion);
+            SHRClient shrClient = new SHRClient();
+            Response response = shrClient.executeServiceByName(shrAddr, SERVICENAME, param, loginId);
+            logger.error(response.getData());
+            result.put("data", JSONObject.parseArray(response.getData().toString()));
+            result.put("success", true);
+            result.put("message", "执行成功");
+            resp.setStatus(200);
+        } catch (Exception e) {
+            e.printStackTrace();
+            resp.setStatus(500);
+            String error = e.getMessage();
+            result.put("data", "");
+            result.put("success", false);
+            if (e instanceof HttpException && error.contains("login shr fail")) {
+                result.put("message", "账号不存在 " + loginId);
+            } else {
+                result.put("message", error);
+            }
+        } finally {
+            resultStr = JSON.toJSONString(result);
+            try {
+                if (streamReader != null) {
+                    streamReader.close();
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        PrintWriter writer = resp.getWriter();
+        resp.setContentType("application/json");
+        writer.write(resultStr);
+        writer.close();
+    }
+}

+ 3 - 1
src/com/kingdee/eas/custom/sso/OAToMBos.java

@@ -142,8 +142,10 @@ public class OAToMBos extends HttpServlet {
             }
             Map toMbosparams = new HashMap();
             toMbosparams.put("token", token);
+            //todo
             //УÑéÁ÷³ÌÉúЧ״̬
-            redirectUrl = SsoUtil.checkFlowEffectiveStateForMbos(redirectUrl, serverName, getLoginIdPath, token);
+            //redirectUrl = SsoUtil.checkFlowEffectiveStateForMbos(redirectUrl, serverName, getLoginIdPath, token);
+            redirectUrl = SsoUtil.checkBillExistForMbos(redirectUrl, serverName, getLoginIdPath, token);
             String urlString = SsoUtil.appendUrl(redirectUrl, toMbosparams);
             resp.sendRedirect(urlString);
             logger.error("redirectMbos url" + urlString);

+ 3 - 1
src/com/kingdee/eas/custom/sso/OAToSHR.java

@@ -204,8 +204,10 @@ public class OAToSHR extends HttpServlet {
                 redirectUrlStr.append(serverName).append(redirectUrl);
             }
         }
+        //todo
         //УÑéÁ÷³ÌÉúЧ״̬
-        String redirect = SsoUtil.checkFlowEffectiveStateForPc(redirectUrlStr.toString(), serverName);
+        //String redirect = SsoUtil.checkFlowEffectiveStateForPc(redirectUrlStr.toString(), serverName);
+        String redirect = SsoUtil.checkBillExistForPc(redirectUrlStr.toString(), serverName);
         String encode = URLEncoder.encode(redirect, "UTF-8");
         url.append(URLEncoder.encode(encode, "UTF-8"));
         logger.error("login: url" + url);

+ 116 - 3
src/com/kingdee/eas/custom/sso/SsoUtil.java

@@ -2,10 +2,17 @@ package com.kingdee.eas.custom.sso;
 
 import com.alibaba.fastjson.JSONObject;
 import com.kingdee.bos.BOSException;
+import com.kingdee.bos.BOSObjectFactory;
 import com.kingdee.bos.Context;
+import com.kingdee.bos.IBOSObject;
+import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
+import com.kingdee.bos.util.BOSObjectType;
+import com.kingdee.bos.util.BOSUuid;
+import com.kingdee.eas.common.EASBizException;
 import com.kingdee.eas.cp.eip.sso.ltpa.LtpaTokenManager;
 import com.kingdee.eas.cp.eip.sso.util.CASLoginConfigPropUtil;
 import com.kingdee.eas.cp.eip.sso.util.CloudParamUtil;
+import com.kingdee.eas.framework.ICoreBillBase;
 import com.kingdee.eas.util.app.DbUtil;
 import com.kingdee.jdbc.rowset.IRowSet;
 import com.kingdee.util.StringUtils;
@@ -15,6 +22,8 @@ import okhttp3.Response;
 import org.apache.log4j.Logger;
 
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
 import java.net.URLEncoder;
 import java.sql.SQLException;
 import java.util.HashMap;
@@ -67,6 +76,7 @@ public class SsoUtil {
         String dataCenter = CASLoginConfigPropUtil.getDataCenter();
         String locale = CASLoginConfigPropUtil.getLocale();
         if (!StringUtils.isEmpty(dataCenter) && !StringUtils.isEmpty(locale)) {
+            //todo
             Context ctx = CloudParamUtil.getContext(dataCenter, locale, "administrator");
             String sql = "SELECT count(1) total FROM T_WFR_Assign WHERE FASSIGNID = ?";
             IRowSet rs = DbUtil.executeQuery(ctx, sql, new Object[]{assignmentId});
@@ -97,9 +107,9 @@ public class SsoUtil {
      * @throws IOException
      */
     public static String checkFlowEffectiveStateForMbos(String redirect,
-                                                 String serverName,
-                                                 String getLoginIdPath,
-                                                 String token) throws SQLException, BOSException, IOException {
+                                                        String serverName,
+                                                        String getLoginIdPath,
+                                                        String token) throws SQLException, BOSException, IOException {
         if (StringUtils.isEmpty(getLoginIdPath)) {
             throw new RuntimeException("getLoginIdPath不能为空!");
         }
@@ -125,6 +135,109 @@ public class SsoUtil {
         }
     }
 
+
+    /**
+     * 校验单据是否存在
+     *
+     * @param redirect
+     * @param serverName
+     * @return
+     * @throws BOSException
+     * @throws SQLException
+     */
+    public static String checkBillExistForPc(String redirect,
+                                             String serverName)
+            throws BOSException, SQLException, EASBizException, UnsupportedEncodingException {
+        if (StringUtils.isEmpty(redirect)) {
+            throw new RuntimeException("重定向地址不能为空!");
+        }
+        if (StringUtils.isEmpty(serverName)) {
+            throw new RuntimeException("serverName不能为空!");
+        }
+        int index = redirect.indexOf("?");
+        Map<String, String> params = new HashMap<>();
+        if (index > 0) {
+            String redirectParams = redirect.substring(index + 1);
+            String[] arrary = redirectParams.split("&");
+            for (int i = 0; i < arrary.length; i++) {
+                String[] split = arrary[i].split("=");
+                if (split.length > 1) {
+                    params.put(split[0], split[1]);
+                }
+            }
+        } else {
+            return redirect;
+        }
+        //流程id
+        String assignmentId = params.get("AssignmentId");
+        if (StringUtils.isEmpty(assignmentId)) {
+            assignmentId = params.get("assignId");
+        }
+        if (StringUtils.isEmpty(assignmentId)) {
+            assignmentId = params.get("assignmentId");
+        }
+        String billID = params.get("billID");
+        if (StringUtils.isEmpty(assignmentId) || StringUtils.isEmpty(billID)) {
+            return redirect;
+        }
+        String dataCenter = CASLoginConfigPropUtil.getDataCenter();
+        String locale = CASLoginConfigPropUtil.getLocale();
+        if (!StringUtils.isEmpty(dataCenter) && !StringUtils.isEmpty(locale)) {
+            Context ctx = CloudParamUtil.getContext(dataCenter, locale, "administrator");
+            //todo
+            billID = URLDecoder.decode(billID, "UTF-8");
+            String bosType = BOSUuid.read(billID).getType().toString();
+            ICoreBillBase bosObject = (ICoreBillBase) BOSObjectFactory.createBOSObject(ctx, new BOSObjectType(bosType));
+            if (bosObject.exists(new ObjectUuidPK(billID))) {
+                return redirect;
+            } else {
+                return serverName + "/shr/flowErrorPage.jsp";
+            }
+        }
+        logger.error("获取用户信息报错,数据中心没找到!");
+        throw new RuntimeException("获取用户信息报错,数据中心没找到!");
+    }
+
+    /**
+     * 校验流程生效状态
+     *
+     * @param redirect
+     * @param serverName
+     * @return
+     * @throws BOSException
+     * @throws SQLException
+     */
+    public static String checkBillExistForMbos(String redirect,
+                                               String serverName,
+                                               String getLoginIdPath,
+                                               String token)
+            throws BOSException, SQLException, EASBizException, IOException {
+        if (StringUtils.isEmpty(getLoginIdPath)) {
+            throw new RuntimeException("getLoginIdPath不能为空!");
+        }
+        if (StringUtils.isEmpty(serverName)) {
+            throw new RuntimeException("serverName不能为空!");
+        }
+        if (StringUtils.isEmpty(token)) {
+            throw new RuntimeException("token不能为空!");
+        }
+        redirect = checkBillExistForPc(redirect, serverName);
+        if (redirect.contains("/shr/flowErrorPage.jsp")) {
+            String userNumber = SsoUtil.loginId2userId(getLoginIdPath, token);
+            String password = LtpaTokenManager.generate(userNumber, LtpaTokenManager.getDefaultLtpaConfig()).toString();
+            logger.error("login: password" + password);
+            StringBuilder url = new StringBuilder();
+            url.append(serverName).append("/shr/index2sso.jsp?username=").append(userNumber)
+                    .append("&password=").append(password).append("&redirectTo=");
+            String encode = URLEncoder.encode(redirect, "UTF-8");
+            url.append(URLEncoder.encode(encode, "UTF-8"));
+            return url.toString();
+        } else {
+            return redirect;
+        }
+    }
+
+
     /**
      * 获取用户信息
      *

+ 202 - 0
websrc/com/kingdee/eas/custom/flow/osf/BatchApproveServiceEx.java

@@ -0,0 +1,202 @@
+package com.kingdee.eas.custom.flow.osf;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.dao.IObjectPK;
+import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
+import com.kingdee.bos.util.BOSUuid;
+import com.kingdee.bos.workflow.ActivityInstInfo;
+import com.kingdee.bos.workflow.AssignmentInfo;
+import com.kingdee.bos.workflow.define.ManpowerActivityDef;
+import com.kingdee.bos.workflow.define.extended.ApproveActivityDef;
+import com.kingdee.bos.workflow.metas.WfAssignmentState;
+import com.kingdee.bos.workflow.service.ormrpc.EnactmentServiceFactory;
+import com.kingdee.bos.workflow.service.ormrpc.IEnactmentService;
+import com.kingdee.eas.base.message.AssignReadFactory;
+import com.kingdee.eas.base.message.AssignReadInfo;
+import com.kingdee.eas.base.message.IAssignRead;
+import com.kingdee.eas.base.message.URLInfo;
+import com.kingdee.eas.base.message.util.ProcessCenterUtil;
+import com.kingdee.eas.base.multiapprove.*;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.hr.service.app.service.BatchApproveService;
+import com.kingdee.eas.util.app.ContextUtil;
+import com.kingdee.shr.base.syssetting.ml.SHRWebResource;
+import com.kingdee.util.StringUtils;
+import com.kingdee.util.UuidException;
+import org.apache.log4j.Logger;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * @Description 批量审批接口扩展
+ * @Date 2024/12/19 10:37
+ * @Created by Heyuan
+ */
+public class BatchApproveServiceEx extends BatchApproveService {
+    private static Logger logger = Logger.getLogger(BatchApproveServiceEx.class);
+
+    @Override
+    public Object process(Context ctx, Map param)
+            throws EASBizException, BOSException {
+        List<Map<String, String>> results = new ArrayList();
+        String assignmentIds = (String) param.get("assignmentIds");
+        String opinion = (String) param.get("opinion");
+        StringBuilder errorMsg = new StringBuilder();
+        if (StringUtils.isEmpty(assignmentIds)) {
+            errorMsg.append("工作流任务id不能为空!").append(System.lineSeparator());
+        } else {
+            try {
+                assignmentIds = URLDecoder.decode(assignmentIds, "utf-8");
+            } catch (UnsupportedEncodingException e) {
+                e.printStackTrace();
+                errorMsg.append("工作流任务id数据错误, " + e.getMessage());
+            }
+        }
+        if (StringUtils.isEmpty(opinion)) {
+            errorMsg.append("审批意见不能为空!");
+        } else {
+            logger.error("opinion_>1 " + opinion);
+            try {
+                opinion = URLDecoder.decode(opinion, "utf-8");
+                logger.error("opinion_>2 " + opinion);
+            } catch (UnsupportedEncodingException e) {
+                e.printStackTrace();
+                errorMsg.append("审批意见数据错误, " + e.getMessage());
+            }
+        }
+        logger.error("assignmentIds>2 " + assignmentIds);
+        if (errorMsg.length() > 0) {
+            Map<String, String> result = new HashMap();
+            result.put("code", "0");
+            result.put("msg", errorMsg.toString());
+            results.add(result);
+        }
+        String[] assignmentIdArray = assignmentIds.split("[,,]");
+        for (int i = 0; i < assignmentIdArray.length; ++i) {
+            results.add(this.handle(ctx, assignmentIdArray[i], opinion));
+        }
+        return results;
+    }
+
+    private Map<String, String> handle(Context ctx,
+                                       String assignmentId,
+                                       String opinion) {
+        Map<String, String> result = new HashMap();
+        result.put("assignmentId", assignmentId);
+        try {
+            String bosType = BOSUuid.read(assignmentId).getType().toString();
+            if ("9623EB51".equals(bosType)) {
+                //任务阅读id
+                try {
+                    IAssignRead assignReadIns = AssignReadFactory.getLocalInstance(ctx);
+                    AssignReadInfo assignReadInfo = assignReadIns.getAssignReadInfo(new ObjectUuidPK(assignmentId));
+                    if (assignReadInfo != null) {
+                        assignmentId = assignReadInfo.getAssignID().toString();
+                    } else {
+                        throw new BOSException("任务阅读数据不存在: " + assignmentId);
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    throw new BOSException("获取任务阅读数据报错: " + assignmentId);
+                }
+            }
+            //校验流程状态
+            String errorMessage = this.verifyData(ctx, assignmentId);
+            if (!StringUtils.isEmpty(errorMessage)) {
+                throw new BOSException(errorMessage);
+            } else {
+                this.doApprove(ctx, assignmentId, opinion);
+                result.put("code", "1");
+                result.put("msg", "成功");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            result.put("code", "0");
+            String error = e.getMessage();
+            if (e instanceof IllegalArgumentException) {
+                result.put("msg", "流程id无效 " + assignmentId);
+            } else {
+                result.put("msg", error);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 校验数据
+     *
+     * @param ctx
+     * @param assignmentId
+     * @return
+     * @throws BOSException
+     */
+    private String verifyData(Context ctx,
+                              String assignmentId)
+            throws BOSException {
+        IEnactmentService service = EnactmentServiceFactory.createEnactService(ctx);
+        Map map = service.getActivityDefAndActivityInstInfo(assignmentId);
+        Object act = map.get("ACTIVITYDEF");
+        if (!(act instanceof ApproveActivityDef) && act instanceof ManpowerActivityDef) {
+            return SHRWebResource.getString("com.kingdee.shr.base.syssetting.CommonserviceResource", "labor_node_not_supported");
+        } else {
+            AssignmentInfo assignmentInfo = service.getAssignmentById(assignmentId);
+            ActivityInstInfo actInstInfo = null;
+            if (null != assignmentInfo) {
+                actInstInfo = service.getActivityInstByActInstId(assignmentInfo.getActInstId());
+            }
+
+            if (actInstInfo != null && (actInstInfo.getState().equalsIgnoreCase("open.not_running.suspended") || actInstInfo.getState().equalsIgnoreCase("open.not_running.blocked"))) {
+                return (new MultiApproveException(MultiApproveException.FLOW_NOT_RUNNING)).getMessage();
+            } else if (assignmentInfo == null) {
+                return (new MultiApproveException(MultiApproveException.ASSIGNMENTINFO_NULL)).getMessage();
+            } else if (assignmentInfo.getState().equals(WfAssignmentState.CANCELED)) {
+                return (new MultiApproveException(MultiApproveException.ASSIGNMENTSTATE_CANCELED)).getMessage();
+            } else if (assignmentInfo.getState().equals(WfAssignmentState.COMPLETED)) {
+                return (new MultiApproveException(MultiApproveException.ASSIGNMENTSTATE_COMPLETED)).getMessage();
+            } else if (assignmentInfo.getState().equals(WfAssignmentState.REJECTED)) {
+                return (new MultiApproveException(MultiApproveException.ASSIGNMENTSTATE_REJECTED)).getMessage();
+            } else {
+                return assignmentInfo.getState().equals(WfAssignmentState.PROCESSING) ? (new MultiApproveException(MultiApproveException.ASSIGNMENTSTATE_COMPLETED)).getMessage() : null;
+            }
+        }
+    }
+
+    /**
+     * 审批
+     *
+     * @param ctx
+     * @param assignmentId
+     * @param opinion
+     * @return
+     * @throws BOSException
+     * @throws EASBizException
+     */
+    private IObjectPK doApprove(Context ctx, String assignmentId, String opinion)
+            throws BOSException, EASBizException {
+        IMultiApprove multiApprove = MultiApproveFactory.getLocalInstance(ctx);
+        MultiApproveInfo mInfo = new MultiApproveInfo();
+        mInfo.setAssignment(assignmentId);
+        URLInfo info = ProcessCenterUtil.getUrlInfos(assignmentId, ctx);
+        String billID = info.getBillID();
+        mInfo.setBillId(BOSUuid.read(billID));
+        mInfo.setIsPass(ApproveResult.PASS);
+        mInfo.setHandlerOpinion(0);
+        mInfo.setOpinion(opinion);
+        mInfo.setCreator(ContextUtil.getCurrentUserInfo(ctx));
+        mInfo.setHandlerContent("同意");
+        mInfo.setExtendedProperty("isAddNew", "isAddNew");
+        mInfo.setExtendedProperty("assignmentID", assignmentId);
+        mInfo.setExtendedProperty("businuessObjectId", billID);
+        IObjectPK pk = multiApprove.submit(mInfo);
+        return pk;
+    }
+
+
+}