Przeglądaj źródła

启动流程支持草稿功能

fancy 5 lat temu
rodzic
commit
7976b27fbe
13 zmienionych plików z 267 dodań i 83 usunięć
  1. 2 2
      o2android/app/assets/server.json
  2. 4 0
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/process/StartProcessStepOneContract.kt
  3. 26 6
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/process/StartProcessStepOneFragment.kt
  4. 29 0
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/process/StartProcessStepOnePresenter.kt
  5. 4 0
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/process/StartProcessStepTwoContract.kt
  6. 36 62
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/process/StartProcessStepTwoFragment.kt
  7. 34 5
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/process/StartProcessStepTwoPresenter.kt
  8. 38 8
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/webview/TaskWebViewActivity.kt
  9. 2 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/O2.kt
  10. 18 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/APIAddressHelper.kt
  11. 13 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/ProcessAssembleSurfaceService.kt
  12. 51 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/o2/ProcessDraftWorkData.kt
  13. 10 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/o2/ProcessInfoData.java

+ 2 - 2
o2android/app/assets/server.json

@@ -1,7 +1,7 @@
 {
   "id" : "o2CenterServer",
-  "name" : "qywx",
-  "centerHost" : "qywx.o2oa.net",
+  "name" : "develop",
+  "centerHost" : "dev.o2oa.net",
   "centerContext" : "/x_program_center",
   "centerPort" : 20030,
   "httpProtocol" : "http"

+ 4 - 0
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/process/StartProcessStepOneContract.kt

@@ -4,6 +4,7 @@ import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.base.BasePresenter
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.base.BaseView
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.identity.ProcessWOIdentityJson
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ApplicationData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ProcessDraftWorkData
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ProcessInfoData
 
 
@@ -17,6 +18,8 @@ object StartProcessStepOneContract {
         fun loadCurrentPersonIdentityFail()
         fun startProcessSuccess(workId:String)
         fun startProcessFail(message:String)
+        fun startDraftSuccess(work: ProcessDraftWorkData)
+        fun startDraftFail(message:String)
     }
 
     interface Presenter : BasePresenter<View> {
@@ -24,5 +27,6 @@ object StartProcessStepOneContract {
         fun loadProcessListByAppId(appId:String)
         fun loadCurrentPersonIdentityWithProcess(processId: String)
         fun startProcess(identity: String, processId: String)
+        fun startDraft(identity: String, processId: String)
     }
 }

+ 26 - 6
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/process/StartProcessStepOneFragment.kt

@@ -6,6 +6,7 @@ import android.os.Bundle
 import android.support.v7.widget.LinearLayoutManager
 import android.widget.LinearLayout
 import kotlinx.android.synthetic.main.fragment_start_process_step_one.*
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2CustomStyle
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.R
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.base.BaseMVPFragment
@@ -14,9 +15,11 @@ import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.adapter.CommonRecycl
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.adapter.CommonRecyclerViewHolder
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.identity.ProcessWOIdentityJson
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ApplicationData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ProcessDraftWorkData
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ProcessInfoData
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.XToast
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.go
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.goThenKill
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.gone
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.visible
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.widgets.CircleImageView
@@ -115,7 +118,12 @@ class StartProcessStepOneFragment : BaseMVPFragment<StartProcessStepOneContract.
     override fun loadCurrentPersonIdentity(list: List<ProcessWOIdentityJson>) {
         if (list.isNotEmpty() ) {
             if (list.size == 1) {
-                startProcess(list[0].distinguishedName)
+                //是否走草稿
+                if (clickProcess != null && clickProcess?.defaultStartMode == O2.O2_Process_start_mode_draft) {
+                    startDraft(list[0].distinguishedName)
+                }else {
+                    startProcess(list[0].distinguishedName)
+                }
             }else {
                 goToStepTwo()
             }
@@ -132,10 +140,7 @@ class StartProcessStepOneFragment : BaseMVPFragment<StartProcessStepOneContract.
 
     override fun startProcessSuccess(workId: String) {
         hideLoadingDialog()
-        val bundle = Bundle()
-        bundle.putString(TaskWebViewActivity.WORK_WEB_VIEW_WORK, workId)
-        bundle.putString(TaskWebViewActivity.WORK_WEB_VIEW_TITLE, "拟稿")
-        (activity as StartProcessActivity).go<TaskWebViewActivity>(bundle)
+        (activity as StartProcessActivity).go<TaskWebViewActivity>(TaskWebViewActivity.start(workId, "", "拟稿"))
         (activity as StartProcessActivity).finish()
     }
 
@@ -144,11 +149,26 @@ class StartProcessStepOneFragment : BaseMVPFragment<StartProcessStepOneContract.
         XToast.toastShort(activity, message)
     }
 
+    override fun startDraftSuccess(work: ProcessDraftWorkData) {
+        hideLoadingDialog()
+        (activity as StartProcessActivity).goThenKill<TaskWebViewActivity>(TaskWebViewActivity.startDraft(work))
+    }
+
+    override fun startDraftFail(message: String) {
+        hideLoadingDialog()
+        XToast.toastShort(activity, message)
+    }
+
     private fun startProcess(identity: String) {
         //启动流程
         mPresenter.startProcess(identity, clickProcess!!.id)
     }
 
+    private fun startDraft(identity: String) {
+        //启动草稿
+        mPresenter.startDraft(identity, clickProcess!!.id)
+    }
+
     private fun onProcessItemClick(processInfoData: ProcessInfoData) {
         clickProcess = processInfoData
         showLoadingDialog()
@@ -158,7 +178,7 @@ class StartProcessStepOneFragment : BaseMVPFragment<StartProcessStepOneContract.
     private fun goToStepTwo() {
         hideLoadingDialog()
         if (clickProcess != null) {
-            val stepTwo = StartProcessStepTwoFragment.newInstance(clickProcess!!.id, clickProcess!!.name)
+            val stepTwo = StartProcessStepTwoFragment.newInstance(clickProcess!!.id, clickProcess!!.name, clickProcess?.defaultStartMode ?: "")
             (activity as StartProcessActivity).addFragment(stepTwo)
         }
     }

+ 29 - 0
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/process/StartProcessStepOnePresenter.kt

@@ -10,6 +10,7 @@ import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ProcessInfoData
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ProcessStartBo
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ProcessWorkData
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.XLog
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.o2Subscribe
 import rx.android.schedulers.AndroidSchedulers
 import rx.schedulers.Schedulers
 
@@ -72,4 +73,32 @@ class StartProcessStepOnePresenter : BasePresenterImpl<StartProcessStepOneContra
                     }))
         }
     }
