一個請假單流程的實現(struts2.1.8+spring2.5+hibernate3集成jbpm4.3)
轉自:http://abstractforever.javaeye.com/blog/608189
先說明這個只是一個例子而已,簡單的介紹了一些寫法,你真的理解了以后完全可以寫出比這個更好的代碼來。
網上隨便找了個請假的流程圖,在此先謝謝提供圖片的人:
使用jbpm工具畫出流程圖,中文好像是亂碼,所以改為英文:
leave.jpdl.xml內容:
- <?xml version="1.0" encoding="UTF-8"?>
- <process name="leave" xmlns="http://jbpm.org/4.3/jpdl">
- <start g="159,47,48,48" name="start1">
- <transition to="exclusive1"/>
- </start>
- <decision expr="#{job}" g="161,152,48,48" name="exclusive1">
- <transition g="42,179:43,-27" name="isChief" to="boosApprove"/>
- <transition g="316,175:-83,-23" name="isnotChief" to="chiefApprove"/>
- </decision>
- <state g="-3,220,92,52" name="boosApprove">
- <transition g="47,340:" to="sendEmail"/>
- </state>
- <state g="270,214,92,52" name="chiefApprove">
- <transition to="exclusive2"/>
- </state>
- <decision expr="#{day}" g="160,219,48,48" name="exclusive2">
- <transition g="-2,-20" name="gt10" to="boosApprove"/>
- <transition g="186,323:12,-47" name="le10" to="sendEmail"/>
- </decision>
- <end g="171,410,48,48" name="end"/>
- <state g="146,313,92,52" name="sendEmail">
- <transition to="end"/>
- </state>
- </process>
分析之后,有如下一些表:
用戶user_
角色role_(簡化到user_)
請假單leave_
假設有這么幾個用戶:
陳均 --普通員工
唐平 --級別最高的,BOOS,老板
胡杰 --級別比較高的,chief主管
張小 --普通員工
用戶測試數據:
- INSERT INTO `user_` VALUES ('9', '陳均', '普通員工');
- INSERT INTO `user_` VALUES ('10', '胡杰', '主管');
- INSERT INTO `user_` VALUES ('11', '唐平', '老板');
- INSERT INTO `user_` VALUES ('12', '張小', '普通員工');
現在集成jbpm4.3,hibernate3,spring2.5,struts2.1.8。
系統初步設計如圖:
1.因為jbpm里面帶有hibernate,所以創建web項目后,導入jbpm-4.3\lib下的所有包,導入jbpm-4.3\jbpm.jar,
把jbpm4.3\lib\下面得juel.jar,juel-engine.jar,juel-impl.jar放到tomcat的lib下面。導入spring2.5的jar,導入struts2.1.8所需jar包。以下jar包不是最簡,有些不是必須的。
spring2.5所需jar包清單:
aspectjrt.jar
aspectjweaver.jar
cglib-nodep-2.1_3.jar
common-annotations.jar
commons-logging.jar
log4j-1.2.15.jar
spring.jar
spring-webmvc-struts.jar
------------------------------------
struts2.1.8所需jar包清單:
commons-fileupload-1.2.1.jar
commons-io-1.3.2.jar
freemarker-2.3.15.jar
ognl-2.7.3.jar
struts2-core-2.1.8.1.jar
struts2-dojo-plugin-2.1.8.1.jar
struts2-spring-plugin-2.1.8.1.jar
xwork-core-2.1.6.jar
-----------------------------------
數據庫和數據源所需jar包:
c3p0-0.9.1.2.jar
mysql-connector-java-5.1.7-bin.jar
找到jbpm-4.3\install\src\cfg\jbpm\下的spring.jbpm.cfg.xml文件,放入項目的src處,改名為jbpm.cfg.xml.
在項目src下面創建applicationContext.xml配置文件,內容如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:p="http://www.springframework.org/schema/p"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
- <!-- 開啟注解配置 -->
- <context:annotation-config />
- <!-- 對指定的包進行組件掃描 -->
- <context:component-scan base-package="org.forever.leave" />
- <!-- 配置數據源,導入c3p0-0.9.1.2.jar,mysql-connector-java-5.1.7-bin.jar -->
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
- destroy-method="close">
- <property name="driverClass">
- <value>com.mysql.jdbc.Driver</value>
- </property>
- <property name="jdbcUrl">
- <value>jdbc:mysql://localhost:3306/jbpmdb</value>
- </property>
- <property name="user">
- <value>root</value>
- </property>
- <property name="password">
- <value>root</value>
- </property>
- </bean>
- <!-- 集成hibernate配置 -->
- <bean id="sessionFactory"
- class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
- <property name="dataSource" ref="dataSource" />
- <property name="hibernateProperties" ref="hibernateProperties" />
- <property name="mappingLocations">
- <list>
- <value>classpath*:org/forever/leave/entities/*.hbm.xml</value>
- <value>classpath:jbpm.repository.hbm.xml</value>
- <!-- 以下幾個jbpm.*.hbm.xml由jBPM自帶 -->
- <value>classpath:jbpm.execution.hbm.xml</value>
- <value>classpath:jbpm.history.hbm.xml</value>
- <value>classpath:jbpm.task.hbm.xml</value>
- <value>classpath:jbpm.identity.hbm.xml</value>
- </list>
- </property>
- </bean>
- <bean name="hibernateProperties"
- class="org.springframework.beans.factory.config.PropertiesFactoryBean">
- <property name="properties">
- <props>
- <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
- <prop key="hibernate.show_sql">true</prop>
- <prop key="hibernate.hbm2ddl.auto">update</prop>
- </props>
- </property>
- </bean>
- <!-- jbpm配置 -->
- <bean id="springHelper" class="org.jbpm.pvm.internal.processengine.SpringHelper" />
- <bean id="processEngine" factory-bean="springHelper"
- factory-method="createProcessEngine" />
- <!-- 模板配置自己寫的,不是必須的 -->
- <bean id="jbpmTemplate" class="org.forever.leave.jbpm.JbpmTemplate">
- <property name="processEngine" ref="processEngine"></property>
- </bean>
- <!-- 數據層用的模板工具,不是必須的 -->
- <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
- <property name="sessionFactory" ref="sessionFactory"></property>
- </bean>
- <!-- 事務配置,必須 -->
- <bean id="transactionManager"
- class="org.springframework.orm.hibernate3.HibernateTransactionManager">
- <property name="sessionFactory" ref="sessionFactory" />
- </bean>
- <!-- 切面配置 -->
- <aop:config>
- <aop:pointcut expression="execution(* org.forever.leave.biz..*.*(..))"
- id="transactionPointcut" />
- <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut" />
- </aop:config>
- <!-- 通知配置 -->
- <tx:advice id="txAdvice" transaction-manager="transactionManager">
- <tx:attributes>
- <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED" />
- <tx:method name="find*" read-only="true" propagation="NOT_SUPPORTED" />
- <tx:method name="*" propagation="REQUIRED" />
- </tx:attributes>
- </tx:advice>
- </beans>
添加 log4j.properties文件;
模板類JbpmTemplate:
- package org.forever.leave.jbpm;
- import java.util.List;
- import java.util.Map;
- import org.jbpm.api.Execution;
- import org.jbpm.api.ExecutionService;
- import org.jbpm.api.HistoryService;
- import org.jbpm.api.ManagementService;
- import org.jbpm.api.ProcessEngine;
- import org.jbpm.api.ProcessInstance;
- import org.jbpm.api.RepositoryService;
- import org.jbpm.api.TaskService;
- import org.jbpm.api.task.Task;
- /**
- * jbpm模板類(初步實現)
- *
- * @author Administrator
- *
- */
- public class JbpmTemplate {
- /**
- * 部署流程到數據庫
- *
- * @param resourceName
- * 資源文件名字 比如(org/forever/jbpm/jpdl/process.jpdl.xml)
- * @return 返回流程定義id(格式:key-version)
- */
- public String Deploy(String resourceName) {
- return repositoryService.createDeployment().addResourceFromClasspath(
- resourceName).deploy();
- }
- /**
- * 創建一個新的流程實例
- *
- * @param processDefinitionKey
- * (process.jpdl.xml中process標簽的key)
- * @param processInstanceKey
- * (用戶給的key,比如一個請假單的id)
- * @return 流程實例
- */
- public ProcessInstance addProcessInstance(String processDefinitionKey,
- String processInstanceKey) {
- return executionService.startProcessInstanceByKey(processDefinitionKey,
- processInstanceKey);
- }
- /**
- * 創建一個新的流程實例
- * @param processDefinitionKey(process.jpdl.xml中process標簽的key)
- * @param variables 該流程實例要用到的變量
- * @param processInstanceKey(用戶給定的業務key)
- * @return
- */
- public ProcessInstance addProcessInstance(
- String processDefinitionKey,
- Map<String, ?> variables,
- String processInstanceKey){
- return executionService.startProcessInstanceByKey(processDefinitionKey, variables, processInstanceKey);
- }
- /**
- * 提交任務
- * @param taskId 任務id
- */
- public void completeTask(String taskId){
- taskService.completeTask(taskId);
- }
- /**
- * 將任務流轉到指定名字的流程中去
- * @param taskId
- * @param outcome
- */
- public void completeTask(String taskId,String outcome){
- taskService.completeTask(taskId, outcome);
- }
- /**
- * 根據key獲取流程實例(這里我使用的uuid)
- *
- * @param key
- * (對應于數據庫表jbpm4_execution中的KEY_字段)
- * @return 返回查找到得流程實例,沒有返回null
- */
- public ProcessInstance getProcessInstance(String key) {
- return executionService.createProcessInstanceQuery()
- .processInstanceKey(key).uniqueResult();
- }
- /**
- * 根據executionId獲取指定的變量值
- * @param executionId
- * @param variableName
- * @return
- */
- public Object getVariableByexecutionId(String executionId,String variableName){
- return executionService.getVariable(executionId, variableName);
- }
- /**
- * 根據任務id獲取指定變量值
- * @param taskId
- * @param variableName
- * @return
- */
- public Object getVariableByTaskId(String taskId,String variableName){
- return taskService.getVariable(taskId, variableName);
- }
- /**
- * 獲取指定用戶名字的任務
- * @param userId
- * @return
- */
- public List<Task> findPersonalTasks(String userId){
- return taskService.findPersonalTasks(userId);
- }
- /**
- * 根據任務id獲取任務
- * @param taskId
- * @return
- */
- public Task getTask(String taskId) {
- return taskService.getTask(taskId);
- }
- /**
- * 根據流程實例id獲取
- * @param executionId
- * @return
- */
- public Execution findExecutionById(String executionId) {
- return executionService.findExecutionById(executionId);
- }
- /**
- * 徹底刪除文件的部署
- *
- * @param deploymentId流程定義id
- */
- public void deleteDeploymentCascade(String deploymentId) {
- repositoryService.deleteDeploymentCascade(deploymentId);
- }
- public JbpmTemplate() {
- }
- public JbpmTemplate(ProcessEngine processEngine) {
- this.processEngine = processEngine;
- repositoryService = processEngine.getRepositoryService();
- executionService = processEngine.getExecutionService();
- taskService = processEngine.getTaskService();
- historyService = processEngine.getHistoryService();
- managementService = processEngine.getManagementService();
- }
- private ProcessEngine processEngine;
- private RepositoryService repositoryService = null;
- private ExecutionService executionService = null;
- private TaskService taskService = null;
- private HistoryService historyService = null;
- private ManagementService managementService = null;
- public ProcessEngine getProcessEngine() {
- return processEngine;
- }
- public void setProcessEngine(ProcessEngine processEngine) {
- this.processEngine = processEngine;
- System.out.println(processEngine);
- repositoryService = processEngine.getRepositoryService();
- executionService = processEngine.getExecutionService();
- taskService = processEngine.getTaskService();
- historyService = processEngine.getHistoryService();
- managementService = processEngine.getManagementService();
- }
- //省略get和set方法
- }
- import java.util.UUID;
- import org.forever.leave.jbpm.JbpmTemplate;
- import org.jbpm.api.ProcessInstance;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class Test {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext(
- "applicationContext.xml");
- JbpmTemplate jbpmTemplate = (JbpmTemplate) context
- .getBean("jbpmTemplate");
- System.out.println(jbpmTemplate);
- jbpmTemplate.Deploy("org/forever/leave/jbpm/jpdl/leave.jpdl.xml");
- UUID uuid = UUID.randomUUID();
- }
- }
控制臺輸出沒有報錯說明jbpm和spring初步集成成功;
訪問http://localhost:8080/leave/user/queryList.action獲取到用戶列表信息,說明集成成功。
項目中需要修改mysql方言為org.hibernate.dialect.MySQLInnoDBDialect,事務service改為biz,剛發現的,呵呵
下一步進行業務的實現。
未完
因為朋友需要,所以對其進行了簡單的實現:
在實現中發現集成的時候,如果你用mysql數據庫,請設置你的方言為:org.hibernate.dialect.MySQLInnoDBDialect
先看一哈這個實現了簡單業務的一個圖,在此用的中文,也是網上找的,呵呵,我都變懶了哈:
對應xml文件:
- <?xml version="1.0" encoding="UTF-8"?>
- <process key="leave" name="leave" xmlns="http://jbpm.org/4.3/jpdl">
- <start g="201,14,48,48" name="開始">
- <transition g="-42,-10" name="請假" to="填寫請假單"/>
- </start>
- <task assignee="writerForm" g="178,87,92,52" name="填寫請假單">
- <transition g="-97,2" name="判斷是不是經理" to="是不是經理"/>
- </task>
- <decision expr="#{manager}" g="204,158,48,48" name="是不是經理">
- <transition g="-23,-11" name="否" to="經理審核"/>
- <transition g="14,-11" name="是" to="老板審批"/>
- </decision>
- <task assignee="#{username}" g="103,252,92,52" name="經理審核">
- <transition g="150,450:10,-21" name="經理批準" to="結束"/>
- <transition g="-22,-22" name="請假天數>5" to="老板審批"/>
- <transition g="-61,-1" name="經理不批準" to="終止"/>
- <transition g="149,114:-55,82" name="經理駁回" to="填寫請假單"/>
- </task>
- <!-- 這里只有一個老板,所以寫死了,如果有多個老板,寫法同上,業務就會改變 -->
- <task assignee="張杰" g="278,251,92,52" name="老板審批">
- <transition g="326,450:-58,-24" name="老板批準" to="結束"/>
- <transition g="7,0" name="老板不批準" to="終止"/>
- <transition g="323,114:13,61" name="老板駁回" to="填寫請假單"/>
- </task>
- <end g="219,429,48,48" name="結束" state="confirm"/>
- <end g="220,360,48,48" name="終止" state="dissent"/>
- </process>
寫了個經理審批的測試類過程:
- package org.forever.leave.biz.test;
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.UUID;
- import org.forever.leave.entities.Leave;
- import org.forever.leave.entities.User;
- import org.jbpm.api.ProcessInstance;
- import org.jbpm.api.task.Task;
- import org.junit.Test;
- //請假測試
- //運行順序
- //testDeploy()
- //testCresteLeave()
- //testStart()
- //testGetTask()
- //testGetLeave()
- public class LeaveTest extends BaseTest{
- //部署流程
- @Test
- public void testDeploy(){
- String resourceName ="org/forever/leave/jbpm/jpdl/leave.jpdl.xml";
- jbpmTemplate.Deploy(resourceName);
- }
- //新建請假單
- @Test
- public void testCresteLeave(){
- //現假設用戶陳均登陸了系統,然后進行請假
- String loginName = "cj";//登陸者
- String password = "cj";//登陸密碼
- User user = userDao.get(loginName,password);
- //status=新建,就是未提交的
- UUID uuid = UUID.randomUUID();
- Leave leave = new Leave(user, 3,new Date(),"新建", "生病了");
- leave.setLeaveId(uuid.toString());
- //保存到數據庫
- leaveDao.save(leave);
- }
- // 啟動流程實例,提交請假申請
- //注意(如果要對該測試類成功測試,首先確保存在juel-engine.jar,juel-impl.jar,juel.jar)
- //部署到tomcat里面的時候就把juel.jar,juel-engine.jar,juel-impl.jar放到tomcat的lib下面
- @Test
- public void testStart() {
- //進行業務流轉所需的變量
- String loginName = "cj";//登陸者
- String password = "cj";//登陸密碼
- User user = userDao.get(loginName,password);
- // 3.啟動流程實例,綁定業務key,key最好是唯一的
- List<?> list = leaveDao.findByUserLeave(user.getUserId());//該用戶可能有多次請假的記錄
- //假設用戶選擇的是index=0的那個請假單
- Leave leave = (Leave)list.get(0);
- String position = user.getPosition();//用戶的職位
- Map<String, Object> variables = new HashMap<String, Object>();//流程中要用到的變量信息
- variables.put("leaveId",leave.getLeaveId());//存放該實例的請假單
- if("員工".equals(position)){//如果是員工請假
- variables.put("manager", "否");
- variables.put("username","胡杰");//指定一個經理進行審批
- }else if("經理".equals(position)){//如果是經理請假
- variables.put("manager", "是");
- //只有一個boos,所以在xml中指定了,在此就不用指定了
- }
- //此時就獲取到了該請假單的id
- //通過該leaveId來綁定一個流程實例
- ProcessInstance processInstance = jbpmTemplate.addProcessInstance("leave",variables, leave.getLeaveId());
- //該表單到時候是在web頁面進行申請時填寫好的
- System.out.println("請假單已填寫:" + processInstance.isActive("填寫請假單"));
- String taskId = jbpmTemplate.findPersonalTasks("writerForm").get(0).getId();
- //讓任務向下流轉,提交任務
- jbpmTemplate.completeTask(taskId);
- }
- //獲取任務集合
- @Test
- public void testGetTask(){
- //經理登陸系統,獲取審批任務
- String username = "胡杰";
- List<Leave> leaves = new ArrayList<Leave>();//該經理可能對多個請假單審批,該集合提供給頁面使用的
- List<Task> list = jbpmTemplate.findPersonalTasks(username);
- if(list.size()==0){
- System.out.println(username + "沒有任務.........");
- }
- else{
- for (Task task : list) {
- System.out.println("任務名字:" + task.getName());
- System.out.println("任務參與者:" + task.getAssignee());
- String taskId = task.getId();
- String leaveId = (String) jbpmTemplate.getVariableByTaskId(taskId, "leaveId");
- Leave leave = leaveDao.findbyIdLeave(leaveId);
- leave.setTaskId(taskId);
- leaves.add(leave);
- }
- }
- //頁面顯示,并全部通過審批
- for (Leave leave : leaves) {
- System.out.println(leave);
- //批準流程
- ProcessInstance processInstance = jbpmTemplate.getProcessInstance(leave.getLeaveId());
- String taskId = leave.getTaskId();
- int day = leave.getDay();//請假天數
- if(day>5 && true){//如果大于5天,并且經理批準,也要提交給boos審核
- jbpmTemplate.completeTask(taskId, "請假天數>5");
- }else{//直接通過,既讓任務流轉到結束
- jbpmTemplate.completeTask(taskId,"經理批準");
- }
- System.out.println("審批結果:" + processInstance.getState());
- leave.setStatus("通過");
- leaveDao.update(leave);//更新結果
- }
- }
- //獲取指定用戶的請假單集合
- @Test
- public void testGetLeave(){
- //進行業務流轉所需的變量
- String loginName = "cj";//登陸者
- String password = "cj";//登陸密碼
- User user = userDao.get(loginName,password);
- //頁面顯示用
- List<?> list = leaveDao.findByUserLeave(user.getUserId());
- for (Object object : list) {
- System.out.println(object);
- //是否已經申請
- //已經提交的請假單不能進行刪除操作(所以慎重,呵呵)
- //新建狀態的請假單可以進行刪除操作
- }
- }
- }
web版的我截幾個效果圖,具體過程你們下載來感受吧:
login.jsp登陸頁面http://localhost:90/leave/login.jsp:第一次需要部署一哈
普通員工登陸用戶名和密碼為cj:
經理用戶名和密碼為hj,登陸后如圖:
老板的用戶名和密碼zxp,進去后如圖:
項目里面帶有數據庫腳本。jar自己加哈,有什么問題,歡迎交流
項目里面帶有數據庫腳本。jar自己加哈,有什么問題,歡迎交流
</p><ul style="display: none;"><li><a href="/misc/goto?guid=5033701441438621600" target="_blank" target="_blank"><img src="http://dl.javaeye.com/upload/attachment/212036/d8afd312-a483-34bd-9ea4-3fed64569630-thumb.gif" class="magplus" title="點擊查看原始大小圖片"></a></li><li>大小: 25 KB</li></ul>
<ul style="display: none;"><li><a href="/misc/goto?guid=5033701441542109889" target="_blank" target="_blank"><img src="http://dl.javaeye.com/upload/attachment/212373/e281c5f6-5e02-362e-8f8a-5118e50404cc-thumb.png" class="magplus" title="點擊查看原始大小圖片"></a></li><li>大小: 14.3 KB</li></ul>
<ul style="display: none;"><li><a href="/misc/goto?guid=5033701441637252122" target="_blank" target="_blank"><img src="http://dl.javaeye.com/upload/attachment/212589/fd4de4c5-eead-33e8-aba4-3501c5e67549-thumb.jpg" class="magplus" title="點擊查看原始大小圖片"></a></li><li>大小: 42.1 KB</li></ul>
<ul><li><a href="/misc/goto?guid=5033701441727972635" target="_blank" target="_blank">leave_集成完成_.rar</a> (51.8 KB)</li></ul>
<ul style="display: none;"><li><a href="/misc/goto?guid=5033701441833385302" target="_blank" target="_blank"><img src="http://dl.javaeye.com/upload/attachment/239719/a5b67170-ebb6-3af8-b112-73f6eb0b9919-thumb.png" class="magplus" title="點擊查看原始大小圖片"></a></li><li>大小: 19.2 KB</li></ul>
<ul style="display: none;"><li><a href="/misc/goto?guid=5033701441934829249" target="_blank" target="_blank"><img src="http://dl.javaeye.com/upload/attachment/239733/ae590370-485f-34a2-9526-7a31569b9cd0-thumb.jpg" class="magplus" title="點擊查看原始大小圖片"></a></li><li>大小: 8.6 KB</li></ul>
<ul style="display: none;"><li><a href="/misc/goto?guid=5033701442024371832" target="_blank" target="_blank"><img src="http://dl.javaeye.com/upload/attachment/239735/b1e7f62e-bf88-3429-8d8a-e2f18c7059eb-thumb.jpg" class="magplus" title="點擊查看原始大小圖片"></a></li><li>大小: 45.9 KB</li></ul>
<ul style="display: none;"><li><a href="/misc/goto?guid=5033701442130348810" target="_blank" target="_blank"><img src="http://dl.javaeye.com/upload/attachment/239741/f041faae-6eee-35d6-9b54-e7e1d488c6fd-thumb.jpg" class="magplus" title="點擊查看原始大小圖片"></a></li><li>大小: 41 KB</li></ul>
<ul style="display: none;"><li><a href="/misc/goto?guid=5033701442235783922" target="_blank" target="_blank"><img src="http://dl.javaeye.com/upload/attachment/239743/9362b0fa-b1e8-3deb-b506-d6ddf0dca660-thumb.jpg" class="magplus" title="點擊查看原始大小圖片"></a></li><li>大小: 14.9 KB</li></ul>
<ul><li><a href="/misc/goto?guid=5033701442335083321" target="_blank" target="_blank">leave_業務實現版_20100425.rar</a> (126.5 KB)</li></ul>
</div>