+
+    override fun startDraft(identity: String, processId: String) {
+        if (TextUtils.isEmpty(identity) || TextUtils.isEmpty(processId)) {
+            mView?.startProcessFail("传入参数为空,无法启动流程, identity:$identity,processId:$processId")
+            return
+        }
+        val body = ProcessStartBo()
+        body.title = ""
+        body.identity = identity
+        getProcessAssembleSurfaceServiceAPI(mView?.getContext())?.let { service->
+            service.startDraft(processId, body)
+                    .subscribeOn(Schedulers.io())
+                    .observeOn(AndroidSchedulers.mainThread())
+                    .o2Subscribe {
+                        onNext {
+                            if (it.data != null) {
+                                mView?.startDraftSuccess(it.data.work)
+                            }else {
+                                mView?.startDraftFail("打开草稿异常!")
+                            }
+                        }
+                        onError { e, _ ->
+                            XLog.error("", e)
+                            mView?.startDraftFail(e?.message ?: "")
+                        }
+                    }
+        }
+    }
 }

+ 4 - 0
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/process/StartProcessStepTwoContract.kt

@@ -3,6 +3,7 @@ package net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.o2.process
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.base.BasePresenter
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.base.BaseView
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.identity.ProcessWOIdentityJson
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ProcessDraftWorkData
 
 
 object StartProcessStepTwoContract {
@@ -11,11 +12,14 @@ object StartProcessStepTwoContract {
         fun loadCurrentPersonIdentityFail()
         fun startProcessSuccess(workId:String)
         fun startProcessFail(message:String)
+        fun startDraftSuccess(work: ProcessDraftWorkData)
+        fun startDraftFail(message:String)
 
     }
 
     interface Presenter : BasePresenter<View> {
         fun loadCurrentPersonIdentityWithProcess(processId: String)
         fun startProcess(title:String, identity:String, processId:String)
+        fun startDraft(title:String, identity: String, processId: String)
     }
 }

+ 36 - 62
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/process/StartProcessStepTwoFragment.kt

@@ -1,24 +1,20 @@
 package net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.o2.process
 
-import android.graphics.Rect
 import android.os.Bundle
 import android.text.TextUtils
-import android.view.View
-import android.view.ViewTreeObserver
-import android.widget.LinearLayout
 import android.widget.RadioButton
 import android.widget.RadioGroup
 import kotlinx.android.synthetic.main.fragment_start_process_step_two.*
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.DateHelper
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.R
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.base.BaseMVPFragment
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.o2.webview.TaskWebViewActivity
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.identity.ProcessWOIdentityJson
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ProcessDraftWorkData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.DateHelper
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.XLog
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.XToast
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.go
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.gone
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.visible
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.goThenKill
 import org.jetbrains.anko.dip
 
 
@@ -29,76 +25,48 @@ class StartProcessStepTwoFragment : BaseMVPFragment<StartProcessStepTwoContract.
     override fun layoutResId(): Int = R.layout.fragment_start_process_step_two
 
     companion object {
-        val PROCESS_ID_KEY = "processId"
-        val PROCESS_NAME_KEY = "processName"
-        fun newInstance(processId:String, processName:String): StartProcessStepTwoFragment {
+        const val PROCESS_ID_KEY = "processId"
+        const val PROCESS_NAME_KEY = "processName"
+        const val PROCESS_START_MODE_KEY = "startMode"
+        fun newInstance(processId:String, processName:String, defaultStartMode: String): StartProcessStepTwoFragment {
             val stepTwo = StartProcessStepTwoFragment()
             val bundle = Bundle()
             bundle.putString(PROCESS_ID_KEY, processId)
             bundle.putString(PROCESS_NAME_KEY, processName)
+            bundle.putString(PROCESS_START_MODE_KEY, defaultStartMode)
             stepTwo.arguments = bundle
             return stepTwo
         }
     }
-    val identityList = ArrayList<ProcessWOIdentityJson>()
-    var processId = ""
-    var processName = ""
-    var identity = ""
-//    var globalLayoutListener: ViewTreeObserver.OnGlobalLayoutListener? = null
+    private val identityList = ArrayList<ProcessWOIdentityJson>()
+    private var processId = ""
+    private var processName = ""
+    private var processStartMode = ""
+    private var identity = ""
     override fun initUI() {
         val startString = getString(R.string.title_activity_start_process_step_two)
         (activity as StartProcessActivity).setToolBarTitle(startString)
         processId = arguments?.getString(PROCESS_ID_KEY) ?: ""
         processName = arguments?.getString(PROCESS_NAME_KEY) ?: ""
+        processStartMode = arguments?.getString(PROCESS_START_MODE_KEY) ?: ""
         tv_start_process_step_two_process_title.text = "$startString-$processName"
         tv_start_process_step_two_time.text = DateHelper.nowByFormate("yyyy-MM-dd HH:mm")
-        btn_start_process_step_two_positive.setOnClickListener { startProcess() }
+        btn_start_process_step_two_positive.setOnClickListener {
+            if (processStartMode == O2.O2_Process_start_mode_draft){
+                startDraft()
+            }else {
+                startProcess()
+            }
+        }
         btn_start_process_step_two_cancel.setOnClickListener { (activity as StartProcessActivity).finish() }
-//        edit_start_process_step_two_title.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
-//            override fun onGlobalLayout() {
-//                globalLayoutListener = this
-//                val screenHeight = activity.window.decorView.rootView.height
-//                val screenWidth = activity.window.decorView.rootView.width
-//                val rect = Rect()
-//                activity.window.decorView.getWindowVisibleDisplayFrame(rect)
-//                val height = screenHeight - (rect.bottom -rect.top)
-//                if (height > screenHeight/3) {
-//                    emptySpaceView(true, screenWidth, height)
-//                }else {
-//                    emptySpaceView(false)
-//                }
-//            }
-//        })
-
         mPresenter.loadCurrentPersonIdentityWithProcess(processId)
     }
 
     override fun onDestroyView() {
-//        if (globalLayoutListener!=null) {
-//            edit_start_process_step_two_title.viewTreeObserver.removeOnGlobalLayoutListener(globalLayoutListener)
-//        }
         super.onDestroyView()
         XLog.debug("StartProcessStepTwoFragment onDestroyView...............")
     }
 
-    var emptyView: View ? = null
-
-    private fun emptySpaceView(isShow:Boolean, width:Int=-1, height:Int=-1){
-        XLog.debug("emptySpaceView $isShow, $width, $height")
-        if (isShow) {
-            if (emptyView ==null) {
-                emptyView = View(activity)
-                val param = LinearLayout.LayoutParams(width, height)
-                linear_start_process_step_two_content.addView(emptyView, param)
-            }
-            emptyView?.visible()
-            scroll_start_process_step_two.postDelayed({
-                scroll_start_process_step_two.fullScroll(View.FOCUS_DOWN)
-            }, 200)
-        }else {
-            emptyView?.gone()
-        }
-    }
 
     override fun loadCurrentPersonIdentity(list: List<ProcessWOIdentityJson>) {
         radio_group_process_step_two_department.removeAllViews()
@@ -137,8 +105,7 @@ class StartProcessStepTwoFragment : BaseMVPFragment<StartProcessStepTwoContract.
         val bundle = Bundle()
         bundle.putString(TaskWebViewActivity.WORK_WEB_VIEW_WORK, workId)
         bundle.putString(TaskWebViewActivity.WORK_WEB_VIEW_TITLE, "拟稿")
-        (activity as StartProcessActivity).go<TaskWebViewActivity>(bundle)
-        (activity as StartProcessActivity).finish()
+        (activity as StartProcessActivity).goThenKill<TaskWebViewActivity>(bundle)
     }
 
     override fun startProcessFail(message:String) {
@@ -146,17 +113,24 @@ class StartProcessStepTwoFragment : BaseMVPFragment<StartProcessStepTwoContract.
         hideLoadingDialog()
     }
 
+    override fun startDraftSuccess(work: ProcessDraftWorkData) {
+        hideLoadingDialog()
+        (activity as StartProcessActivity).goThenKill<TaskWebViewActivity>(TaskWebViewActivity.startDraft(work))
+    }
 
+    override fun startDraftFail(message: String) {
+        hideLoadingDialog()
+        XToast.toastShort(activity, message)
+    }
 
     private fun startProcess() {
-//        var title = edit_start_process_step_two_title.text.toString()
-//        if (TextUtils.isEmpty(title)) {
-////            XToast.toastShort(activity, "请输入文件标题")
-////            return
-//            title = "无标题"
-//        }
         showLoadingDialog()
         mPresenter.startProcess("", identity, processId)
     }
 
+    private fun startDraft() {
+        showLoadingDialog()
+        mPresenter.startDraft("", identity, processId)
+    }
+
 }

+ 34 - 5
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/process/StartProcessStepTwoPresenter.kt

@@ -8,6 +8,7 @@ import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.identity.ProcessW
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ProcessStartBo
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ProcessWorkData
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.XLog
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.o2Subscribe
 import rx.android.schedulers.AndroidSchedulers
 import rx.schedulers.Schedulers
 
@@ -18,10 +19,10 @@ class StartProcessStepTwoPresenter : BasePresenterImpl<StartProcessStepTwoContra
             service.availableIdentityWithProcess(processId)
                     .subscribeOn(Schedulers.io())
                     .observeOn(AndroidSchedulers.mainThread())
-                    .subscribe(ResponseHandler<List<ProcessWOIdentityJson>>({ list ->
+                    .subscribe(ResponseHandler<List<ProcessWOIdentityJson>> { list ->
                         XLog.debug("identities: $list")
                         mView?.loadCurrentPersonIdentity(list)
-                    }),
+                    },
                             ExceptionHandler(mView?.getContext(), { e -> mView?.loadCurrentPersonIdentityFail() }))
         }
     }
@@ -38,16 +39,44 @@ class StartProcessStepTwoPresenter : BasePresenterImpl<StartProcessStepTwoContra
                 service.startProcess(processId, body)
                     .subscribeOn(Schedulers.io())
                     .observeOn(AndroidSchedulers.mainThread())
-                    .subscribe(ResponseHandler<List<ProcessWorkData>>({ list ->
+                    .subscribe(ResponseHandler<List<ProcessWorkData>> { list ->
                         try {
                             mView?.startProcessSuccess(list[0].taskList[0].work)
                         } catch (e: Exception) {
                             XLog.error("", e)
                             mView?.startProcessFail("返回数据异常!${e.message}")
                         }
-                    }), ExceptionHandler(mView?.getContext(), { e ->
+                    }, ExceptionHandler(mView?.getContext()) { e ->
                         mView?.startProcessFail(e.message ?: "")
-                    }))
+                    })
+        }
+    }
+
+    override fun startDraft(title: String, identity: String, processId: String) {
+        if (TextUtils.isEmpty(identity) || TextUtils.isEmpty(processId)) {
+            mView?.startProcessFail("传入参数为空,无法启动流程, identity:$identity,processId:$processId")
+            return
+        }
+        val body = ProcessStartBo()
+        body.title = ""
+        body.identity = identity
+        getProcessAssembleSurfaceServiceAPI(mView?.getContext())?.let { service->
+            service.startDraft(processId, body)
+                    .subscribeOn(Schedulers.io())
+                    .observeOn(AndroidSchedulers.mainThread())
+                    .o2Subscribe {
+                        onNext {
+                            if (it.data != null) {
+                                mView?.startDraftSuccess(it.data.work)
+                            }else {
+                                mView?.startDraftFail("打开草稿异常!")
+                            }
+                        }
+                        onError { e, _ ->
+                            XLog.error("", e)
+                            mView?.startDraftFail(e?.message ?: "")
+                        }
+                    }
         }
     }
 }

+ 38 - 8
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/webview/TaskWebViewActivity.kt

@@ -26,6 +26,7 @@ import com.google.gson.reflect.TypeToken
 import kotlinx.android.synthetic.main.activity_work_web_view.*
 import net.muliba.fancyfilepickerlibrary.FilePicker
 import net.muliba.fancyfilepickerlibrary.PicturePicker
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2App
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2SDKManager
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.R
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.base.BaseMVPActivity
@@ -33,6 +34,7 @@ import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.tbs.FileReaderActivity
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.APIAddressHelper
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.WorkNewActionItem
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.WorkControl
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ProcessDraftWorkData
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.ReadData
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.WorkOpinionData
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.vo.O2UploadImageData
@@ -52,6 +54,7 @@ import rx.Scheduler
 import rx.android.schedulers.AndroidSchedulers
 import rx.schedulers.Schedulers
 import java.io.File
+import java.net.URLEncoder
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
 
@@ -66,6 +69,7 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
         val WORK_WEB_VIEW_TITLE = "xbpm.work.web.view.title"
         val WORK_WEB_VIEW_WORK = "xbpm.work.web.view.work"
         val WORK_WEB_VIEW_WORK_COMPLETED = "xbpm.work.web.view.work.completed"
+        val WORK_WEB_VIEW_DRAFT = "xbpm.work.web.view.work.draft"
 
         fun start(work: String?, workCompleted: String?, title: String?):  Bundle {
             val bundle = Bundle()
@@ -74,6 +78,12 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
             bundle.putString(WORK_WEB_VIEW_WORK_COMPLETED, workCompleted)
             return bundle
         }
+
+        fun startDraft(draft: ProcessDraftWorkData?):  Bundle {
+            val bundle = Bundle()
+            bundle.putSerializable(WORK_WEB_VIEW_DRAFT, draft)
+            return bundle
+        }
     }
 
     private  val WORK_WEB_VIEW_UPLOAD_REQUEST_CODE = 1001
@@ -86,6 +96,7 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
     private  var workCompletedId = ""
     private  var isWorkCompleted = false
     private  var url = ""
+    private var draft: ProcessDraftWorkData? = null
 
     private var control: WorkControl? = null
     private var read: ReadData? = null
@@ -110,15 +121,34 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
         title = intent.extras?.getString(WORK_WEB_VIEW_TITLE) ?: ""
         workId = intent.extras?.getString(WORK_WEB_VIEW_WORK) ?: ""
         workCompletedId = intent.extras?.getString(WORK_WEB_VIEW_WORK_COMPLETED) ?: ""
-
-        isWorkCompleted = !TextUtils.isEmpty(workCompletedId)
-
-        if (isWorkCompleted) {
-            url = APIAddressHelper.instance().getWorkCompletedUrl()
-            url = String.format(url, workCompletedId)
+        draft = if (intent.extras?.getSerializable(WORK_WEB_VIEW_DRAFT) != null){
+            intent.extras?.getSerializable(WORK_WEB_VIEW_DRAFT) as ProcessDraftWorkData
         } else {
-            url = APIAddressHelper.instance().getWorkUrlPre()
-            url = String.format(url, workId)
+            null
+        }
+
+        //草稿文档处理
+        if (draft != null) {
+            if (!TextUtils.isEmpty(draft!!.id)){
+                url = APIAddressHelper.instance().getProcessDraftWithIdUrl()
+                url = String.format(url, draft!!.id)
+            }else {
+                url = APIAddressHelper.instance().getProcessDraftUrl()
+                val json = O2SDKManager.instance().gson.toJson(draft)
+                XLog.debug("草稿对象:$json")
+                val enJson = URLEncoder.encode(json, "utf-8")
+                XLog.debug("草稿对象 encode:$enJson")
+                url = String.format(url, enJson)
+            }
+        }else {
+            isWorkCompleted = !TextUtils.isEmpty(workCompletedId)
+            if (isWorkCompleted) {
+                url = APIAddressHelper.instance().getWorkCompletedUrl()
+                url = String.format(url, workCompletedId)
+            } else {
+                url = APIAddressHelper.instance().getWorkUrlPre()
+                url = String.format(url, workId)
+            }
         }
         url += "&time=" + System.currentTimeMillis()
 

+ 2 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/O2.kt

@@ -13,6 +13,8 @@ object O2 {
     val O2_COLLECT_URL = "http://collect.o2oa.net:20080/o2_collect_assemble/"
     val O2_DOWNLOAD_URL = "https://sample.o2oa.net/app/download.html"
 
+    const val O2_Process_start_mode_draft = "draft"
+
     /**
      * 项目文件存储路径
      * 根目录

+ 18 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/APIAddressHelper.kt

@@ -92,6 +92,24 @@ class APIAddressHelper private constructor() {
         } ?: ""
     }
 
+    /**
+     * 流程草稿打开的url
+     */
+    fun getProcessDraftUrl(): String {
+        return webServerData?.let {
+            "$httpHead${webServerData?.host}:${webServerData?.port}/x_desktop/workmobilewithaction.html?draft=%s"
+        } ?: ""
+    }
+
+    /**
+     * 流程草稿打开的url
+     */
+    fun getProcessDraftWithIdUrl(): String {
+        return webServerData?.let {
+            "$httpHead${webServerData?.host}:${webServerData?.port}/x_desktop/workmobilewithaction.html?draftid=%s"
+        } ?: ""
+    }
+
     /**
      * 查看帖子的url
      * @param subjectId 帖子id

+ 13 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/ProcessAssembleSurfaceService.kt

@@ -244,6 +244,19 @@ interface ProcessAssembleSurfaceService {
     fun getTask(@Path("taskId") taskId: String): Observable<ApiResponse<TaskData>>
 
 
+
+    /**
+     * 启动草稿
+     * @param processId
+     * *
+     * @param body
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/draft/process/{processId}")
+    fun startDraft(@Path("processId") processId: String, @Body body: ProcessStartBo): Observable<ApiResponse<ProcessDraftData>>
+
     /**
      * 启动流程
      * @param processId

+ 51 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/o2/ProcessDraftWorkData.kt

@@ -0,0 +1,51 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2
+
+import java.io.Serializable
+
+
+/**
+ * Created by fancyLou on 2020-04-21.
+ * Copyright © 2020 O2. All rights reserved.
+ */
+
+/**
+ *  "work": {
+"id": "",
+"title": "流程开发测试-无标题",
+"creatorPerson": "楼国栋@louguodong@P",
+"creatorIdentity": "楼国栋@6fef54b9-e195-4609-b030-aa446a4164f3@I",
+"creatorUnit": "开发部@22@U",
+"application": "d18a3210-22f2-431c-af29-dbb4f6e8ae82",
+"applicationName": "流程开发",
+"applicationAlias": "",
+"process": "4be0e389-a69b-466d-a725-97f9a189d7ff",
+"processName": "流程开发测试",
+"processAlias": "",
+"workCreateType": "surface",
+"form": "7d0d8ac2-7c8c-4bcc-9e2f-6d436a7a39b5",
+"properties": {
+"manualForceTaskIdentityList": [],
+"manualEmpowerMap": {},
+"serviceValue": {}
+}
+}
+ */
+class ProcessDraftWorkData (
+    var id: String = "",
+    var title: String = "",
+    var creatorPerson: String = "",
+    var creatorIdentity: String = "",
+    var creatorUnit: String = "",
+    var application: String = "",
+    var applicationName: String = "",
+    var applicationAlias: String = "",
+    var process: String = "",
+    var processName: String = "",
+    var processAlias: String = "",
+    var workCreateType: String = "",
+    var form: String = ""
+): Serializable
+
+class ProcessDraftData(
+        var work: ProcessDraftWorkData = ProcessDraftWorkData()
+)

+ 10 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/o2/ProcessInfoData.java

@@ -10,6 +10,8 @@ public class ProcessInfoData {
     private String alias;
     private String description;
 
+    private String defaultStartMode;	//默认启动方式,draft,instance
+
     public String getId() {
         return id;
     }
@@ -41,4 +43,12 @@ public class ProcessInfoData {
     public void setDescription(String description) {
         this.description = description;
     }
+
+    public String getDefaultStartMode() {
+        return defaultStartMode;
+    }
+
+    public void setDefaultStartMode(String defaultStartMode) {
+        this.defaultStartMode = defaultStartMode;
+    }
 }