Просмотр исходного кода

一些问题修复,app内更新调整,文件模块调整等等

fancy 6 лет назад
Родитель
Сommit
2985eed23d
100 измененных файлов с 6193 добавлено и 704 удалено
  1. 2 2
      o2android/app/assets/server.json
  2. 9 9
      o2android/app/build.gradle
  3. BIN
      o2android/app/libs/o2_auth_sdk-release.aar
  4. 1 4
      o2android/app/src/main/AndroidManifest.xml
  5. 88 0
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/O2AppUpdateManager.kt
  6. 2 0
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/base/BasePresenter.kt
  7. 104 0
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/base/BasePresenterImpl.kt
  8. 1 0
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/cms/application/CMSApplicationActivity.kt
  9. 35 16
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/cms/application/CMSPublishDocumentActivity.kt
  10. 4 1
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/cms/application/CMSPublishDocumentContract.kt
  11. 32 2
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/cms/application/CMSPublishDocumentPresenter.kt
  12. 37 1
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/cms/view/CMSWebViewActivity.kt
  13. 16 38
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/about/AboutActivity.kt
  14. 4 0
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/bind/FirstStepFragment.kt
  15. 15 31
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/launch/LaunchActivity.kt
  16. 6 6
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/main/MainActivity.kt
  17. 29 29
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/main/SettingsFragment.kt
  18. 5 9
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/scanlogin/ScanLoginActivity.kt
  19. 7 2
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/security/AccountSecurityActivity.kt
  20. 0 1
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/webview/PortalWebViewActivity.kt
  21. 173 126
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/webview/TaskWebViewActivity.kt
  22. 1 0
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/webview/TaskWebViewPresenter.kt
  23. 13 2
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/webview/TaskWorkSubmitDialogFragment.kt
  24. 0 160
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/ApkUpdateCheck.java
  25. 2 1
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/CMSWorkControl.kt
  26. 10 0
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/O2AppUpdateBean.kt
  27. 7 0
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/O2AppUpdateBeanData.kt
  28. 14 0
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/utils/AndroidUtils.kt
  29. 0 124
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/utils/AppUpdateUtil.kt
  30. 0 99
      o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/utils/ZoneXBPMCrashHandler.java
  31. 2 0
      o2android/app/src/main/res/layout/activity_account_security.xml
  32. 24 0
      o2android/app/src/main/res/layout/activity_cms_web_view_document.xml
  33. 33 33
      o2android/app/src/main/res/layout/fragment_main_settings.xml
  34. 2 0
      o2android/app/src/main/res/values/strings.xml
  35. 2 2
      o2android/gradle.properties
  36. BIN
      o2android/gradle/wrapper/gradle-wrapper.jar
  37. 0 6
      o2android/gradle/wrapper/gradle-wrapper.properties
  38. 4 0
      o2android/o2_auth_sdk/.gitignore
  39. 86 0
      o2android/o2_auth_sdk/build.gradle
  40. 39 0
      o2android/o2_auth_sdk/proguard-rules.pro
  41. 2 0
      o2android/o2_auth_sdk/src/main/AndroidManifest.xml
  42. 151 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/O2.kt
  43. 162 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/O2CustomStyle.kt
  44. 595 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/O2SDKManager.kt
  45. 295 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/APIAddressHelper.kt
  46. 59 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/ExceptionHandler.kt
  47. 29 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/O2Interceptor.kt
  48. 15 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/ResponseHandler.kt
  49. 493 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/RetrofitClient.kt
  50. 38 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/ApiService.kt
  51. 165 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/AttendanceAssembleControlService.kt
  52. 149 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/BBSAssembleControlService.kt
  53. 137 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/CMSAssembleControlService.kt
  54. 123 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/CalendarAssembleControlService.kt
  55. 130 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/CloudFileControlService.kt
  56. 105 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/CollectService.kt
  57. 26 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/FaceppApiService.kt
  58. 179 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/FileAssembleControlService.kt
  59. 41 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/HotpicAssembleControlService.kt
  60. 29 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/JPushControlService.kt
  61. 209 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/MeetingAssembleControlService.kt
  62. 84 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/OrgAssembleAuthenticationService.kt
  63. 174 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/OrgAssembleExpressService.kt
  64. 48 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/OrgAssemblePersonalService.kt
  65. 96 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/OrganizationAssembleControlAlphaService.kt
  66. 17 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/OrganizationAssembleCustomService.kt
  67. 19 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/PgyUpdateApiService.kt
  68. 19 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/PortalAssembleSurfaceService.kt
  69. 344 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/ProcessAssembleSurfaceService.kt
  70. 18 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/QueryAssembleSurfaceService.kt
  71. 19 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/SkinDownLoadService.kt
  72. 23 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/api/service/Tuling123Service.kt
  73. 48 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/enums/APIDistributeTypeEnum.java
  74. 18 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/enums/LaunchState.kt
  75. 36 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/DownloadBean.java
  76. 28 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/DownloadProgressHandler.java
  77. 30 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/ProgressHandler.java
  78. 59 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/ProgressHelper.java
  79. 9 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/ProgressListener.java
  80. 59 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/ProgressResponseBody.java
  81. 10 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/exception/NoBindException.kt
  82. 8 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/exception/NoLoginException.kt
  83. 8 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/exception/O2ResponseException.kt
  84. 38 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/DepartmentItem.java
  85. 328 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/APIAssemblesData.java
  86. 55 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/APIDataBean.java
  87. 26 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/APIDistributeData.java
  88. 30 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/APILogData.kt
  89. 86 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/APIWebServerData.java
  90. 82 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/ApiErrorResponse.java
  91. 83 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/ApiResponse.java
  92. 16 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/IdData.java
  93. 6 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/JPushDeviceForm.kt
  94. 6 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/TestObject.kt
  95. 13 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/TulingPostData.kt
  96. 12 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/TulingResponse.kt
  97. 17 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/ValueData.java
  98. 31 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/ValueNumberData.java
  99. 14 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/WorkControl.kt
  100. 235 0
      o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/attendance/AttendanceJSON.kt

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

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

+ 9 - 9
o2android/app/build.gradle

@@ -12,7 +12,6 @@ ext {
     signingConfigStorePassword = ""
 
     jpushAppKey = ""
-    pgyAppId = ""
     baiduSpeechAppId = ""
     baiduSpeechSecret = ""
     baiduSpeechAppKey = ""
@@ -33,7 +32,6 @@ def loadProperties() {
 
     //release key
     project.jpushAppKey = properties.getProperty("JPUSH_APPKEY")
-    project.pgyAppId = properties.getProperty("PGY_APP_ID")
     project.baiduSpeechAppId = properties.getProperty("BAIDU_SPEECH_APPID")
     project.baiduSpeechSecret = properties.getProperty("BAIDU_SPEECH_SECRET")
     project.baiduSpeechAppKey = properties.getProperty("BAIDU_SPEECH_APPKEY")
@@ -107,13 +105,12 @@ android {
     buildTypes {
         debug {
             signingConfig signingConfigs.debug
-            buildConfigField "Boolean", "InnerServer", "false"
+            buildConfigField "Boolean", "InnerServer", "true"
             buildConfigField "Boolean", "LOG_ENABLE", "true"
             buildConfigField "Boolean", "LOG_FILE", "true"
             manifestPlaceholders = [JPUSH_PKGNAME      : defaultConfig.applicationId,
                                     JPUSH_APPKEY       : project.jpushAppKey,
                                     JM_IM_USER_PASSWORD: project.jpushIMPassword,
-                                    PGY_APP_ID         : project.pgyAppId,
                                     BAIDU_SPEECH_APPID : project.baiduSpeechAppId,
                                     BAIDU_SPEECH_SECRET: project.baiduSpeechSecret,
                                     BAIDU_SPEECH_APPKEY: project.baiduSpeechAppKey,
@@ -128,7 +125,6 @@ android {
             manifestPlaceholders = [JPUSH_PKGNAME      : defaultConfig.applicationId,
                                     JPUSH_APPKEY       : project.jpushAppKey,
                                     JM_IM_USER_PASSWORD: project.jpushIMPassword,
-                                    PGY_APP_ID         : project.pgyAppId,
                                     BAIDU_SPEECH_APPID : project.baiduSpeechAppId,
                                     BAIDU_SPEECH_SECRET: project.baiduSpeechSecret,
                                     BAIDU_SPEECH_APPKEY: project.baiduSpeechAppKey,
@@ -200,13 +196,13 @@ dependencies {
     implementation files('libs/BaiduLBS_Android.jar')
     implementation files('libs/bdasr_V3_20180320_9066860.jar')
     implementation files('libs/com.baidu.tts_2.3.1.20170808_e39ea89.jar')
-    implementation files('libs/pgyer_sdk_2.2.2.jar')
     implementation files('libs/zxing.jar')
     implementation files('libs/pinyin4j-2.5.0.jar')
     implementation files('libs/universal-image-loader-1.9.5.jar')
     implementation files('libs/tbs_sdk_thirdapp_v4.3.0.1072_43646_sharewithdownloadwithfile_withoutGame_obfs_20190429_175122.jar')
     implementation(name: 'material-calendarview-fancy-1.1', ext: 'aar')
-    implementation(name: 'o2_auth_sdk-release', ext: 'aar')
+//    implementation(name: 'o2_auth_sdk-release', ext: 'aar')
+    implementation project(path: ':o2_auth_sdk')
 
     implementation(name: 'flutterpack-release', ext: 'aar')
     implementation(name: 'shared_preferences-release', ext: 'aar')
@@ -251,7 +247,10 @@ dependencies {
 
     implementation 'com.tencent.bugly:crashreport:2.6.6'
 
-    //极光推送
+
+
+
+    //
     implementation 'cn.jiguang.sdk:jpush:3.1.2'
     implementation 'cn.jiguang.sdk:jmessage:2.5.0'
 
@@ -270,7 +269,7 @@ dependencies {
     //滚动选择器
     implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1'
 
-    //activity result
+    //链式方式获取Activity返回结果
     implementation 'com.github.lwugang:ActivityResult:59b23e3682'
 
     //google architecture component
@@ -299,6 +298,7 @@ dependencies {
     implementation 'com.google.code.gson:gson:2.8.5'
 
 
+
 }
 
 

BIN
o2android/app/libs/o2_auth_sdk-release.aar


+ 1 - 4
o2android/app/src/main/AndroidManifest.xml

@@ -427,10 +427,7 @@
         <meta-data
             android:name="JM_IM_USER_PASSWORD"
             android:value="${JM_IM_USER_PASSWORD}" /> <!-- ```````````````````meta```````````````````` -->
-        <!-- 蒲公英 appid -->
-        <meta-data
-            android:name="PGYER_APPID"
-            android:value="${PGY_APP_ID}" /> <!-- bugly -->
+        <!-- bugly -->
         <!-- 配置APP ID -->
         <meta-data
             android:name="BUGLY_APPID"

+ 88 - 0
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/O2AppUpdateManager.kt

@@ -0,0 +1,88 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM
+
+import android.app.Activity
+import android.text.TextUtils
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.O2AppUpdateBean
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.O2AppUpdateBeanData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.AndroidUtils
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.XLog
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.o2Subscribe
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import rx.Observable
+import rx.android.schedulers.AndroidSchedulers
+import rx.schedulers.Schedulers
+import java.lang.Exception
+
+
+class O2AppUpdateManager private constructor() {
+
+    companion object {
+        private var INSTANCE: O2AppUpdateManager? = null
+        fun instance(): O2AppUpdateManager {
+            if (INSTANCE == null) {
+                INSTANCE = O2AppUpdateManager()
+            }
+            return INSTANCE!!
+        }
+    }
+
+    //更新的json地址
+    private val o2AppVersionJsonUrl = "https://sample.o2oa.net/app/app.json"
+    private val client = OkHttpClient()
+
+
+
+    fun checkUpdate(activity: Activity, call: O2AppUpdateCallback) {
+        Observable.just(o2AppVersionJsonUrl).subscribeOn(Schedulers.io())
+                .map { url ->
+                    val request = Request.Builder().url(url).build()
+                    try {
+                        val response = client.newCall(request).execute()
+                        val json = response.body()?.string()
+                        XLog.debug("json: $json")
+                        if (json != null && !TextUtils.isEmpty(json)) {
+                            val data = O2SDKManager.instance().gson.fromJson(json, O2AppUpdateBeanData::class.java)
+                            if (data?.android != null) {
+                                data.android
+                            }else {
+                                throw Exception("Json解析出错,请检查版本更新的json格式!")
+                            }
+                        }else {
+                            throw Exception("没有获取到版本更新的json文件内容!")
+                        }
+                    }catch (e: Exception) {
+                        XLog.error("", e)
+                        throw e
+                    }
+                }.observeOn(AndroidSchedulers.mainThread())
+                .o2Subscribe {
+                    onNext {
+                        val vcode = AndroidUtils.getAppVersionCode(activity)
+                        try {
+                            XLog.debug("vcode: $vcode , build:${it?.buildNo}")
+                            if (it != null && it.buildNo.toInt() > vcode) {
+                                call.onUpdate(it)
+                            }else {
+                                call.onNoneUpdate("没有新版本!")
+                            }
+                        } catch (e: Exception) {
+                            call.onNoneUpdate(e.message ?: "")
+                        }
+                    }
+                    onError { e, _ ->
+                        XLog.error("", e)
+                        call.onNoneUpdate(e?.message ?: "")
+                    }
+                }
+    }
+
+
+
+
+}
+
+interface O2AppUpdateCallback {
+    fun onUpdate(version: O2AppUpdateBean)
+    fun onNoneUpdate(error: String)
+}

+ 2 - 0
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/base/BasePresenter.kt

@@ -8,4 +8,6 @@ package net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.base
 interface BasePresenter<in V : BaseView> {
     fun attachView(view: V)
     fun detachView()
+    fun jPushBindDevice(deviceToken: String)
+    fun jPushUnBindDevice(deviceToken: String)
 }

+ 104 - 0
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/base/BasePresenterImpl.kt

@@ -1,10 +1,17 @@
 package net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.base
 
 import android.content.Context
+import android.text.TextUtils
+import cn.jpush.android.api.JPushInterface
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.BuildConfig
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.RetrofitClient
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service.*
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.JPushDeviceForm
 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.o2Subscribe
+import rx.android.schedulers.AndroidSchedulers
+import rx.schedulers.Schedulers
 
 
 /**
@@ -62,6 +69,24 @@ open class BasePresenterImpl<V: BaseView> : BasePresenter<V> {
         }
     }
 
+    /**
+     * 查询服务
+     */
+    fun getQueryAssembleSurfaceServiceAPI(context: Context?): QueryAssembleSurfaceService? {
+        return try {
+            RetrofitClient.instance().queryAssembleSurfaceServiceAPI()
+        }catch (e: Exception) {
+            XLog.error("", e)
+            if (context!=null) {
+                XToast.toastLong(context, "查询模块异常,请联系管理员!!")
+            }
+            null
+        }
+    }
+
+
+
+
     /**
      * 认证服务
      */
@@ -152,6 +177,22 @@ open class BasePresenterImpl<V: BaseView> : BasePresenter<V> {
         }
     }
 
+    /**
+     * 新版云盘服务
+     */
+    fun getCloudFileControlService(context: Context?): CloudFileControlService? {
+        return try {
+            RetrofitClient.instance().cloudFileControlApi()
+        }catch (e:Exception){
+            XLog.error("", e)
+            if (context!=null){
+                XToast.toastLong(context, "云盘服务模块异常,请联系管理员!")
+            }
+            null
+        }
+    }
+
+
     /**
      * 会议管理服务
      */
@@ -257,6 +298,69 @@ open class BasePresenterImpl<V: BaseView> : BasePresenter<V> {
         }
     }
 
+
+    /**
+     * 极光消息管理
+     */
+    private fun getJPushControlService(): JPushControlService? {
+        return try {
+            RetrofitClient.instance().jPushControlService()
+        }catch (e:Exception) {
+            XLog.error("极光消息推送模块异常,请联系管理员!", e)
+            null
+        }
+    }
+
+    /**
+     * 绑定设备到个人属性 内部直连版本使用
+     */
+    override fun jPushBindDevice(deviceToken: String) {
+        if (BuildConfig.InnerServer) {
+            XLog.info("绑定设备号")
+            val service = getJPushControlService()
+            if (service != null) {
+                val form = JPushDeviceForm(deviceToken)
+                service.deviceBind(form).subscribeOn(Schedulers.io())
+                        .observeOn(AndroidSchedulers.mainThread())
+                        .o2Subscribe {
+                            onNext { res ->
+                                XLog.info("绑定设备到个人属性,结果:${res.data.isValue}")
+                            }
+                            onError { e, _ ->
+                                XLog.error("绑定设备到个人属性出错,", e)
+                            }
+                        }
+            } else {
+                XLog.error("没有极光推送模块")
+            }
+        }
+    }
+
+    /**
+     * 解除绑定设备 内部直连版本使用
+     */
+    override fun jPushUnBindDevice(deviceToken: String) {
+        if (BuildConfig.InnerServer) {
+            XLog.info("解除绑定设备号")
+            val service = getJPushControlService()
+            if (service != null) {
+                service.deviceUnBind(deviceToken).subscribeOn(Schedulers.io())
+                        .observeOn(AndroidSchedulers.mainThread())
+                        .o2Subscribe {
+                            onNext { res ->
+                                XLog.info("绑定设备到个人属性,结果:${res.data.isValue}")
+                            }
+                            onError { e, _ ->
+                                XLog.error("绑定设备到个人属性出错,", e)
+                            }
+                        }
+            } else {
+                XLog.error("没有极光推送模块")
+            }
+        }
+    }
+
+
     /**
      * 图灵 v1 服务
      */

+ 1 - 0
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/cms/application/CMSApplicationActivity.kt

@@ -173,6 +173,7 @@ class CMSApplicationActivity : BaseMVPActivity<CMSApplicationContract.View, CMSA
 
 
     private fun showPublishCategoriesList() {
+        //处理绑定流程的那些发布
         val items = canPublishCategories.map { it.categoryName }
         BottomSheetMenu(this)
                 .setTitle("选择发布的分类")

+ 35 - 16
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/cms/application/CMSPublishDocumentActivity.kt

@@ -10,15 +10,14 @@ import kotlinx.android.synthetic.main.activity_cms_publish_document.*
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.R
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.base.BaseMVPActivity
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.cms.view.CMSWebViewActivity
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.o2.webview.TaskWebViewActivity
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.cms.CMSCategoryInfoJson
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.cms.CMSDocumentInfoJson
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.identity.WoIdentityListItem
 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.goThenKill
 import org.jetbrains.anko.dip
-import java.util.*
 import kotlin.collections.ArrayList
 
 class CMSPublishDocumentActivity : BaseMVPActivity<CMSPublishDocumentContract.View, CMSPublishDocumentContract.Presenter>(),
@@ -95,6 +94,7 @@ class CMSPublishDocumentActivity : BaseMVPActivity<CMSPublishDocumentContract.Vi
     }
 
     override fun newDocumentId(id: String) {
+        hideLoadingDialog()
         if (!TextUtils.isEmpty(id)) {
             val title = edit_cms_publish_title.text.toString()
             goThenKill<CMSWebViewActivity>(CMSWebViewActivity.startBundleData(id, title))
@@ -103,10 +103,25 @@ class CMSPublishDocumentActivity : BaseMVPActivity<CMSPublishDocumentContract.Vi
         }
     }
 
-    override fun newDocumentFail() {
-        XToast.toastShort(this, "保存失败!")
+    override fun newDocumentFail(msg: String) {
+        hideLoadingDialog()
+        XToast.toastShort(this, msg)
     }
 
+    override fun startProcessSuccess(workId: String, title: String) {
+        hideLoadingDialog()
+        val bundle = Bundle()
+        bundle.putString(TaskWebViewActivity.WORK_WEB_VIEW_WORK, workId)
+        bundle.putString(TaskWebViewActivity.WORK_WEB_VIEW_TITLE, title)
+        goThenKill<TaskWebViewActivity>(bundle)
+    }
+
+    override fun startProcessFail(message: String) {
+        XToast.toastShort(this, "启动流程失败, $message")
+        hideLoadingDialog()
+    }
+
+
     private fun createDocument() {
         val title = edit_cms_publish_title.text.toString()
         if(TextUtils.isEmpty(title)) {
@@ -117,18 +132,22 @@ class CMSPublishDocumentActivity : BaseMVPActivity<CMSPublishDocumentContract.Vi
             XToast.toastShort(this, "身份不能为空!")
             return
         }
-        val document = CMSDocumentInfoJson()
-//        document.id = UUID.randomUUID().toString()
-        document.title = title
-        document.appId = category!!.appId
-        document.categoryId = category!!.id
-        document.categoryAlias = category!!.categoryAlias
-        document.categoryName = category!!.categoryName
-        document.creatorIdentity = identity
-        document.docStatus = "draft"
-        document.isNewDocument = true
-        XLog.info(document.toString())
-        mPresenter.newDocument(document)
+        showLoadingDialog()
+        if (category?.workflowFlag != null && "" != category?.workflowFlag) {
+            mPresenter.startProcess(title, identity, category?.workflowFlag!!)
+        }else {
+            val document = CMSDocumentInfoJson()
+            document.title = title
+            document.appId = category!!.appId
+            document.categoryId = category!!.id
+            document.categoryAlias = category!!.categoryAlias
+            document.categoryName = category!!.categoryName
+            document.creatorIdentity = identity
+            document.docStatus = "draft"
+            document.isNewDocument = true
+            XLog.info(document.toString())
+            mPresenter.newDocument(document)
+        }
 
     }
 

+ 4 - 1
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/cms/application/CMSPublishDocumentContract.kt

@@ -15,11 +15,14 @@ object CMSPublishDocumentContract {
     interface View : BaseView {
         fun currentPersonIdentities(list: List<WoIdentityListItem>)
         fun newDocumentId(id: String)
-        fun newDocumentFail()
+        fun newDocumentFail(msg: String)
+        fun startProcessSuccess(workId:String, title: String)
+        fun startProcessFail(message:String)
     }
 
     interface Presenter : BasePresenter<View> {
         fun findCurrentPersonIdentity()
         fun newDocument(doc: CMSDocumentInfoJson)
+        fun startProcess(title: String, identifyId: String, processId: String)
     }
 }

+ 32 - 2
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/cms/application/CMSPublishDocumentPresenter.kt

@@ -1,8 +1,13 @@
 package net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.cms.application
 
+import android.text.TextUtils
+import net.muliba.accounting.app.ExceptionHandler
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2SDKManager
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.base.BasePresenterImpl
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.ResponseHandler
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.cms.CMSDocumentInfoJson
+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 okhttp3.MediaType
@@ -48,14 +53,39 @@ class CMSPublishDocumentPresenter : BasePresenterImpl<CMSPublishDocumentContract
                         if (id!=null) {
                             mView?.newDocumentId(id.id)
                         }else {
-                            mView?.newDocumentFail()
+                            mView?.newDocumentFail("没有返回文档Id!")
                         }
                     }
                     onError { e, isNetworkError ->
                         XLog.error("保存文档错误, netErr: $isNetworkError", e)
-                        mView?.newDocumentFail()
+                        mView?.newDocumentFail(e?.message ?: "")
                     }
                 }
     }
 
+    override fun startProcess(title: String, identifyId: String, processId: String) {
+        if (TextUtils.isEmpty(identifyId) || TextUtils.isEmpty(processId)) {
+            mView?.startProcessFail("传入参数为空,无法启动流程,identity:$identifyId,processId:$processId")
+            return
+        }
+        val body = ProcessStartBo()
+        body.title = title
+        body.identity = identifyId
+        getProcessAssembleSurfaceServiceAPI(mView?.getContext())?.let { service ->
+            service.startProcess(processId, body)
+                    .subscribeOn(Schedulers.io())
+                    .observeOn(AndroidSchedulers.mainThread())
+                    .subscribe(ResponseHandler<List<ProcessWorkData>> { list ->
+                        try {
+                            mView?.startProcessSuccess(list[0].taskList[0].work, title)
+                        } catch (e: Exception) {
+                            XLog.error("", e)
+                            mView?.startProcessFail("返回数据异常!${e.message}")
+                        }
+                    }, ExceptionHandler(mView?.getContext()) { e ->
+                        mView?.startProcessFail(e.message ?: "")
+                    })
+        }
+    }
+
 }

+ 37 - 1
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/cms/view/CMSWebViewActivity.kt

@@ -34,6 +34,7 @@ import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.vo.AttachmentItemVO
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.vo.O2UploadImageData
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.*
 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.o2Subscribe
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.visible
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.permission.PermissionRequester
@@ -258,6 +259,26 @@ class CMSWebViewActivity : BaseMVPActivity<CMSWebViewContract.View, CMSWebViewCo
         })
     }
 
+    /**
+     * 编辑文档
+     * 点击把文档从阅读表单变成编辑表单
+     */
+    fun editDocument(view: View?) {
+        web_view_cms_document_content.evaluateJavascript("layout.appForm.editDocumentForMobile()") { value ->
+            XLog.info("转成编辑表单,返回:$value")
+        }
+    }
+
+    /**
+     * 保存文档
+     *
+     */
+    fun saveDocument(view: View?) {
+        web_view_cms_document_content.evaluateJavascript("layout.appForm.saveDocument(layout.close)") { value ->
+            XLog.info("保存表单,返回:$value")
+        }
+    }
+
 
     //MARK: javascript interface
 
@@ -282,7 +303,8 @@ class CMSWebViewActivity : BaseMVPActivity<CMSWebViewContract.View, CMSWebViewCo
         //                        "allowEditDocument":  isControl && !this.document.wf_workId,
         //                        "allowDeleteDocument":  isControl && !this.document.wf_workId,
         //                        "allowArchiveDocument" : false,
-        //                        "allowRedraftDocument" : false
+        //                        "allowRedraftDocument" : false,
+        //                        "currentMode": "read" //edit 编辑表单还是阅读表单
         //                    };
         XLog.debug("表单加载完成回调:$control")
         if (!TextUtils.isEmpty(control)) {
@@ -297,6 +319,20 @@ class CMSWebViewActivity : BaseMVPActivity<CMSWebViewContract.View, CMSWebViewCo
                     if (cmsWorkControl.allowPublishDocument) {
                         tv_cms_form_publish_btn.visible()
                         i++
+                    }else {
+                        if (cmsWorkControl.allowEditDocument && cmsWorkControl.allowSave) {
+                            if (cmsWorkControl.currentMode == "read") {
+                                tv_cms_form_edit_btn.visible()
+                                tv_cms_form_save_btn.gone()
+                            }else if (cmsWorkControl.currentMode == "edit") {
+                                tv_cms_form_edit_btn.gone()
+                                tv_cms_form_save_btn.visible()
+                            }
+                            i++
+                        }else {
+                            tv_cms_form_edit_btn.gone()
+                            tv_cms_form_save_btn.gone()
+                        }
                     }
                     if (i>0) {
                         fl_bottom_operation_bar.visible()

+ 16 - 38
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/about/AboutActivity.kt

@@ -9,15 +9,11 @@ import android.support.v7.app.AppCompatActivity
 import android.support.v7.widget.Toolbar
 import android.text.TextUtils
 import android.widget.TextView
-import com.pgyersdk.update.PgyUpdateManager
-import com.pgyersdk.update.UpdateManagerListener
 import kotlinx.android.synthetic.main.content_about.*
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2CustomStyle
-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.*
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.o2.DownloadAPKFragment
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.service.DownloadAPKService
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.PgyUpdateBean
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.O2AppUpdateBean
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.*
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.widgets.dialog.O2AlertIconEnum
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.widgets.dialog.O2DialogSupport
@@ -59,11 +55,6 @@ class AboutActivity : AppCompatActivity() {
         }
     }
 
-    override fun onPause() {
-        super.onPause()
-        PgyUpdateManager.unregister()
-    }
-
 
     /**
      * 检查应用是否需要更新
@@ -102,39 +93,26 @@ class AboutActivity : AppCompatActivity() {
         val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
         startActivityForResult(intent, 10086)
     }
-    private fun checkAppUpdate(noUpdateIsNotify: Boolean = false, callbackContinue:((flag: Boolean)->Unit)? = null) {
-        PgyUpdateManager.register(this, object : UpdateManagerListener() {
-            override fun onUpdateAvailable(p0: String?) {
-                XLog.debug("onUpdateAvailable $p0")
-                val bean = O2SDKManager.instance().gson.fromJson(p0, PgyUpdateBean::class.java)
-                versionName = bean.data.versionName
-                downloadUrl = bean.data.downloadURL
+    private fun checkAppUpdate(callbackContinue:((flag: Boolean)->Unit)? = null) {
+        O2AppUpdateManager.instance().checkUpdate(this, object : O2AppUpdateCallback {
+            override fun onUpdate(version: O2AppUpdateBean) {
+                XLog.debug("onUpdateAvailable $version")
+                versionName = version.versionName
+                downloadUrl = version.downloadUrl
                 XLog.info("versionName:$versionName, downloadUrl:$downloadUrl")
-                if (bean != null) {
-                    val currentversionName = AndroidUtils.getAppVersionName(this@AboutActivity)
-                    if (currentversionName != versionName) {
-                        O2DialogSupport.openConfirmDialog(this@AboutActivity,"版本 $versionName 更新:"+ bean.data.releaseNote, listener = { _ ->
-                            XLog.info("notification is true..........")
-                            callbackContinue?.invoke(true)
-                        }, icon = O2AlertIconEnum.UPDATE, negativeListener = { _->
-                            callbackContinue?.invoke(false)
-                        })
-
-                    } else {
-                        callbackContinue?.invoke(false)
-                        XLog.info("versionName is same , do not show dialog! versionName:$versionName ")
-                    }
-                }else {
+                O2DialogSupport.openConfirmDialog(this@AboutActivity,"版本 $versionName 更新:"+version.content, listener = { _ ->
+                    XLog.info("notification is true..........")
+                    callbackContinue?.invoke(true)
+                }, icon = O2AlertIconEnum.UPDATE, negativeListener = {_->
                     callbackContinue?.invoke(false)
-                }
-
+                })
             }
 
-            override fun onNoUpdateAvailable() {
-                XLog.info("没有发现新版本!")
-                XToast.toastShort(this@AboutActivity, "没有发现新版本!")
+            override fun onNoneUpdate(error: String) {
+                XLog.info(error)
                 callbackContinue?.invoke(false)
             }
+
         })
     }
     private fun downloadServiceStart() {

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

@@ -66,6 +66,10 @@ class FirstStepFragment : BaseMVPFragment<FirstStepContract.View, FirstStepContr
     }
 
     override fun receiveUnitList(list: List<CollectUnitData>) {
+        if (list.isEmpty()) {
+            XToast.toastShort(activity, "没有获取到绑定服务器列表!")
+            return
+        }
         if (list.size == 1) {
             autoBind(list[0])
         }else {

+ 15 - 31
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/launch/LaunchActivity.kt

@@ -38,10 +38,8 @@ import net.zoneland.x.bpm.mobile.v1.zoneXBPM.widgets.dialog.O2AlertIconEnum
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.widgets.dialog.O2DialogSupport
 import org.jetbrains.anko.dip
 import android.support.annotation.RequiresApi
-import com.pgyersdk.update.PgyUpdateManager
-import com.pgyersdk.update.UpdateManagerListener
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.service.DownloadAPKService
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.PgyUpdateBean
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.O2AppUpdateBean
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.*
 
 
@@ -210,40 +208,26 @@ class LaunchActivity : BaseMVPActivity<LaunchContract.View, LaunchContract.Prese
         val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
         startActivityForResult(intent, 10086)
     }
-    private fun checkAppUpdate(noUpdateIsNotify: Boolean = false, callbackContinue:((flag: Boolean)->Unit)? = null) {
-        PgyUpdateManager.register(this, object : UpdateManagerListener() {
-            override fun onUpdateAvailable(p0: String?) {
-                XLog.debug("onUpdateAvailable $p0")
-                val bean = O2SDKManager.instance().gson.fromJson(p0, PgyUpdateBean::class.java)
-                versionName = bean.data.versionName
-                downloadUrl = bean.data.downloadURL
+    private fun checkAppUpdate(callbackContinue:((flag: Boolean)->Unit)? = null) {
+        O2AppUpdateManager.instance().checkUpdate(this, object : O2AppUpdateCallback {
+            override fun onUpdate(version: O2AppUpdateBean) {
+                XLog.debug("onUpdateAvailable $version")
+                versionName = version.versionName
+                downloadUrl = version.downloadUrl
                 XLog.info("versionName:$versionName, downloadUrl:$downloadUrl")
-                if (bean != null) {
-                    val currentversionName = AndroidUtils.getAppVersionName(this@LaunchActivity)
-                    if (currentversionName != versionName) {
-                        O2DialogSupport.openConfirmDialog(this@LaunchActivity,"版本 $versionName 更新:"+ bean.data.releaseNote, listener = { _ ->
-                            XLog.info("notification is true..........")
-                            callbackContinue?.invoke(true)
-//                            toDownloadService(activity)
-                        }, icon = O2AlertIconEnum.UPDATE, negativeListener = {_->
-                            callbackContinue?.invoke(false)
-                        })
-
-                    } else {
-                        callbackContinue?.invoke(false)
-                        XLog.info("versionName is same , do not show dialog! versionName:$versionName ")
-                    }
-                }else {
+                O2DialogSupport.openConfirmDialog(this@LaunchActivity,"版本 $versionName 更新:"+version.content, listener = { _ ->
+                    XLog.info("notification is true..........")
+                    callbackContinue?.invoke(true)
+                }, icon = O2AlertIconEnum.UPDATE, negativeListener = {_->
                     callbackContinue?.invoke(false)
-                }
-
+                })
             }
 
-            override fun onNoUpdateAvailable() {
-                XLog.info("没有发现新版本!")
-
+            override fun onNoneUpdate(error: String) {
+                XLog.info(error)
                 callbackContinue?.invoke(false)
             }
+
         })
     }
     private fun downloadServiceStart() {

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

@@ -18,15 +18,12 @@ import android.text.TextUtils
 import android.util.DisplayMetrics
 import android.view.KeyEvent
 import android.view.View
-import com.pgyersdk.update.PgyUpdateManager
+import cn.jpush.android.api.JPushInterface
 import kotlinx.android.synthetic.main.activity_main.*
 import kotlinx.android.synthetic.main.fragment_main_bottom_bar_image.*
 import net.muliba.changeskin.FancySkinManager
 import net.muliba.fancyfilepickerlibrary.PicturePicker
-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.O2SDKManager
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.R
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.*
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.base.BaseMVPActivity
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.o2.my.ClipAvatarActivity
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.adapter.MainActivityFragmentAdapter
@@ -168,13 +165,16 @@ class MainActivity : BaseMVPActivity<MainContract.View, MainContract.Presenter>(
                 }
             }
         }
+        if (BuildConfig.InnerServer) {
+            val token = JPushInterface.getRegistrationID(this)
+            mPresenter.jPushBindDevice(token)
+        }
     }
 
 
     override fun onPause() {
         super.onPause()
         pictureLoaderService?.close()
-        PgyUpdateManager.unregister()//点击太快 进入main后马上跳到别的Activity去有可能会出错 需要这个unregister
     }
 
     override fun onSaveInstanceState(outState: Bundle?) {

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

@@ -1,27 +1,24 @@
 package net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.o2.main
 
-import android.Manifest
 import android.text.TextUtils
 import android.view.View
-import com.pgyersdk.feedback.PgyFeedback
-import com.pgyersdk.views.PgyerDialog
+import cn.jpush.android.api.JPushInterface
 import kotlinx.android.synthetic.main.fragment_main_settings.*
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.*
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.base.BaseMVPViewPagerFragment
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.o2.about.AboutActivity
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.o2.login.LoginActivity
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.o2.notice.NoticeSettingActivity
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.o2.organization.ContactPickerActivity
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.o2.security.AccountSecurityActivity
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.app.o2.skin.SkinManagerActivity
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.BitmapUtil
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.HttpCacheUtil
-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.*
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.permission.PermissionRequester
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.go
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.goAndClearBefore
+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.AndroidShareDialog
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.widgets.BottomSheetMenu
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.widgets.dialog.O2AlertIconEnum
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.widgets.dialog.O2DialogSupport
 
@@ -58,7 +55,7 @@ class SettingsFragment : BaseMVPViewPagerFragment<SettingsContract.View, Setting
             setting_button_customer_service_id.setOnClickListener(this)
         }
 
-        setting_button_feedback_id.setOnClickListener(this)
+//        setting_button_feedback_id.setOnClickListener(this)
         myInfo_logout_btn_id.setOnClickListener(this)
 
         val path = O2CustomStyle.setupAboutImagePath(activity)
@@ -80,7 +77,7 @@ class SettingsFragment : BaseMVPViewPagerFragment<SettingsContract.View, Setting
                 }, O2AlertIconEnum.CLEAR)
             }
             R.id.setting_button_customer_service_id -> shareDialog.show()
-            R.id.setting_button_feedback_id -> startFeedBack()
+//            R.id.setting_button_feedback_id -> startFeedBack()
             R.id.setting_button_about_id -> activity.go<AboutActivity>()
             R.id.myInfo_logout_btn_id -> logout()
 
@@ -101,30 +98,33 @@ class SettingsFragment : BaseMVPViewPagerFragment<SettingsContract.View, Setting
     }
 
     private fun logout() {
-        XLog.debug("acti ity: ${activity == null}")
         O2DialogSupport.openConfirmDialog(activity, "确定要退出登录吗?", {
+            if (BuildConfig.InnerServer) {
+                val token = JPushInterface.getRegistrationID(activity)
+                mPresenter.jPushUnBindDevice(token)
+            }
             mPresenter.logout()
         })
     }
 
-    private fun startFeedBack() {
-        PermissionRequester(activity)
-                .request(Manifest.permission.RECORD_AUDIO)
-                .o2Subscribe {
-                    onNext { (granted, shouldShowRequestPermissionRationale, deniedPermissions) ->
-                        XLog.info("granted:$granted , shouldShowRequest:$shouldShowRequestPermissionRationale, denied:$deniedPermissions")
-                        if (!granted) {
-                            O2DialogSupport.openAlertDialog(activity, "需要麦克风权限才能进行语音反馈!")
-                        } else {
-                            PgyerDialog.setDialogTitleBackgroundColor("#FB4747")
-                            PgyFeedback.getInstance().showDialog(activity)
-                        }
-                    }
-                    onError { e, _ ->
-                        XLog.error("麦克风权限验证异常", e)
-                    }
-                }
-    }
+//    private fun startFeedBack() {
+//        PermissionRequester(activity)
+//                .request(Manifest.permission.RECORD_AUDIO)
+//                .o2Subscribe {
+//                    onNext { (granted, shouldShowRequestPermissionRationale, deniedPermissions) ->
+//                        XLog.info("granted:$granted , shouldShowRequest:$shouldShowRequestPermissionRationale, denied:$deniedPermissions")
+//                        if (!granted) {
+//                            O2DialogSupport.openAlertDialog(activity, "需要麦克风权限才能进行语音反馈!")
+//                        } else {
+//                            PgyerDialog.setDialogTitleBackgroundColor("#FB4747")
+//                            PgyFeedback.getInstance().showDialog(activity)
+//                        }
+//                    }
+//                    onError { e, _ ->
+//                        XLog.error("麦克风权限验证异常", e)
+//                    }
+//                }
+//    }
 
     private fun logoutThenJump2Login() {
         O2SDKManager.instance().logoutCleanCurrentPerson()

+ 5 - 9
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/scanlogin/ScanLoginActivity.kt

@@ -59,15 +59,11 @@ class ScanLoginActivity : BaseMVPActivity<ScanLoginContract.View, ScanLoginContr
 
     private fun parseResult() {
         if (StringUtil.isUrl(result)) {
-            if (result.contains("pgyer.com")) {
-                parseMeta()
-                if (!TextUtils.isEmpty(meta)) {
-                    title = getString(net.zoneland.x.bpm.mobile.v1.zoneXBPM.R.string.scan_login_confirm_title)
-                    activity_scan_login.visible()
-                    tv_scan_login_text_content.gone()
-                }else{
-                    gotoDefaultBrowser()
-                }
+            parseMeta()
+            if (!TextUtils.isEmpty(meta)) {
+                title = getString(net.zoneland.x.bpm.mobile.v1.zoneXBPM.R.string.scan_login_confirm_title)
+                activity_scan_login.visible()
+                tv_scan_login_text_content.gone()
             }else if (result.contains("x_meeting_assemble_control") && result.contains("/checkin")){
                 meetingCheckin(result)//会议签到
             }else{

+ 7 - 2
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/security/AccountSecurityActivity.kt

@@ -42,8 +42,13 @@ class AccountSecurityActivity : BaseMVPActivity<AccountSecurityContract.View, Ac
         initBiometryAuthView()
 
 
-        rl_account_security_bind_device_btn.setOnClickListener {
-            go<DeviceManagerActivity>()
+        if (BuildConfig.InnerServer) {
+            ll_account_security_bind_device_layout.gone()
+        }else {
+            ll_account_security_bind_device_layout.visible()
+            rl_account_security_bind_device_btn.setOnClickListener {
+                go<DeviceManagerActivity>()
+            }
         }
 
     }

+ 0 - 1
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/webview/PortalWebViewActivity.kt

@@ -58,7 +58,6 @@ class PortalWebViewActivity : BaseMVPActivity<PortalWebViewContract.View, Portal
                 }
             }
         }
-        toolbar?.visibility = View.GONE
     }
 
     override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {

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

@@ -9,6 +9,8 @@ import android.graphics.Color
 import android.net.Uri
 import android.net.http.SslError
 import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
 import android.provider.MediaStore
 import android.support.v4.content.ContextCompat
 import android.text.TextUtils
@@ -21,7 +23,6 @@ import android.webkit.WebView
 import android.webkit.WebViewClient
 import android.widget.*
 import com.google.gson.reflect.TypeToken
-import com.tencent.smtt.sdk.QbSdk
 import kotlinx.android.synthetic.main.activity_work_web_view.*
 import net.muliba.fancyfilepickerlibrary.FilePicker
 import net.muliba.fancyfilepickerlibrary.PicturePicker
@@ -33,7 +34,6 @@ 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.ReadData
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.TaskData
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.WorkOpinionData
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.vo.O2UploadImageData
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.*
@@ -46,7 +46,14 @@ import net.zoneland.x.bpm.mobile.v1.zoneXBPM.widgets.BottomSheetMenu
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.widgets.WebChromeClientWithProgressAndValueCallback
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.widgets.dialog.O2DialogSupport
 import org.jetbrains.anko.dip
+import org.jetbrains.anko.doAsync
+import rx.Observable
+import rx.Scheduler
+import rx.android.schedulers.AndroidSchedulers
+import rx.schedulers.Schedulers
 import java.io.File
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
 
 
 class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebViewContract.Presenter>(), TaskWebViewContract.View {
@@ -196,32 +203,55 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
         }
     }
 
-    //MARK: - click operation button event
+    //MARK:- 表单处理
 
+    //region 表单处理按钮
+
+    /**
+     * 删除工作
+     */
     fun formDeleteBtnClick(view: View?) {
         O2DialogSupport.openConfirmDialog(this@TaskWebViewActivity, getString(R.string.delete_work_confirm_message), listener =  {
             showLoadingDialog()
             mPresenter.delete(workId)
         })
     }
+
+    /**
+     * 保存工作
+     */
     fun formSaveBtnClick(view: View?) {
         XLog.debug("click save button")
         web_view.clearFocus()
-        evaluateJavascriptGetFormData()
+        evaluateJavascriptGetFormDataAndSave()
     }
+
+    /**
+     * 继续流转
+     */
     fun formGoNextBtnClick(view: View?) {
         XLog.debug("click submit button")
         web_view.clearFocus()
-        formData()
-        getFormOpinion()
-        submitData()
+        formData{
+            getFormOpinion{
+                submitData()
+            }
+        }
     }
+
+    /**
+     * 标记为已阅
+     */
     fun formSetReadBtnClick(view: View?) {
         O2DialogSupport.openConfirmDialog(this@TaskWebViewActivity, getString(R.string.read_complete_confirm_message), listener =  {
             showLoadingDialog()
             mPresenter.setReadComplete(read)
         })
     }
+
+    /**
+     * 撤回工作
+     */
     fun formRetractBtnClick(view: View?) {
         O2DialogSupport.openConfirmDialog(this@TaskWebViewActivity, getString(R.string.retract_confirm_message), listener = {
             showLoadingDialog()
@@ -229,6 +259,8 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
         })
     }
 
+    //endregion
+
     // MARK: - finish submit callback webview javascript
     /**
      * @param site 如果是手写签批的 返回site值
@@ -243,58 +275,66 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
 
     // MARK: - javascriptInterface
 
+    //region javascriptInterface
+    @JavascriptInterface
+    fun closeWork(result: String) {
+        XLog.debug("关闭表单 closeWork :$result")
+        finish()
+    }
+
     /**
      * 表单加载完成后回调
      */
     @JavascriptInterface
     fun appFormLoaded(result: String) {// 获取control 动态生成操作按钮
         XLog.debug("表单加载完成回调:$result")// 20190520 result改成了操作按钮列表 如果是result是true就是老系统,用原来的方式。。。。。。。。得兼容老方式诶
-        runOnUiThread {
-            if (TextUtils.isEmpty(title)) {
-                web_view.evaluateJavascript("layout.appForm.businessData.work.title") { value ->
-                    XLog.debug("title: $title")
-                    try {
-                        title = O2SDKManager.instance().gson.fromJson(value, String::class.java)
-                        updateToolbarTitle(title)
-                    } catch (e: Exception) {
-                    }
-                }
-            }
-
-            if (result == "true") { // 老版本的操作
-                // 获取control 生成操作按钮
-                web_view.evaluateJavascript("layout.appForm.businessData.control") { value ->
-                    XLog.debug("control: $value")
-                    try {
-                        control = O2SDKManager.instance().gson.fromJson(value, WorkControl::class.java)
-                    } catch (e: Exception) {
-                    }
-                    initOptionBar()
-                }
-            }else {// 2019-05-21 增加新版操作按钮
-                // 解析result 操作按钮列表
-                if (!TextUtils.isEmpty(result)) {
-                    try {
-                        val type = object : TypeToken<List<WorkNewActionItem>>() {}.type
-                        val list: List<WorkNewActionItem> = O2SDKManager.instance().gson.fromJson(result, type)
-                        initOptionBarNew(list)
-                    }catch (e: Exception){
-                        XLog.error("解析操作按钮结果列表出错", e)
-                    }
-                }else {
-                    XLog.error("操作按钮结果为空")
-                }
-
-            }
-
-            web_view.evaluateJavascript("layout.appForm.businessData.read") { value ->
-                XLog.debug("read: $value")
-                try {
-                    read = O2SDKManager.instance().gson.fromJson(value, ReadData::class.java)
-                } catch (e: Exception) {
-                }
-            }
-        }
+        //2019-12-09 使用workwithaction的html 不用移动端的相关操作按钮了
+//        runOnUiThread {
+//            if (TextUtils.isEmpty(title)) {
+//                web_view.evaluateJavascript("layout.app.appForm.businessData.work.title") { value ->
+//                    XLog.debug("title: $title")
+//                    try {
+//                        title = O2SDKManager.instance().gson.fromJson(value, String::class.java)
+//                        updateToolbarTitle(title)
+//                    } catch (e: Exception) {
+//                    }
+//                }
+//            }
+//
+//            if (result == "true") { // 老版本的操作
+//                // 获取control 生成操作按钮
+//                web_view.evaluateJavascript("layout.app.appForm.businessData.control") { value ->
+//                    XLog.debug("control: $value")
+//                    try {
+//                        control = O2SDKManager.instance().gson.fromJson(value, WorkControl::class.java)
+//                    } catch (e: Exception) {
+//                    }
+//                    initOptionBar()
+//                }
+//            }else {// 2019-05-21 增加新版操作按钮
+//                // 解析result 操作按钮列表
+//                if (!TextUtils.isEmpty(result)) {
+//                    try {
+//                        val type = object : TypeToken<List<WorkNewActionItem>>() {}.type
+//                        val list: List<WorkNewActionItem> = O2SDKManager.instance().gson.fromJson(result, type)
+//                        initOptionBarNew(list)
+//                    }catch (e: Exception){
+//                        XLog.error("解析操作按钮结果列表出错", e)
+//                    }
+//                }else {
+//                    XLog.error("操作按钮结果为空")
+//                }
+//
+//            }
+//
+//            web_view.evaluateJavascript("layout.app.appForm.businessData.read") { value ->
+//                XLog.debug("read: $value")
+//                try {
+//                    read = O2SDKManager.instance().gson.fromJson(value, ReadData::class.java)
+//                } catch (e: Exception) {
+//                }
+//            }
+//        }
     }
 
 
@@ -399,17 +439,23 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
             }
         }
     }
-
+    //endregion
 
     //MARK: - view implements
 
+    //region view implements
+
     override fun finishLoading() {
+        XLog.debug("finishLoading.........")
         hideLoadingDialog()
     }
 
     override fun saveSuccess() {
-        hideLoadingDialog()
-        XToast.toastShort(this, "保存成功!")
+        XLog.debug("savesucess.........")
+        evaluateJavascriptAfterSave {
+            hideLoadingDialog()
+            XToast.toastShort(this, "保存成功!")
+        }
     }
     override fun submitSuccess() {
         hideLoadingDialog()
@@ -446,7 +492,7 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
     override fun uploadAttachmentSuccess(attachmentId: String, site: String) {
         XLog.debug("uploadAttachmentResponse attachmentId:$attachmentId, site:$site")
         hideLoadingDialog()
-        web_view.evaluateJavascript("layout.appForm.uploadedAttachment(\"$site\", \"$attachmentId\")"){
+        web_view.evaluateJavascript("layout.app.appForm.uploadedAttachment(\"$site\", \"$attachmentId\")"){
             value -> XLog.debug("uploadedAttachment, onReceiveValue value=$value")
         }
     }
@@ -454,7 +500,7 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
     override fun replaceAttachmentSuccess(attachmentId: String, site: String) {
         XLog.debug("replaceAttachmentResponse attachmentId:$attachmentId, site:$site")
         hideLoadingDialog()
-        web_view.evaluateJavascript("layout.appForm.replacedAttachment(\"$site\", \"$attachmentId\")"){
+        web_view.evaluateJavascript("layout.app.appForm.replacedAttachment(\"$site\", \"$attachmentId\")"){
             value -> XLog.debug("replacedAttachment, onReceiveValue value=$value")
         }
     }
@@ -501,8 +547,10 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
             XLog.error("图片控件对象不存在。。。。。。。。")
         }
     }
+    //endregion
 
-    //MARK: - private function
+
+    //region  private function
 
     /**
      * 生成操作按钮
@@ -546,9 +594,8 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
      * 生成操作按钮 新版
      */
     private fun initOptionBarNew(list: List<WorkNewActionItem>) {
-        if(!list.isEmpty()) {
-            val len = list.count()
-            when(len) {
+        if(list.isNotEmpty()) {
+            when(list.count()) {
                 1 -> {
                     val menuItem = list[0]
                     tv_work_form_bottom_first_action.text = menuItem.text
@@ -673,11 +720,14 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
         return button
     }
 
+    /**
+     * 提交数据
+     */
     private fun submitData() {
-        web_view.evaluateJavascript("layout.appForm.formValidation(\"\", \"\")") { value ->
+        web_view.evaluateJavascript("layout.app.appForm.formValidation(\"\", \"\")") { value ->
             XLog.debug("formValidation,value:$value")
             if (value == "true") {
-                web_view.evaluateJavascript("layout.appForm.businessData.task") { task ->
+                web_view.evaluateJavascript("layout.app.appForm.businessData.task") { task ->
                     XLog.debug("submitData, onReceiveValue value=$task")
                     try {
                         XLog.debug("submitData,TaskData:$task")
@@ -702,7 +752,7 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
      * 选择路由和填写意见后,提交工作前
      */
     fun validateFormForSubmitDialog(route: String, opinion: String, callback:(Boolean)->Unit) {
-        web_view.evaluateJavascript("layout.appForm.formValidation(\"$route\", \"$opinion\")") { value ->
+        web_view.evaluateJavascript("layout.app.appForm.formValidation(\"$route\", \"$opinion\")") { value ->
             if (value == "true") {
                 callback(true)
             }else {
@@ -717,15 +767,16 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
     }
 
 
-    private fun formData() {
-        web_view.evaluateJavascript("layout.appForm.getData()") { value ->
+    private fun formData(callback: () -> Unit) {
+        web_view.evaluateJavascript("layout.app.appForm.getData()") { value ->
             XLog.debug("evaluateJavascriptGetFormData, onReceiveValue form value=$value")
             formData = value
+            callback()
         }
     }
 
-    private fun getFormOpinion() {
-        web_view.evaluateJavascript("layout.appForm.getOpinion()") { value ->
+    private fun getFormOpinion(callback: () -> Unit) {
+        web_view.evaluateJavascript("layout.app.appForm.getOpinion()") { value ->
             XLog.debug("evaluateJavascript get from Opinion, onReceiveValue form value=$value")
             if (!TextUtils.isEmpty(value)) {
                 formOpinion = if (value == "\"\"") {
@@ -741,73 +792,68 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
                 }
 
             }
+            callback()
         }
     }
 
-    private fun evaluateJavascriptGetFormData() {
-        web_view.evaluateJavascript("layout.appForm.getData()") { value ->
-            XLog.debug("evaluateJavascriptGetFormData, onReceiveValue save value=$value")
-            if (value == null) {
-                runOnUiThread {
-                    XToast.toastShort(getContext(), "没有获取到表单数据!")
+
+    private fun evaluateJavascriptGetFormDataAndSave() {
+        showLoadingDialog()
+        web_view.evaluateJavascript("(layout.app.appForm.fireEvent(\"beforeSave\");return layout.app.appForm.getData();)") { value ->
+            XLog.debug("evaluateJavascriptGetFormDataAndSave, onReceiveValue save value=$value")
+            formData = value
+            XLog.debug("执行完成。。。。")
+            runOnUiThread {
+                XLog.debug("runOnUiThread  ....................")
+                if (formData == null || "" == formData) {
+                    XLog.debug("formData is null")
+                    hideLoadingDialog()
+                    XToast.toastShort(this@TaskWebViewActivity, "没有获取到表单数据!")
+                }else {
+                    evaluateJavascriptBeforeSave {
+                        mPresenter.save(workId, formData!!)
+                    }
                 }
-                return@evaluateJavascript
             }
-            formData = value
-            showLoadingDialog()
-            mPresenter.save(workId, value)
         }
     }
 
+
+
     /**
-     * 继续流转 路由选择弹出窗
-     *
-     * @param data
+     * 执行beforeSave
      */
-    private fun openChooseRouterDialog(data: TaskData) {
-        val dialog = O2DialogSupport.openCustomViewDialog(this,
-                getString(R.string.work_form_submit),
-                getString(R.string.work_form_submit_button),
-                getString(R.string.work_form_cancel_button),
-                R.layout.dialog_approve_router_choose,
-                { dialog ->
-                    val text = dialog.findViewById<EditText>(R.id.edit_approve_router_opinion)
-                    val opinion = text.text.toString()
-                    XLog.debug("Positive,opinion: $opinion")
-                    val group = dialog.findViewById<RadioGroup>(R.id.radio_group_approve_router_choose)
-                    XLog.debug("Positvie,checked id:" + group.checkedRadioButtonId)
-                    val radio = dialog.findViewById<RadioButton>(group.checkedRadioButtonId)
-                    val routeName = radio.text.toString()
-                    XLog.debug("Positive,radio, $routeName")
-                    validateFormBeforeSubmit(routeName, opinion, data)
-                    dialog.dismiss()
-                },
-                { _ ->
-                    hideLoadingDialog()
-                })
-        val opinionText = dialog.findViewById<EditText>(R.id.edit_approve_router_opinion)
-        opinionText.setText(formOpinion)
-        val group = dialog.findViewById<RadioGroup>(R.id.radio_group_approve_router_choose)
-        routeNameList.mapIndexed { index, s ->
-            val tempButton = RadioButton(this@TaskWebViewActivity)
-            tempButton.text = s
-            tempButton.isChecked = routeNameList.size==1
-            tempButton.id = index+ 100
-            group.addView(tempButton, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
-        }
-    }
-
-    private fun validateFormBeforeSubmit(routeName: String, opinion: String, data: TaskData) {
-        web_view.evaluateJavascript("layout.appForm.formValidation(\"$routeName\", \"$opinion\")") { value ->
-            XLog.debug("validateFormBeforeSubmit,value:$value")
-            if ("true" == value) {
-                data.opinion = opinion
-                data.routeName = routeName
-                showLoadingDialog()
-                mPresenter.submit(data, workId, formData)
-            }else {
-                XToast.toastShort(this@TaskWebViewActivity, "请检查表单填写是否正确!")
-            }
+    fun evaluateJavascriptBeforeSave(callback: () -> Unit) {
+        web_view.evaluateJavascript("layout.app.appForm.fireEvent(\"beforeSave\")") { value ->
+            XLog.info("执行beforeSave , result: $value")
+            callback()
+        }
+    }
+    /**
+     * 执行 afterSave
+     */
+    fun evaluateJavascriptAfterSave(callback: () -> Unit) {
+        web_view.evaluateJavascript("layout.app.appForm.fireEvent(\"afterSave\")") { value ->
+            XLog.info("执行afterSave , result: $value")
+            callback()
+        }
+    }
+    /**
+     * 执行 beforeProcess
+     */
+    fun evaluateJavascriptBeforeProcess(callback: () -> Unit) {
+        web_view.evaluateJavascript("layout.app.appForm.fireEvent(\"beforeProcess\")") { value ->
+            XLog.info("执行 beforeProcess , result: $value")
+            callback()
+        }
+    }
+    /**
+     * 执行 afterProcess
+     */
+    fun evaluateJavascriptAfterProcess(callback: () -> Unit) {
+        web_view.evaluateJavascript("layout.app.appForm.fireEvent(\"afterProcess\")") { value ->
+            XLog.info("执行 afterProcess , result: $value")
+            callback()
         }
     }
 
@@ -882,5 +928,6 @@ class TaskWebViewActivity : BaseMVPActivity<TaskWebViewContract.View, TaskWebVie
         }
     }
 
+    //endregion
 
 }

+ 1 - 0
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/webview/TaskWebViewPresenter.kt

@@ -33,6 +33,7 @@ class TaskWebViewPresenter : BasePresenterImpl<TaskWebViewContract.View>(), Task
 
 
     override fun save(workId: String, formData: String) {
+        XLog.debug("save ....... workid:$workId formData:$formData")
         if (TextUtils.isEmpty(workId) || TextUtils.isEmpty(formData)) {
             mView?.invalidateArgs()
             XLog.error("arguments is null  workid:$workId, formData:$formData")

+ 13 - 2
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/webview/TaskWorkSubmitDialogFragment.kt

@@ -131,7 +131,14 @@ class TaskWorkSubmitDialogFragment: DialogFragment(), TaskWorkSubmitDialogContra
                             taskData.routeName = routeName
                             taskData.opinion = opinion
                             loadingDialog.show()
-                            presenter.submit(sign, taskData, workId, formData)
+
+                            //执行beforeProcess beforeSave
+                            (activity as TaskWebViewActivity).evaluateJavascriptBeforeSave {
+                                (activity as TaskWebViewActivity).evaluateJavascriptBeforeProcess{
+                                    presenter.submit(sign, taskData, workId, formData)
+                                }
+                            }
+
                         }else {
                             XToast.toastShort(activity, "表单校验不通过!")
                             closeSelf()
@@ -168,7 +175,11 @@ class TaskWorkSubmitDialogFragment: DialogFragment(), TaskWorkSubmitDialogContra
         loadingDialog.dismiss()
         if (result) {
             if (activity != null && activity is TaskWebViewActivity) {
-                (activity as TaskWebViewActivity).finishSubmit(site)
+                (activity as TaskWebViewActivity).evaluateJavascriptAfterSave {
+                    (activity as TaskWebViewActivity).evaluateJavascriptAfterProcess {
+                        (activity as TaskWebViewActivity).finishSubmit(site)
+                    }
+                }
             }
             closeSelf()
         }else {

+ 0 - 160
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/ApkUpdateCheck.java

@@ -1,160 +0,0 @@
-package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.download;
-
-import android.app.Activity;
-import android.app.ProgressDialog;
-import android.os.Looper;
-import android.text.TextUtils;
-
-import com.pgyersdk.update.UpdateManagerListener;
-
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.SDCardHelper;
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.RetrofitClient;
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service.PgyUpdateApiService;
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.AndroidUtils;
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.FileExtensionHelper;
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.XLog;
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.XToast;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import okhttp3.OkHttpClient;
-import okhttp3.ResponseBody;
-import retrofit2.Response;
-import rx.Subscriber;
-import rx.android.schedulers.AndroidSchedulers;
-import rx.functions.Func1;
-import rx.schedulers.Schedulers;
-
-/**
- * Created by FancyLou on 2016/4/21.
- */
-public class ApkUpdateCheck {
-
-    public void downLoadApk(final Activity activity, String url, final String result) {
-        //监听下载进度
-        final ProgressDialog dialog = new ProgressDialog(activity);
-        dialog.setProgressNumberFormat("%1d KB/%2d KB");
-        dialog.setTitle("下载");
-        dialog.setMessage("正在下载,请稍后...");
-        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
-        dialog.setCancelable(false);
-        dialog.show();
-
-        ProgressHelper.setProgressHander(new DownloadProgressHandler() {
-            @Override
-            public void onProgress(long progress, long total, boolean done) {
-                XLog.debug("是否在主线程中运行" + String.valueOf(Looper.getMainLooper() == Looper.myLooper()));
-                XLog.debug(String.format("%d%% done\n",(100 * progress) / total));
-                XLog.debug("done --->" + String.valueOf(done));
-                dialog.setMax((int) (total/1024));
-                dialog.setProgress((int) (progress/1024));
-                if(done){
-                    dialog.dismiss();
-                }
-            }
-        });
-        OkHttpClient.Builder builder = ProgressHelper.addProgress(null);
-
-        PgyUpdateApiService service = RetrofitClient.Companion.instance()
-                .updateApiService("http://app.pgyer.com/", builder);
-        service.apkDownload(url)
-                .subscribeOn(Schedulers.io())
-                .map(new Func1<Response<ResponseBody>, String>() {
-                    @Override
-                    public String call(Response<ResponseBody> responseBodyResponse) {
-                        XLog.debug("下载结束, 进入response body 处理函数~~~~~~~~~~~~~~~~~~");
-                        String apk = "";
-                        try {
-
-                            InputStream inputStream = null;
-                            OutputStream outputStream = null;
-                            try {
-                                String temp = FileExtensionHelper.getXBPMTempFolder();
-                                long currentTime = System.currentTimeMillis();
-                                apk = temp+ File.separator + "xbpm_"+currentTime+".apk";
-                                SDCardHelper.INSTANCE.generateNewFile(apk);
-                                File file = new File(apk);
-
-                                byte[] fileReader = new byte[4096];
-
-                                long fileSize = responseBodyResponse.body().contentLength();
-                                long fileSizeDownloaded = 0;
-
-                                inputStream = responseBodyResponse.body().byteStream();
-                                outputStream = new FileOutputStream(file);
-
-                                while (true) {
-                                    int read = inputStream.read(fileReader);
-                                    if (read == -1) {
-                                        break;
-                                    }
-                                    outputStream.write(fileReader, 0, read);
-                                    fileSizeDownloaded += read;
-                                    XLog.debug("file download: " + fileSizeDownloaded + " of " + fileSize);
-                                }
-                                outputStream.flush();
-                                UpdateManagerListener.updateLocalBuildNumber(result);
-                                XLog.debug("file download finish ...............");
-                                return apk;
-                            } catch (IOException e) {
-                                XLog.error("生成apk文件出错", e);
-                            } finally {
-                                if (inputStream != null) {
-                                    inputStream.close();
-                                }
-                                if (outputStream != null) {
-                                    outputStream.close();
-                                }
-                            }
-//                            InputStream is = responseBodyResponse.body().byteStream();
-//                            String temp = FileExtensionHelper.getXBPMTempFolder();
-//                            long currentTime = System.currentTimeMillis();
-//                            apk = temp+ File.separator + "xbpm_"+currentTime+".apk";
-//                            SDCardHelper.generateNewFile(apk);
-//                            File file = new File(apk);
-//                            FileOutputStream fos = new FileOutputStream(file);
-//                            BufferedInputStream bis = new BufferedInputStream(is);
-//                            byte[] buffer = new byte[1024];
-//                            int len;
-//                            while ((len = bis.read(buffer)) != -1) {
-//                                fos.write(buffer, 0, len);
-//                                fos.flush();
-//                            }
-//                            fos.close();
-//                            bis.close();
-//                            is.close();
-                        } catch (Exception e) {
-                            XLog.error("生成apk文件出错", e);
-                        }
-                        return apk;
-                    }
-                })
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribe(new Subscriber<String>() {
-                    @Override
-                    public void onCompleted() {
-
-                    }
-
-                    @Override
-                   public void onError(Throwable e) {
-                        XLog.error("download apk failure", e);
-                    }
-
-                    @Override
-                    public void onNext(String response) {
-                        XLog.info("download, apk url :"+ response);
-                        if (!TextUtils.isEmpty(response)){
-                            AndroidUtils.INSTANCE.runApp(activity, response);
-                        }else {
-                            XToast.INSTANCE.toastShort(activity, "下载APK文件出错");
-                        }
-                    }
-                });
-
-    }
-}

+ 2 - 1
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/CMSWorkControl.kt

@@ -11,5 +11,6 @@ class CMSWorkControl(
         var allowEditDocument: Boolean = false,
         var allowDeleteDocument: Boolean = false,
         var allowArchiveDocument: Boolean = false,
-        var allowRedraftDocument: Boolean = false
+        var allowRedraftDocument: Boolean = false,
+        var currentMode: String = "read" //edit read 编辑表单和阅读表单
 )

+ 10 - 0
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/O2AppUpdateBean.kt

@@ -0,0 +1,10 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo
+
+
+
+data class O2AppUpdateBean(
+        var versionName: String = "", // app 显示版本号
+        var buildNo: String  = "", // app内部版本号 一个数字
+        var downloadUrl: String = "", //下载地址
+        var content: String = "" //更新内容
+)

+ 7 - 0
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/O2AppUpdateBeanData.kt

@@ -0,0 +1,7 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo
+
+
+
+data class O2AppUpdateBeanData(
+        var android: O2AppUpdateBean? //android更新数据
+)

+ 14 - 0
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/utils/AndroidUtils.kt

@@ -223,6 +223,20 @@ object AndroidUtils {
         return version
     }
 
+    /**
+     * 获取当前应用的版本号
+     *
+     */
+    fun getAppVersionCode(context: Context): Int {
+        val versionCode: Int
+        try {
+            versionCode = context.packageManager.getPackageInfo(context.packageName, 0).versionCode
+        }catch (e: PackageManager.NameNotFoundException) {
+            throw java.lang.RuntimeException(this.javaClass.simpleName + " this application not found! ")
+        }
+        return versionCode
+    }
+
     /**
      * 实现文本复制功能
      * @param content

+ 0 - 124
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/utils/AppUpdateUtil.kt

@@ -1,124 +0,0 @@
-package net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils
-
-import android.app.Activity
-import android.content.Context
-import android.content.Intent
-import android.os.Build
-import android.support.v4.app.NotificationManagerCompat
-import com.pgyersdk.update.PgyUpdateManager
-import com.pgyersdk.update.UpdateManagerListener
-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.o2.DownloadAPKFragment
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.service.DownloadAPKService
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.PgyUpdateBean
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.widgets.dialog.O2AlertIconEnum
-import net.zoneland.x.bpm.mobile.v1.zoneXBPM.widgets.dialog.O2DialogSupport
-import java.lang.ref.WeakReference
-
-/**
- * Created by fancyLou on 22/03/2018.
- * Copyright © 2018 O2. All rights reserved.
- */
-
-
-class AppUpdateUtil(activity: Activity) {
-
-
-    private val weakReference: WeakReference<Activity> = WeakReference(activity)
-
-    private var versionName = ""
-    private var downloadUrl = ""
-
-    fun checkAppUpdate(noUpdateIsNotify: Boolean = false, callbackContinue:((flag: Boolean)->Unit)? = null) {
-        PgyUpdateManager.register(weakReference.get(), object : UpdateManagerListener() {
-            override fun onUpdateAvailable(p0: String?) {
-                XLog.debug("onUpdateAvailable $p0")
-                val bean = O2SDKManager.instance().gson.fromJson(p0, PgyUpdateBean::class.java)
-                val activity = weakReference.get()
-                versionName = bean.data.versionName
-                downloadUrl = bean.data.downloadURL
-                XLog.info("versionName:$versionName, downloadUrl:$downloadUrl")
-                if (bean != null && activity != null) {
-                    val currentversionName = AndroidUtils.getAppVersionName(activity)
-                    if (currentversionName != versionName) {
-                        O2DialogSupport.openConfirmDialog(activity, bean.data.releaseNote, listener = { _ ->
-                            XLog.info("notification is true..........")
-                            callbackContinue?.invoke(true)
-//                            toDownloadService(activity)
-                        }, icon = O2AlertIconEnum.UPDATE, negativeListener = {_->
-                            callbackContinue?.invoke(false)
-                        })
-
-                    } else {
-                        callbackContinue?.invoke(false)
-                        XLog.info("versionName is same , do not show dialog! versionName:$versionName ")
-                    }
-                }else {
-                    callbackContinue?.invoke(false)
-                }
-
-            }
-
-            override fun onNoUpdateAvailable() {
-                XLog.info("没有发现新版本!")
-                if (noUpdateIsNotify) {
-                    val activity = weakReference.get()
-                    if (activity != null) {
-                        XToast.toastShort(activity, "没有发现新版本!")
-                    }
-                }
-                callbackContinue?.invoke(false)
-            }
-        })
-    }
-
-    /**
-     * 是否开启通知
-     */
-    private fun isNotificationEnabled(context: Context): Boolean {
-        return try {
-            val manager = NotificationManagerCompat.from(context)
-            manager.areNotificationsEnabled()
-        } catch (e: Exception) {
-            e.printStackTrace()
-            false
-        }
-    }
-
-    private fun alertNotificationProcessBar(activity: Activity) {
-        O2DialogSupport.openConfirmDialog(activity, activity.getString(R.string.permission_notification),
-                listener = { _ ->
-                    //去设置通知权限
-                    AndroidUtils.gotoSettingApplication(activity)
-                },
-                negativeListener = { _ ->
-                    //跳过 不开启通知显示进度条
-                    toDownloadService(activity)
-                })
-
-    }
-
-    private fun toDownloadService(activity: Activity) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !activity.packageManager.canRequestPackageInstalls()) {// 8.0需要判断安装未知来源的权限
-            O2DialogSupport.openAlertDialog(activity, "非常抱歉,'安装未知应用' 权限未开通, 马上去设置", { _->
-                AndroidUtils.gotoSettingInstalls(activity)
-            })
-        } else {
-            downloadServiceStart(activity)
-//            callbackContinue?.invoke()
-        }
-
-
-    }
-
-    fun downloadServiceStart(activity: Activity) {
-        val intent = Intent(activity, DownloadAPKService::class.java)
-        intent.action = activity.packageName + DownloadAPKService.DOWNLOAD_SERVICE_ACTION
-        intent.putExtra(DownloadAPKService.VERSIN_NAME_EXTRA_NAME, versionName)
-        intent.putExtra(DownloadAPKService.DOWNLOAD_URL_EXTRA_NAME, downloadUrl)
-        activity.startService(intent)
-
-    }
-}

+ 0 - 99
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/utils/ZoneXBPMCrashHandler.java

@@ -1,99 +0,0 @@
-package net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils;
-
-import android.content.Context;
-import android.os.Looper;
-import android.widget.Toast;
-
-import com.pgyersdk.crash.PgyCrashManager;
-
-
-/**
- * 捕获android app crash
- * Created by FancyLou on 2016/3/3.
- */
-public class ZoneXBPMCrashHandler implements Thread.UncaughtExceptionHandler {
-
-    public static final String TAG = "CrashHandler";
-
-    // 系统默认的UncaughtException处理类
-    private Thread.UncaughtExceptionHandler mDefaultHandler;
-    private static ZoneXBPMCrashHandler instance = new ZoneXBPMCrashHandler();
-    // 程序的Context对象
-    private Context mContext;
-
-    private ZoneXBPMCrashHandler(){}
-
-    public static ZoneXBPMCrashHandler getInstance() {
-        return instance;
-    }
-
-    /**
-     * 初始化
-     *
-     * @param context
-     */
-    public void init(Context context) {
-        mContext = context;
-        // 获取系统默认的UncaughtException处理器
-        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
-        // 设置该CrashHandler为程序的默认处理器
-        Thread.setDefaultUncaughtExceptionHandler(this);
-        //注册蒲公英crash上报管理器
-        PgyCrashManager.register(mContext);
-    }
-
-    @Override
-    public void uncaughtException(Thread thread, Throwable ex) {
-        if (!handleException(ex) && mDefaultHandler != null) {
-            // 如果用户没有处理则让系统默认的异常处理器来处理
-            mDefaultHandler.uncaughtException(thread, ex);
-        } else {
-//            try {
-//                Thread.sleep(3000);
-//            } catch (InterruptedException e) {
-//                Log.e(TAG, "error : ", e);
-//            }
-//            XLog.error("异常捕获,重启应用中。。。。。。。。。。。。。。。。。。");
-//            Intent intent = new Intent(mContext, LaunchActivity.class);
-//            PendingIntent restartIntent = PendingIntent.getActivity(mContext.getApplicationContext(),
-//                    0,
-//                    intent,
-//                    PendingIntent.FLAG_CANCEL_CURRENT);
-//            AlarmManager mgr = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
-//            mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent);
-
-            XLog.error("异常捕获,结束应用。。。。。。。。。。。。。。。。。。。。。。。");
-            android.os.Process.killProcess(android.os.Process.myPid());
-            System.exit(0);//0表示正常退出 防止系统恢复档期crash的activity
-        }
-    }
-
-    /**
-     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
-     *
-     * @param ex
-     * @return true:如果处理了该异常信息;否则返回false.
-     */
-    private boolean handleException(Throwable ex) {
-        if (ex == null) {
-            return false;
-        }
-//        ex.printStackTrace();
-        XLog.error( "crash handler catch the exception......................", ex);
-        // 使用Toast来显示异常信息
-        new Thread() {
-            @Override
-            public void run() {
-                Looper.prepare();
-                Toast.makeText(mContext, "非常抱歉,程序出现未知异常,即将退出.", Toast.LENGTH_LONG)
-                        .show();
-                Looper.loop();
-            }
-        }.start();
-        // 将错误信息发送到蒲公英服务器
-        PgyCrashManager.reportCaughtException(mContext, new Exception(ex));
-
-        return true;
-    }
-
-}

+ 2 - 0
o2android/app/src/main/res/layout/activity_account_security.xml

@@ -173,6 +173,8 @@
     </LinearLayout>
 
         <LinearLayout
+            android:id="@+id/ll_account_security_bind_device_layout"
+            android:visibility="visible"
             android:orientation="vertical"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"

+ 24 - 0
o2android/app/src/main/res/layout/activity_cms_web_view_document.xml

@@ -68,6 +68,30 @@
                     android:visibility="gone"
                     android:onClick="publishDocument"
                     />
+                <TextView
+                    android:id="@+id/tv_cms_form_edit_btn"
+                    android:layout_height="match_parent"
+                    android:layout_width="0dp"
+                    android:layout_weight="1"
+                    android:text="@string/cms_work_form_edit"
+                    android:textColor="@color/z_color_primary"
+                    android:textSize="@dimen/font_large"
+                    android:gravity="center"
+                    android:visibility="gone"
+                    android:onClick="editDocument"
+                    />
+                <TextView
+                    android:id="@+id/tv_cms_form_save_btn"
+                    android:layout_height="match_parent"
+                    android:layout_width="0dp"
+                    android:layout_weight="1"
+                    android:text="@string/cms_work_form_save"
+                    android:textColor="@color/z_color_primary"
+                    android:textSize="@dimen/font_large"
+                    android:gravity="center"
+                    android:visibility="gone"
+                    android:onClick="saveDocument"
+                    />
 
             </LinearLayout>
         </FrameLayout>

+ 33 - 33
o2android/app/src/main/res/layout/fragment_main_settings.xml

@@ -243,40 +243,40 @@
                             android:visibility="visible"/>
                     </RelativeLayout>
 
-                    <View
-                        android:layout_width="match_parent"
-                        android:layout_height="1dp"
-                        android:background="@color/z_color_split_line_ddd"
-                        android:padding="0dp" />
+<!--                    <View-->
+<!--                        android:layout_width="match_parent"-->
+<!--                        android:layout_height="1dp"-->
+<!--                        android:background="@color/z_color_split_line_ddd"-->
+<!--                        android:padding="0dp" />-->
                     <!--反馈-->
-                    <RelativeLayout
-                        android:id="@+id/setting_button_feedback_id"
-                        android:layout_width="match_parent"
-                        android:layout_height="44dp"
-                        android:background="@drawable/white_background_selector">
-                        <ImageView
-                            android:id="@+id/setting_image_advice_icon"
-                            android:layout_width="22dp"
-                            android:layout_height="22dp"
-                            android:layout_centerVertical="true"
-                            android:src="@mipmap/icon_setting_feedback_22dp"
-                            android:layout_alignParentLeft="true"/>
-                        <TextView
-                            android:layout_width="match_parent"
-                            android:layout_height="wrap_content"
-                            android:layout_toRightOf="@id/setting_image_advice_icon"
-                            android:layout_centerVertical="true"
-                            android:layout_marginLeft="10dp"
-                            android:text="意见反馈"
-                            android:textSize="15sp"
-                            android:textColor="@color/z_color_text_primary_dark"/>
-                        <ImageView
-                            android:layout_width="22dp"
-                            android:layout_height="22dp"
-                            android:layout_alignParentRight="true"
-                            android:layout_centerVertical="true"
-                            android:src="@mipmap/icon_arrow_22dp"/>
-                    </RelativeLayout>
+<!--                    <RelativeLayout-->
+<!--                        android:id="@+id/setting_button_feedback_id"-->
+<!--                        android:layout_width="match_parent"-->
+<!--                        android:layout_height="44dp"-->
+<!--                        android:background="@drawable/white_background_selector">-->
+<!--                        <ImageView-->
+<!--                            android:id="@+id/setting_image_advice_icon"-->
+<!--                            android:layout_width="22dp"-->
+<!--                            android:layout_height="22dp"-->
+<!--                            android:layout_centerVertical="true"-->
+<!--                            android:src="@mipmap/icon_setting_feedback_22dp"-->
+<!--                            android:layout_alignParentLeft="true"/>-->
+<!--                        <TextView-->
+<!--                            android:layout_width="match_parent"-->
+<!--                            android:layout_height="wrap_content"-->
+<!--                            android:layout_toRightOf="@id/setting_image_advice_icon"-->
+<!--                            android:layout_centerVertical="true"-->
+<!--                            android:layout_marginLeft="10dp"-->
+<!--                            android:text="意见反馈"-->
+<!--                            android:textSize="15sp"-->
+<!--                            android:textColor="@color/z_color_text_primary_dark"/>-->
+<!--                        <ImageView-->
+<!--                            android:layout_width="22dp"-->
+<!--                            android:layout_height="22dp"-->
+<!--                            android:layout_alignParentRight="true"-->
+<!--                            android:layout_centerVertical="true"-->
+<!--                            android:src="@mipmap/icon_arrow_22dp"/>-->
+<!--                    </RelativeLayout>-->
 
                 </LinearLayout>
 

+ 2 - 0
o2android/app/src/main/res/values/strings.xml

@@ -631,6 +631,8 @@
     <string name="cms_start_create_title_hint">请输入文档标题</string>
     <string name="cms_start_create_identity">身份:</string>
     <string name="cms_work_form_publish">发    布</string>
+    <string name="cms_work_form_edit">编    辑</string>
+    <string name="cms_work_form_save">保    存</string>
 
 
     <!-- open im key -->

+ 2 - 2
o2android/gradle.properties

@@ -20,8 +20,8 @@ org.gradle.parallel=true
 
 
 # o2
-o2.versionName=5.0.2
-o2.versionCode=102
+o2.versionName=5.0.3
+o2.versionCode=103
 
 
 # sjgj

BIN
o2android/gradle/wrapper/gradle-wrapper.jar


+ 0 - 6
o2android/gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +0,0 @@
-#Mon Sep 26 11:35:59 CST 2016
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

+ 4 - 0
o2android/o2_auth_sdk/.gitignore

@@ -0,0 +1,4 @@
+/build
+.project
+.classpath
+.settings/

+ 86 - 0
o2android/o2_auth_sdk/build.gradle

@@ -0,0 +1,86 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+
+android {
+    compileSdkVersion 26
+    buildToolsVersion "27.0.3"
+
+
+
+    defaultConfig {
+        minSdkVersion 19
+        targetSdkVersion 26
+        versionCode 1
+        versionName "1.0"
+
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    implementation 'com.android.support:appcompat-v7:26.1.0'
+
+    //kotlin
+    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+
+    //http框架
+    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
+    implementation 'com.squareup.retrofit2:converter-gson:2.2.0'
+    implementation 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
+    implementation 'com.squareup.okhttp3:okhttp:3.11.0'
+    implementation 'io.reactivex:rxjava:1.1.6'
+    implementation 'io.reactivex:rxandroid:1.2.1'
+
+    implementation('com.github.bumptech.glide:glide:3.7.0') {
+        force = true
+    }
+}
+
+//添加以下方法
+//在 build/libs 目录下生成 makeKotlinJar.jar 文件
+// 这种方式生成的jar文件如果被kotlin app项目引用,则会出现kotlin库重复的错误,所以生成的jar
+//task makeJar(type: Jar) {
+//    delete('build/libs/o2_auth_sdk.jar')
+//    archiveName 'o2_auth_sdk.jar'
+//    //添加项目中java生成的class文件目录
+//    from('build/intermediates/classes/release/')
+//    //添加项目中kotlin生成的class文件目录
+//    from('build/tmp/kotlin-classes/release')
+////    添加Kotlin库(方法1)
+//    from {
+//        String[] include = [
+//                "kotlin-stdlib-${kotlin_version}.jar"
+//        ]
+//        configurations.compile
+//                .findAll { include.contains(it.name) }
+//                .collect { it.isDirectory() ? it : zipTree(it) }
+//    }
+//
+//    destinationDir = file('build/libs')
+//
+//    exclude('android/**')
+//
+//    include('**/**')
+//
+//}
+//
+//makeJar.dependsOn(build)
+
+// 将打包好的aar包拷贝到app下
+task copy2App(type: Copy) {
+    from 'build/outputs/aar/o2_auth_sdk-release.aar'
+    into '../app/libs'
+}
+
+copy2App.dependsOn(assemble)
+

+ 39 - 0
o2android/o2_auth_sdk/proguard-rules.pro

@@ -0,0 +1,39 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
+
+
+# 如果使用了Gson之类的工具要使被它解析的JavaBean类即实体类不被混淆。
+-keep class net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.** { *; }
+
+
+# 保持哪些类不被混淆
+-keep public class * extends android.app.Fragment
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+#如果有引用v4包可以添加下面这行
+-keep public class * extends android.support.v4.app.Fragment

+ 2 - 0
o2android/o2_auth_sdk/src/main/AndroidManifest.xml

@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.o2oa.o2_auth_sdk" />

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

@@ -0,0 +1,151 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM
+
+import android.content.Context
+import android.content.Intent
+
+/**
+ * Created by fancy on 2017/6/5.
+ */
+
+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"
+
+    /**
+     * 项目文件存储路径
+     * 根目录
+     */
+    val BASE_FILE_PATH = "ZONE_XBPM"
+
+    val BASE_APP_ALIAS = "XBPM"
+
+    val AVATAR_TMP_FOLDER = "avatar_temp"
+
+    val BASE_TMP_FOLDER = "temp"
+
+    val BASE_IM_RECI_FOLDER = "im"
+
+    val SKIN_FILE_FOLDER = "skin"
+
+    //流程附件目录
+    val BASE_WORK_ATTACH_FOLDER = "process"
+
+    val BASE_BBS_ATTACH_FOLDER = "bbs"
+
+    val BASE_MEETING_ATTACH_FOLDER = "meeting"
+
+    val BASE_CMS_ATTACH_FOLDER = "cms"
+
+    val BASE_LOG_FOLDER = "log"
+
+    val HTTP_CACHE_FOLDER = "ok_http_cache"
+
+    val FIRST_PAGE_TAG = "(0)"
+
+    /**
+     * 图片后缀
+     */
+    val IMAGE_SUFFIX_JPG = ".jpg"
+    val IMAGE_SUFFIX_PNG = ".png"
+
+    /**
+     * 默认分页 每页显示数据
+     */
+    val DEFAULT_PAGE_NUMBER = 15
+
+
+    /**
+     * 论坛内容中的图片展现宽度不超过720
+     */
+    val BBS_IMAGE_MAX_WIDTH = 720
+
+    /**
+     * 清除临时文件的任务id
+     */
+    val O2_CLEAR_TEMP_FILE_JOB_ID = 1024
+    val O2_COLLECT_LOG_JOB_ID = 1025
+
+
+    /**
+     * 消息id
+     */
+    val NOTIFYID = 19840523
+
+
+    val NOTIFICATION_STRING = "通知"
+
+    /**
+     * choosePicture activity requestCode
+     */
+    val CHOOSE_PICTURE_REQUEST_CODE = 1110
+
+
+    val SETTING_MESSAGE_NOTICE_KEY = "SETTING_MESSAGE_NOTICE_KEY"//消息是否提醒 默认true
+    val SETTING_MESSAGE_NOTICE_SOUND_KEY = "SETTING_MESSAGE_NOTICE_SOUND_KEY"//消息提醒声音是否开启 默认true
+    val SETTING_MESSAGE_NOTICE_VIBRATE_KEY = "SETTING_MESSAGE_NOTICE_VIBRATE_KEY"//消息提醒震动是否开启 默认true
+
+
+    /**
+     * 热图
+     */
+    val SETTING_HOT_PICTURE_DEFAULT_SHOW_NUMBER = 5//首页广告热图默认显示数量
+    val DEFAULT_HOT_PICTURE_ID = "xbpm_hot_picture"//默认广告热图的id
+
+
+    val DEVICE_TYPE = "android"
+
+    val TOKEN_TYPE_ANONYMOUS = "anonymous"
+
+    /**
+     * 考勤审核人确定方式 如果是这个值 申诉的时候就需要选择身份
+     */
+    val ATTENDANCE_SETTING_AUDITOR_TYPE_NEED_CHOOSE_IDENTITY = "所属部门职务"
+    /**
+     * 申诉审批状态启用开关 启用
+     */
+    val ATTENDANCE_SETTING_APPEAL_ABLE_TRUE = "true"
+
+
+    //////////////////////////////////SharedPreferences KEY /////////////////////////////////////////////////
+
+    val PREFERENCE_FILE = "API_DISTRIBUTE_FILE"
+    val PRE_ASSEMBLESJSON_KEY = "ASSEMBLESJSON_KEY"
+    val PRE_WEBSERVERJSON_KEY = "WEBSERVERJSON_KEY"
+    val PRE_CENTER_HOST_KEY = "PRE_CENTER_HOST_KEY"//中心服务器地址
+    val PRE_CENTER_HTTP_PROTOCOL_KEY = "PRE_CENTER_HTTP_PROTOCOL_KEY"//中心服务器 HTTP协议
+    val PRE_CENTER_CONTEXT_KEY = "PRE_CENTER_CONTEXT_KEY"//中心服务器上下文
+    val PRE_CENTER_PORT_KEY = "PRE_CENTER_PORT_KEY"//中心服务器端口
+    val PRE_CENTER_URL_KEY = "PRE_CENTER_URL_KEY"
+    val PRE_BIND_UNIT_ID_KEY = "PRE_BIND_UNIT_ID_KEY"//绑定的公司的id unitId
+    val PRE_BIND_UNIT_KEY = "PRE_BIND_UNIT_KEY"//绑定的公司 unitName
+    val PRE_BIND_PHONE_KEY = "PRE_BIND_PHONE_KEY"//绑定手机号码
+    val PRE_BIND_PHONE_TOKEN_KEY = "PRE_BIND_PHONE_TOKEN_JPUSH_KEY"//绑定手机唯一编码 @date 2018-04-19 修改成极光推送
+
+    val PRE_DEVICE_DPI_KEY = "PRE_DEVICE_DPI_KEY"//手机分辨率
+
+    val PRE_LAUNCH_INTRODUCTION_KEY = "PRE_LAUNCH_INTRODUCTION_KEY"//启动页,首次安装介绍页面
+
+    val PREFERENCE_CONSTANCE_FILE = "PREFERENCE_CONSTANCE_FILE"
+    val PRE_UPDATE_REMIND_DAY = "PRE_UPDATE_REMIND_DAY"
+    val PRE_GUIDE_KEY = "guide_key"
+    val PRE_DEMO_ALERT_REMIND_DAY = "PRE_DEMO_ALERT_REMIND_DAY"
+
+    val PRE_IS_FIRST = "IS_FIRST_LOGIN"
+
+    val BUSINESS_TYPE_MESSAGE_CENTER = 0//信息中心
+    val BUSINESS_TYPE_WORK_CENTER = 1//工作中心
+
+
+    val SKIN_CHANGE_BROADCAST_ACTION_KEY = "net.zoneland.o2.skin.change"//改变皮肤广播的Action
+    val SKIN_CHANGE_BROAD_CAST_KEY = "skin_change_broad_cast_key"//改变皮肤发送广播的key
+
+
+
+    val O2_INDEX_OR_PORTAL = "O2_INDEX_OR_PORTAL"
+
+    val O2_CLIENT = "oa"
+
+
+}

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

@@ -0,0 +1,162 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM
+
+import android.content.Context
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.FileUtil
+import java.io.File
+import com.bumptech.glide.Glide
+import android.os.Looper
+
+
+
+/**
+ * 服务器自定义图片
+ * Created by fancyLou on 16/04/2018.
+ * Copyright © 2018 O2. All rights reserved.
+ */
+
+
+object O2CustomStyle {
+
+    const val CUSTOM_STYLE_JSON_KEY = "customStyleJsonKey"
+    //MARK - 自定义信息 更新hash
+    const val CUSTOM_STYLE_UPDATE_HASH_KEY = "customStyleUpdateHashKey"
+
+    //MARK - 移动端首页展现是默认的native 还是配置的portal门户页面
+    const val INDEX_TYPE_DEFAULT = "default"
+    const val INDEX_TYPE_PORTAL = "portal"
+
+    //MARK - 移动端首页展现类型的key
+    const val INDEX_TYPE_PREF_KEY = "customStyleIndexTypeKey"
+    const val INDEX_ID_PREF_KEY = "customStyleIndexIdKey"
+
+    const val extension_png = ".png"
+
+    //MARK - 缓存图片key
+    const val IMAGE_KEY_LAUNCH_LOGO = "launch_logo" //启动页logo图  关于页面用的也是这个图 195px    65dp
+    //首页底部菜单home按钮  114px   38dp
+    const val IMAGE_KEY_INDEX_BOTTOM_MENU_LOGO_FOCUS = "index_bottom_menu_logo_focus"
+    const val IMAGE_KEY_INDEX_BOTTOM_MENU_LOGO_BLUR = "index_bottom_menu_logo_blur"
+
+    const val IMAGE_KEY_LOGIN_AVATAR = "login_avatar" //登录页默认头像  225px  75dp
+
+    const val IMAGE_KEY_PEOPLE_AVATAR_DEFAULT = "people_avatar_default" //人员默认头像  120px  40dp
+
+    const val IMAGE_KEY_PROCESS_DEFAULT = "process_default"  //流程默认图标   90px  30dp
+
+    const val IMAGE_KEY_SETUP_ABOUT_LOGO = "setup_about_logo" //设置页 关于按钮 logo    66px  22dp
+
+
+    /**
+     * 启动 logo图地址
+     */
+    fun launchLogoImagePath(context: Context?): String? {
+        return if (context != null) {
+            FileUtil.appExternalImageDir(context)?.absolutePath + File.separator + IMAGE_KEY_LAUNCH_LOGO + extension_png
+        } else {
+            null
+        }
+    }
+
+    /**
+     * 首页底部Home focus 图地址
+     */
+    fun indexMenuLogoFocusImagePath(context: Context?): String? {
+        return if (context != null) {
+            FileUtil.appExternalImageDir(context)?.absolutePath + File.separator + IMAGE_KEY_INDEX_BOTTOM_MENU_LOGO_FOCUS + extension_png
+        } else {
+            null
+        }
+    }
+
+    /**
+     * 首页底部Home blur 图地址
+     */
+    fun indexMenuLogoBlurImagePath(context: Context?): String? {
+        return if (context != null) {
+            FileUtil.appExternalImageDir(context)?.absolutePath + File.separator + IMAGE_KEY_INDEX_BOTTOM_MENU_LOGO_BLUR + extension_png
+        } else {
+            null
+        }
+    }
+
+    /**
+     * 登录页头像 图地址
+     */
+    fun loginAvatarImagePath(context: Context?): String? {
+        return if (context != null) {
+            FileUtil.appExternalImageDir(context)?.absolutePath + File.separator + IMAGE_KEY_LOGIN_AVATAR + extension_png
+        } else {
+            null
+        }
+    }
+
+    /**
+     * 人员头像默认 图地址
+     */
+    fun peopleAvatarImagePath(context: Context?): String? {
+        return if (context != null) {
+            FileUtil.appExternalImageDir(context)?.absolutePath + File.separator + IMAGE_KEY_PEOPLE_AVATAR_DEFAULT + extension_png
+        } else {
+            null
+        }
+    }
+
+    /**
+     * 流程默认 图地址
+     */
+    fun processDefaultImagePath(context: Context?): String? {
+        return if (context != null) {
+            FileUtil.appExternalImageDir(context)?.absolutePath + File.separator + IMAGE_KEY_PROCESS_DEFAULT + extension_png
+        } else {
+            null
+        }
+    }
+
+    /**
+     * 设置页关于logo 图地址
+     */
+    fun setupAboutImagePath(context: Context?): String? {
+        return if (context != null) {
+            FileUtil.appExternalImageDir(context)?.absolutePath + File.separator + IMAGE_KEY_SETUP_ABOUT_LOGO + extension_png
+        } else {
+            null
+        }
+    }
+
+
+    // 切换更新服务器资源后需要清除缓存。。。。。。。。。
+
+    /**
+     * 清除图片磁盘缓存
+     */
+    fun clearImageDiskCache(context: Context) {
+        try {
+            if (Looper.myLooper() == Looper.getMainLooper()) {
+                Thread(Runnable {
+                    Glide.get(context).clearDiskCache()
+                }).start()
+            } else {
+                Glide.get(context).clearDiskCache()
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+
+    }
+
+    /**
+     * 清除图片内存缓存
+     */
+    fun clearImageMemoryCache(context: Context) {
+        try {
+            if (Looper.myLooper() == Looper.getMainLooper()) { //只能在主线程执行
+                Glide.get(context).clearMemory()
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+
+    }
+
+
+}

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

@@ -0,0 +1,595 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.SharedPreferences
+import android.text.TextUtils
+import android.util.Log
+import com.google.gson.Gson
+import com.google.gson.GsonBuilder
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.APIAddressHelper
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.RetrofitClient
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.enums.LaunchState
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.exception.NoBindException
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.exception.NoLoginException
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.AuthenticationInfoJson
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.CollectUnitData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.portal.PortalData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.SharedPreferencesHelper
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.edit
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.o2Subscribe
+import rx.Observable
+import rx.android.schedulers.AndroidSchedulers
+import rx.schedulers.Schedulers
+import java.lang.Exception
+import java.lang.RuntimeException
+
+/**
+ * Created by fancyLou on 2018/11/22.
+ * Copyright © 2018 O2. All rights reserved.
+ */
+
+
+class O2SDKManager private constructor()  {
+
+    val TAG = "O2SDKManager"
+
+    companion object {
+
+        @SuppressLint("StaticFieldLeak")
+        @Volatile
+        private var INSTANCE: O2SDKManager? = null
+
+        fun instance(): O2SDKManager {
+            if (INSTANCE == null) {
+                synchronized(O2SDKManager::class) {
+                    if (INSTANCE == null) {
+                        INSTANCE = O2SDKManager()
+                    }
+                }
+            }
+            return INSTANCE!!
+        }
+
+    }
+
+    private val CURRENT_PERSON_ID_KEY = "CURRENT_PERSON_ID_KEY"//用户 id
+    private val CURRENT_PERSON_DISTINGUISHED_KEY = "CURRENT_PERSON_DISTINGUISHED_KEY"//用户 唯一标识
+    private val CURRENT_PERSON_UPDATETIME_KEY = "CURRENT_PERSON_UPDATETIME_KEY"//用户最后更新时间
+    private val CURRENT_PERSON_GENDERTYPE_KEY = "CURRENT_PERSON_GENDERTYPE_KEY"//性别
+    private val CURRENT_PERSON_PINYIN_KEY = "CURRENT_PERSON_PINYIN_KEY"//拼音
+    private val CURRENT_PERSON_PINYININITIAL_KEY = "CURRENT_PERSON_PINYININITIAL_KEY"//拼音简写
+    private val CURRENT_PERSON_NAME_KEY = "CURRENT_PERSON_NAME_KEY"//姓名
+    private val CURRENT_PERSON_EMPLOYEE_KEY = "CURRENT_PERSON_EMPLOYEE_KEY"//员工号
+    private val CURRENT_PERSON_UNIQUE_KEY = "CURRENT_PERSON_UNIQUE_KEY"//
+    private val CURRENT_PERSON_CONTROLLERLIST_KEY = "CURRENT_PERSON_CONTROLLERLIST_KEY"//
+    private val CURRENT_PERSON_MAIL_KEY = "CURRENT_PERSON_MAIL_KEY"//邮箱地址
+    private val CURRENT_PERSON_QQ_KEY = "CURRENT_PERSON_QQ_KEY"//我的qq
+    private val CURRENT_PERSON_WEIXIN_KEY = "CURRENT_PERSON_WEIXIN_KEY"//微信号
+    private val CURRENT_PERSON_MOBILE_KEY = "CURRENT_PERSON_MOBILE_KEY"//手机号
+    private val CURRENT_PERSON_DEVICELIST_KEY = "CURRENT_PERSON_DEVICELIST_KEY"//
+    private val CURRENT_PERSON_SIGNATURE_KEY = "CURRENT_PERSON_SIGNATURE_KEY"//
+    private val CURRENT_PERSON_TOKEN_KEY = "CURRENT_PERSON_TOKEN_KEY"//登录的token
+    private val CURRENT_PERSON_ROLELIST_KEY = "CURRENT_PERSON_ROLELIST_KEY"//角色
+
+    /***********************当前登录的用户信息 */
+    var cId: String = ""//用户唯一标识
+    var distinguishedName: String = "" //用户唯一标识
+    var cUnique: String = "" //用户唯一标识
+    var cUpdateTime: String = ""
+    var cGenderType: String = ""
+    var cPinyin: String = ""
+    var cPinyinInitial: String = ""
+    var cName: String = ""
+    var cEmployee: String = ""
+    var cControllerList: String = ""
+    var cMail: String = ""
+    var cQq: String = ""
+    var cWeixin: String = ""
+    var cMobile: String = ""
+    var cDeviceList: String = ""
+    var cSignature: String = ""
+    var cRoleList: String = ""//角色
+    //扩展信息
+    var zToken: String = ""//用户登录的token
+
+
+
+    private lateinit var context: Context
+    private lateinit var spHelper: SharedPreferencesHelper
+    val gson: Gson by lazy { GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create() }
+
+    /**
+     * Application onCreate中初始化 context = ApplicationContext
+     */
+    fun init(context: Context) {
+        //初始化RetrofitClient
+        this.context = context
+        spHelper = SharedPreferencesHelper(context)
+
+        RetrofitClient.instance().init(context)
+        cId = prefs().getString(CURRENT_PERSON_ID_KEY, "")
+        distinguishedName = prefs().getString(CURRENT_PERSON_DISTINGUISHED_KEY, "")
+        cUpdateTime = prefs().getString(CURRENT_PERSON_UPDATETIME_KEY, "")
+        cGenderType = prefs().getString(CURRENT_PERSON_GENDERTYPE_KEY, "")
+        cPinyin = prefs().getString(CURRENT_PERSON_PINYIN_KEY, "")
+        cPinyinInitial = prefs().getString(CURRENT_PERSON_PINYININITIAL_KEY, "")
+        cName = prefs().getString(CURRENT_PERSON_NAME_KEY, "")
+        cEmployee = prefs().getString(CURRENT_PERSON_EMPLOYEE_KEY, "")
+        cUnique = prefs().getString(CURRENT_PERSON_UNIQUE_KEY, "")
+        cControllerList = prefs().getString(CURRENT_PERSON_CONTROLLERLIST_KEY, "")
+        cMail = prefs().getString(CURRENT_PERSON_MAIL_KEY, "")
+        cQq = prefs().getString(CURRENT_PERSON_QQ_KEY, "")
+        cWeixin = prefs().getString(CURRENT_PERSON_WEIXIN_KEY, "")
+        cMobile = prefs().getString(CURRENT_PERSON_MOBILE_KEY, "")
+        cDeviceList = prefs().getString(CURRENT_PERSON_DEVICELIST_KEY, "")
+        cSignature = prefs().getString(CURRENT_PERSON_SIGNATURE_KEY, "")
+        cRoleList = prefs().getString(CURRENT_PERSON_ROLELIST_KEY, "")
+        //扩展信息
+        zToken = prefs().getString(CURRENT_PERSON_TOKEN_KEY, "")//TOKEN
+
+
+    }
+
+    fun prefs(): SharedPreferences = spHelper.prefs()
+
+
+    /**
+     * 启动  整个启动过程,检查绑定 连接中心服务器 下载配置 登录
+     */
+    fun launch(deviceToken: String, showState:(state: LaunchState)->Unit) {
+
+        if (TextUtils.isEmpty(deviceToken)) {
+            Log.e(TAG,"没有deviceToken!")
+            showState(LaunchState.NoBindError)
+            return
+        }
+        val phone = prefs().getString(O2.PRE_BIND_PHONE_KEY, "")
+        val unit = prefs().getString(O2.PRE_BIND_UNIT_KEY, "")
+        if (TextUtils.isEmpty(phone) || TextUtils.isEmpty(unit)) {
+            Log.e(TAG,"没有绑定手机号码。。。。")
+            showState(LaunchState.NoBindError)
+            return
+        }
+        try {
+            val client = RetrofitClient.instance()
+            showState(LaunchState.ConnectO2Collect)
+            client.collectApi().checkBindDeviceNew(deviceToken, phone, unit, O2.DEVICE_TYPE)
+                    .subscribeOn(Schedulers.io())
+                    .observeOn(AndroidSchedulers.mainThread())
+                    .o2Subscribe {
+                        onNext {collectUnitRes->
+                            saveCollectInfo(collectUnitRes.data, showState)
+                        }
+                        onError { e, _ ->
+                            Log.e(TAG, "检查绑定异常", e)
+                            showState(LaunchState.NoBindError)
+                        }
+                    }
+        }catch (e: RuntimeException) {
+            Log.e(TAG, "catch到的异常", e)
+            showState(LaunchState.UnknownError)
+        }
+
+    }
+
+    /**
+     * 启动 内网使用版本
+     */
+    fun launchInner(serverJson: String, showState:(state: LaunchState)->Unit) {
+        if (TextUtils.isEmpty(serverJson)) {
+            showState(LaunchState.UnknownError)
+            return
+        }
+        try {
+            Observable.just(true)
+                    .subscribeOn(Schedulers.io())
+                    .flatMap {
+                        val server = gson.fromJson<CollectUnitData>(serverJson, CollectUnitData::class.java)
+                        Observable.just(server)
+                    }
+                    .observeOn(AndroidSchedulers.mainThread())
+                    .o2Subscribe {
+                        onNext { unit->
+                            saveCollectInfo(unit, showState)
+                        }
+                        onError { e, _ ->
+                            Log.e(TAG, "未知异常", e)
+                            showState(LaunchState.UnknownError)
+                        }
+                    }
+        }catch (e: Exception) {
+            Log.e(TAG, "catch到的异常", e)
+            showState(LaunchState.UnknownError)
+        }
+
+    }
+
+    /**
+     * 绑定信息存储
+     */
+    fun bindUnit(unit: CollectUnitData, phone: String, deviceToken: String) {
+        val url = APIAddressHelper.instance().getCenterUrl(unit.centerHost, unit.centerContext, unit.centerPort)
+        prefs().edit {
+            putString(O2.PRE_CENTER_URL_KEY, url)
+            putString(O2.PRE_CENTER_HTTP_PROTOCOL_KEY, unit.httpProtocol)
+            putString(O2.PRE_CENTER_HOST_KEY, unit.centerHost)
+            putString(O2.PRE_CENTER_CONTEXT_KEY, unit.centerContext)
+            putInt(O2.PRE_CENTER_PORT_KEY, unit.centerPort)
+            putString(O2.PRE_BIND_UNIT_ID_KEY, unit.id)
+            putString(O2.PRE_BIND_UNIT_KEY, unit.name)
+            putString(O2.PRE_BIND_PHONE_KEY, phone)
+            putString(O2.PRE_BIND_PHONE_TOKEN_KEY, deviceToken)
+        }
+    }
+
+    /**
+     * 清除绑定信息
+     */
+    fun clearBindUnit() {
+        prefs().edit {
+            putString(O2.PRE_CENTER_URL_KEY, "")
+            putString(O2.PRE_CENTER_HOST_KEY, "")
+            putString(O2.PRE_CENTER_HTTP_PROTOCOL_KEY, "")
+            putString(O2.PRE_CENTER_CONTEXT_KEY, "")
+            putInt(O2.PRE_CENTER_PORT_KEY, 0)
+            putString(O2.PRE_BIND_UNIT_ID_KEY, "")
+            putString(O2.PRE_BIND_UNIT_KEY, "")
+            putString(O2.PRE_BIND_PHONE_KEY, "")
+            putString(O2.PRE_BIND_PHONE_TOKEN_KEY, "")
+        }
+    }
+
+
+    private fun saveCollectInfo(unit: CollectUnitData, showState:(state: LaunchState)->Unit) {
+        Log.d(TAG, "unit: ${unit.centerHost}, port: ${unit.centerPort} , id: ${unit.id}")
+        val host = unit.centerHost
+        val newUrl = APIAddressHelper.instance().getCenterUrl(unit.centerHost, unit.centerContext, unit.centerPort)
+        O2SDKManager.instance().prefs().edit {
+            putString(O2.PRE_BIND_UNIT_ID_KEY, unit.id)
+            putString(O2.PRE_CENTER_URL_KEY, newUrl)
+            putString(O2.PRE_CENTER_HTTP_PROTOCOL_KEY, unit.httpProtocol)
+            putString(O2.PRE_CENTER_HOST_KEY, unit.centerHost)
+            putString(O2.PRE_CENTER_CONTEXT_KEY, unit.centerContext)
+            putInt(O2.PRE_CENTER_PORT_KEY, unit.centerPort)
+            putString(O2.PRE_BIND_UNIT_KEY, unit.name)
+        }
+        Log.d(TAG, "保存 服务器信息成功!!!!newUrl:$newUrl")
+        Log.d(TAG, "httpProtocol:${unit.httpProtocol}")
+        Log.d(TAG, "host:$host")
+        //更新http协议
+        RetrofitClient.instance().setO2ServerHttpProtocol(unit.httpProtocol)
+        APIAddressHelper.instance().setHttpProtocol(unit.httpProtocol)
+        /////////////////////////// 开始业务逻辑  ////////////////////////////////////
+
+        Log.d(TAG, "开始连接center......$newUrl")
+        showState(LaunchState.ConnectO2Server)
+        val client = RetrofitClient.instance()
+        val api = client.api(newUrl)
+        api.getWebserverDistributeWithSource(host)
+                .subscribeOn(Schedulers.io())
+                .flatMap { response->
+                    Log.d(TAG, "开始检查配置.....")
+                    showState(LaunchState.CheckMobileConfig)
+                    APIAddressHelper.instance().setDistributeData(response.data)
+                    api.getCustomStyleUpdateDate()
+                }
+                .flatMap { response->
+                    val hash = prefs().getString(O2CustomStyle.CUSTOM_STYLE_UPDATE_HASH_KEY, "")
+                            ?: ""
+                    val result = response.data.value
+                    Log.d(TAG, "检查配置newHash:$result , oldHash:$hash")
+                    if (hash == result) {
+                        Observable.just(false)
+                    } else {
+                        prefs().edit {
+                            putString(O2CustomStyle.CUSTOM_STYLE_UPDATE_HASH_KEY, result)
+                        }
+                        Observable.just(true)
+                    }
+                }.flatMap { flag->
+                    if (flag) {
+                        Log.d(TAG, "开始下载配置.....")
+                        showState(LaunchState.DownloadMobileConfig)
+                        var excep = false
+                        api.getCustomStyle()
+                                .subscribeOn(Schedulers.immediate())
+                                .o2Subscribe {
+                                    onNext {res->
+                                        val style = res.data
+                                        // 去除不需要显示的门户
+                                        val portalList = style.portalList
+                                        val newlist: ArrayList<PortalData> = ArrayList()
+                                        if (!portalList.isEmpty()) {
+                                            for (portal in portalList) {
+                                                if (portal.mobileClient) {
+                                                    newlist.add(portal)
+                                                }
+                                            }
+                                            style.portalList = newlist
+                                        }
+
+                                        val styleJson = gson.toJson(style)
+                                        prefs().edit {
+                                            putString(O2CustomStyle.CUSTOM_STYLE_JSON_KEY, styleJson)
+                                        }
+                                    }
+                                    onError { e, _ ->
+                                        Log.e(TAG, "下载配置文件出错", e)
+                                        excep = true
+                                    }
+                                }
+                        if (excep) {
+                            Observable.error<Boolean>(RuntimeException("下载配置文件出错"))
+                        }else {
+                            Observable.just(true)
+                        }
+                    }else {
+                        Observable.just(true)
+                    }
+                }.flatMap { flag ->
+                    Log.d(TAG, "开始登录......$flag")
+                    showState(LaunchState.AutoLogin)
+                    if (TextUtils.isEmpty(zToken)) {
+                        Observable.error<ApiResponse<AuthenticationInfoJson>>(NoLoginException("没有登录!"))
+                    }else {
+                        client.assembleAuthenticationApi().who(zToken)
+                    }
+                }
+                .observeOn(AndroidSchedulers.mainThread())
+                .o2Subscribe {
+                    onNext { who->
+                        val authentication = who.data
+                        if (authentication.name != O2.TOKEN_TYPE_ANONYMOUS) {
+                            if (TextUtils.isEmpty(authentication.token)) {
+                                Log.d(TAG, "开始登录过期了......")
+                                logoutCleanCurrentPerson()
+                                showState(LaunchState.NoLoginError)
+                            } else {
+                                setCurrentPersonData(authentication)
+                                showState(LaunchState.Success)
+                            }
+                        }else{
+                            Log.d(TAG, "开始登录过期了......")
+                            logoutCleanCurrentPerson()
+                            showState(LaunchState.NoLoginError)
+                        }
+                    }
+                    onError { e, _ ->
+                        Log.e(TAG, "", e)
+                        if (e is NoLoginException) {
+                            showState(LaunchState.NoLoginError)
+                        }else {
+                            showState(LaunchState.UnknownError)
+                        }
+                    }
+                }
+    }
+
+
+    /**
+     * 是否系统管理员
+     */
+    fun isAdministrator(): Boolean {
+        val roleList = this.cRoleList.split(",").map {
+            if (it.contains("@")) {
+                it.substring(0, it.indexOf("@")).toLowerCase()
+            } else {
+                it.toLowerCase()
+            }
+        }
+        fun isAdminRole(): Boolean = roleList.any { it == "manager" }
+        return this.cName == "xadmin" || isAdminRole()
+    }
+
+    /**
+     * 是否会议管理员
+     */
+    fun isMeetingAdministrator(): Boolean {
+        if (isAdministrator()) return true
+        val roleList = this.cRoleList.split(",").map {
+            if (it.contains("@")) {
+                it.substring(0, it.indexOf("@")).toLowerCase()
+            } else {
+                it.toLowerCase()
+            }
+        }
+        return roleList.any { it == "meetingmanager" }
+    }
+
+    /**
+     * 登录 加载用户信息
+     */
+    fun setCurrentPersonData(data: AuthenticationInfoJson) {
+        storagecId(data.id)
+        storageDistinguishedName(data.distinguishedName)
+        storagecUpdateTime(data.updateTime)
+        storagezToken(data.token)
+        storagecGenderType(data.genderType)
+        storagecPinyin(data.pinyin)
+        storagecPinyinInitial(data.pinyinInitial)
+        storagecName(data.name)
+        storagecEmployee(data.employee)
+        storagecUnique(data.unique)
+        storagecControllerList(data.controllerList.joinToString(","))
+        storagecMail(data.mail)
+        storagecQq(data.qq)
+        storagecWeixin(data.weixin)
+        storagecMobile(data.mobile)
+        storagecDeviceList(data.deviceList.joinToString(","))
+        storagecSignature(data.signature)
+        storagecRoleList(data.roleList.joinToString(","))
+    }
+
+    /**
+     * 登出 清空用户数据
+     */
+    fun logoutCleanCurrentPerson() {
+        storagecId("")
+        storageDistinguishedName("")
+        storagecUnique("")
+        storagecUpdateTime("")
+        storagezToken("")
+        storagecGenderType("")
+        storagecPinyin("")
+        storagecPinyinInitial("")
+        storagecName("")
+        storagecEmployee("")
+        storagecControllerList("")
+        storagecMail("")
+        storagecQq("")
+        storagecWeixin("")
+        storagecMobile("")
+        storagecDeviceList("")
+//        storagecIcon("")
+        storagecSignature("")
+        storagecRoleList("")
+    }
+
+
+    fun storagecRoleList(cRoleList: String) {
+        if (this.cRoleList == cRoleList) {
+            return
+        }
+        this.cRoleList = cRoleList
+        prefs().edit().putString(CURRENT_PERSON_ROLELIST_KEY, cRoleList).apply()
+    }
+
+    fun storagezToken(zToken: String) {
+        if (this.zToken == zToken) {
+            return
+        }
+        this.zToken = zToken
+        prefs().edit().putString(CURRENT_PERSON_TOKEN_KEY, zToken).apply()
+    }
+
+    fun storagecId(cId: String) {
+        if (this.cId == cId) {
+            return
+        }
+        this.cId = cId
+        prefs().edit().putString(CURRENT_PERSON_ID_KEY, cId).apply()
+    }
+
+    fun storageDistinguishedName(distinguishedName: String) {
+        if (this.distinguishedName == distinguishedName) {
+            return
+        }
+        this.distinguishedName = distinguishedName
+        prefs().edit().putString(CURRENT_PERSON_DISTINGUISHED_KEY, distinguishedName).apply()
+    }
+
+    fun storagecUpdateTime(cUpdateTime: String) {
+        if (this.cUpdateTime == cUpdateTime) {
+            return
+        }
+        this.cUpdateTime = cUpdateTime
+        prefs().edit().putString(CURRENT_PERSON_UPDATETIME_KEY, cUpdateTime).apply()
+    }
+
+    fun storagecGenderType(cGenderType: String) {
+        if (this.cGenderType == cGenderType) {
+            return
+        }
+        this.cGenderType = cGenderType
+        prefs().edit().putString(CURRENT_PERSON_GENDERTYPE_KEY, cGenderType).apply()
+    }
+
+    fun storagecPinyin(cPinyin: String) {
+        if (this.cPinyin == cPinyin) {
+            return
+        }
+        this.cPinyin = cPinyin
+        prefs().edit().putString(CURRENT_PERSON_PINYIN_KEY, cPinyin).apply()
+    }
+
+    fun storagecPinyinInitial(cPinyinInitial: String) {
+        if (this.cPinyinInitial == cPinyinInitial) {
+            return
+        }
+        this.cPinyinInitial = cPinyinInitial
+        prefs().edit().putString(CURRENT_PERSON_PINYININITIAL_KEY, cPinyinInitial).apply()
+    }
+
+    fun storagecName(cName: String) {
+        if (this.cName == cName) {
+            return
+        }
+        this.cName = cName
+        prefs().edit().putString(CURRENT_PERSON_NAME_KEY, cName).apply()
+    }
+
+    fun storagecEmployee(cEmployee: String) {
+        if (this.cEmployee == cEmployee) {
+            return
+        }
+        this.cEmployee = cEmployee
+        prefs().edit().putString(CURRENT_PERSON_EMPLOYEE_KEY, cEmployee).apply()
+    }
+
+    fun storagecUnique(cUnique: String) {
+        if (this.cUnique == cUnique) {
+            return
+        }
+        this.cUnique = cUnique
+        prefs().edit().putString(CURRENT_PERSON_UNIQUE_KEY, cUnique).apply()
+    }
+
+    fun storagecControllerList(cControllerList: String) {
+        if (this.cControllerList == cControllerList) {
+            return
+        }
+        this.cControllerList = cControllerList
+        prefs().edit().putString(CURRENT_PERSON_CONTROLLERLIST_KEY, cControllerList).apply()
+    }
+
+    fun storagecMail(cMail: String) {
+        if (this.cMail == cMail) {
+            return
+        }
+        this.cMail = cMail
+        prefs().edit().putString(CURRENT_PERSON_MAIL_KEY, cMail).apply()
+    }
+
+    fun storagecQq(cQq: String) {
+        if (this.cQq == cQq) {
+            return
+        }
+        this.cQq = cQq
+        prefs().edit().putString(CURRENT_PERSON_QQ_KEY, cQq).apply()
+    }
+
+    fun storagecWeixin(cWeixin: String) {
+        if (this.cWeixin == cWeixin) {
+            return
+        }
+        this.cWeixin = cWeixin
+        prefs().edit().putString(CURRENT_PERSON_WEIXIN_KEY, cWeixin).apply()
+    }
+
+    fun storagecMobile(cMobile: String) {
+        if (this.cMobile == cMobile) {
+            return
+        }
+        this.cMobile = cMobile
+        prefs().edit().putString(CURRENT_PERSON_MOBILE_KEY, cMobile).apply()
+    }
+
+    fun storagecDeviceList(cDeviceList: String) {
+        if (this.cDeviceList == cDeviceList) {
+            return
+        }
+        this.cDeviceList = cDeviceList
+        prefs().edit().putString(CURRENT_PERSON_DEVICELIST_KEY, cDeviceList).apply()
+    }
+
+    fun storagecSignature(cSignature: String) {
+        if (this.cSignature == cSignature) {
+            return
+        }
+        this.cSignature = cSignature
+        prefs().edit().putString(CURRENT_PERSON_SIGNATURE_KEY, cSignature).apply()
+    }
+
+}

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

@@ -0,0 +1,295 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api
+
+import android.text.TextUtils
+import android.util.Log
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2SDKManager
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.enums.APIDistributeTypeEnum
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.APIAssemblesData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.APIDataBean
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.APIDistributeData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.APIWebServerData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.DateHelper
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.extension.edit
+
+/**
+ * Created by fancy on 2017/6/5.
+ */
+
+class APIAddressHelper private constructor() {
+
+    companion object {
+        private var INSTANCE: APIAddressHelper? = null
+        fun instance(): APIAddressHelper {
+            if (INSTANCE == null) {
+                INSTANCE = APIAddressHelper()
+                INSTANCE?.loadDistributeData()
+            }
+            return INSTANCE!!
+        }
+    }
+
+
+    val webSocketHead = "ws://"
+    var httpHead = "http://"
+
+    val apiDistribute: HashMap<APIDistributeTypeEnum, APIDataBean> = HashMap()
+    var webServerData: APIWebServerData? = null
+
+
+    /**
+     * 设置服务器协议
+     * @param httpProtocol http https
+     */
+    fun setHttpProtocol(httpProtocol:String) {
+        httpHead = "$httpProtocol://"
+    }
+
+    fun getCenterUrl(host: String, context: String, port: Int): String {
+        return if (context.contains("/")) {
+            "$httpHead$host:$port$context/"
+        } else {
+            "$httpHead$host:$port/$context/"
+        }
+    }
+
+    /**
+     * 临时地址
+     */
+    fun getDownloadPuppy2018SkinUrl(): String {
+//        return webServerData?.let {
+//            "$httpHead${webServerData?.host}:${webServerData?.port}/"
+//        } ?: ""
+        return "http://dev.o2oa.io/"
+    }
+
+    fun getFaceppServerUrl(): String {
+        return webServerData?.let {
+            "http://${webServerData?.host}:8888/x_faceset_control/"
+        } ?: ""
+    }
+
+    /**
+     * 待办 待阅等任务的网页打开地址
+     */
+    fun getWorkUrlPre(): String {
+        return webServerData?.let {
+            "$httpHead${webServerData?.host}:${webServerData?.port}/x_desktop/workmobilewithaction.html?workid=%s"
+        } ?: ""
+    }
+
+    /**
+     * 已经完成的任务待办打开
+     */
+    fun getWorkCompletedUrl(): String {
+        return webServerData?.let {
+            "$httpHead${webServerData?.host}:${webServerData?.port}/x_desktop/workmobilewithaction.html?workcompletedid=%s"
+        } ?: ""
+    }
+
+    /**
+     * 查看帖子的url
+     * @param subjectId 帖子id
+     * @param page 评论页数
+     */
+    fun getBBSWebViewUrl(subjectId: String, page: Int): String {
+        return webServerData?.let {
+            "$httpHead${webServerData?.host}:${webServerData?.port}/x_desktop/forumdocMobile.html?id=$subjectId&page=$page"
+        } ?: ""
+    }
+
+    /**
+     * 论坛附件下载地址
+     * jaxrs/attachment/download/${attachmentId}/stream/true
+     */
+    fun getBBSAttachmentURL(attachmentId: String): String {
+        return webServerData?.let {
+            getAPIDistribute(APIDistributeTypeEnum.x_bbs_assemble_control) + "jaxrs/attachment/download/$attachmentId/stream/true"
+        } ?: ""
+    }
+
+    /**
+     * cms 文章地址
+     */
+    fun getCMSWebViewUrl(docId: String): String {
+        return webServerData?.let {
+            "$httpHead${webServerData?.host}:${webServerData?.port}/x_desktop/cmsdocMobile.html?id=$docId"
+        } ?: ""
+    }
+
+    /**
+     * 热图图片地址
+     * http://host:port/x_file_assemble_control/jaxrs/file/${pId}/download/stream
+     */
+    fun getHotPictureUrl(pid: String): String {
+        return getAPIDistribute(APIDistributeTypeEnum.x_file_assemble_control) + "jaxrs/file/$pid/download/stream"
+    }
+
+
+    /**
+     * 新版用户头像地址
+     */
+    fun getPersonAvatarUrlWithId(id:String, withTimeSuffix:Boolean = false): String {
+        var url =  getAPIDistribute(APIDistributeTypeEnum.x_organization_assemble_control) + "jaxrs/person/$id/icon"
+        if (withTimeSuffix){
+            url += "?" + DateHelper.nowByFormate("MMddHHmmss")
+        }
+        return url
+    }
+
+    /**
+     * 用户头像地址 没有权限的
+     */
+    fun getPersonAvatarUrlWithoutPermission(id: String, withTimeSuffix:Boolean = false): String {
+        var url = getAPIDistribute(APIDistributeTypeEnum.x_organization_assemble_personal) + "jaxrs/icon/$id"
+        if (withTimeSuffix){
+            url += "?" + DateHelper.nowByFormate("MMddHHmmss")
+        }
+        return url
+    }
+
+    /**
+     * 门户打开地址
+     */
+    fun getPortalWebViewUrl(portalId:String): String {
+        return webServerData?.let {
+            "$httpHead${webServerData?.host}:${webServerData?.port}/x_desktop/appMobile.html?app=portal.Portal&status={\"portalId\":\"$portalId\"}"
+        } ?: ""
+    }
+
+    /**
+     * 门户icon地址
+     */
+    fun getPortalIconUrl(portalId: String, withTimeSuffix:Boolean = false): String {
+        var url = getAPIDistribute(APIDistributeTypeEnum.x_portal_assemble_surface) + "jaxrs/portal/$portalId/icon"
+        if (withTimeSuffix){
+            url += "?" + DateHelper.nowByFormate("MMddHHmmss")
+        }
+        return url
+    }
+
+    fun getWebViewHost(): String {
+        return webServerData?.let { webServerData?.host } ?: ""
+    }
+
+    /**
+     * web服务器地址 如:http://dev.o2oa.io:80
+     */
+    fun getWebServerUrl():String {
+        return "$httpHead${webServerData?.host}:${webServerData?.port}/"
+    }
+
+    fun setDistributeData(distributeData: APIDistributeData) {
+        val data = distributeData.assembles
+        val webData = distributeData.webServer
+        if (data == null || webData == null) {
+            throw RuntimeException("Assembles or webServer is null")
+        }
+
+        val dataJson = O2SDKManager.instance().gson.toJson(data)
+        val webDataJson = O2SDKManager.instance().gson.toJson(webData)
+        if (TextUtils.isEmpty(dataJson) || TextUtils.isEmpty(webDataJson)) {
+            throw RuntimeException("Assembles or webServer parse json error")
+        }
+        val oldDataJson = O2SDKManager.instance().prefs().getString(O2.PRE_ASSEMBLESJSON_KEY, "")
+        val oldWebDataJson = O2SDKManager.instance().prefs().getString(O2.PRE_WEBSERVERJSON_KEY, "")
+        if (dataJson != oldDataJson || webDataJson != oldWebDataJson) {
+            O2SDKManager.instance().prefs().edit {
+                putString(O2.PRE_ASSEMBLESJSON_KEY, dataJson)
+                putString(O2.PRE_WEBSERVERJSON_KEY, webDataJson)
+            }
+        }
+        setData(data, webData)
+    }
+
+    fun loadDistributeData() {
+        Log.i("APIAddress", "loadDistributeData.........................")
+        val oldDataJson = O2SDKManager.instance().prefs().getString(O2.PRE_ASSEMBLESJSON_KEY, "")
+        val oldWebDataJson = O2SDKManager.instance().prefs().getString(O2.PRE_WEBSERVERJSON_KEY, "")
+        val httpProtocol = O2SDKManager.instance().prefs().getString(O2.PRE_CENTER_HTTP_PROTOCOL_KEY, "")
+        if (!TextUtils.isEmpty(oldDataJson) && !TextUtils.isEmpty(oldWebDataJson)) {
+            try {
+                if (!TextUtils.isEmpty(httpProtocol)){
+                    setHttpProtocol(httpProtocol)
+                }
+                val data = O2SDKManager.instance().gson.fromJson<APIAssemblesData>(oldDataJson, APIAssemblesData::class.java)
+                val webData = O2SDKManager.instance().gson.fromJson<APIWebServerData>(oldWebDataJson, APIWebServerData::class.java)
+                setData(data, webData)
+            } catch (e: Exception) {
+            }
+        }
+    }
+
+
+    fun setData(data: APIAssemblesData, webData: APIWebServerData) {
+        webServerData = webData
+        if(data.x_file_assemble_control != null) {
+            apiDistribute[APIDistributeTypeEnum.x_file_assemble_control] = data.x_file_assemble_control
+        }
+        if(data.x_meeting_assemble_control != null) {
+            apiDistribute[APIDistributeTypeEnum.x_meeting_assemble_control] = data.x_meeting_assemble_control
+        }
+        if(data.x_attendance_assemble_control != null) {
+            apiDistribute[APIDistributeTypeEnum.x_attendance_assemble_control] = data.x_attendance_assemble_control
+        }
+        if(data.x_okr_assemble_control != null) {
+            apiDistribute[APIDistributeTypeEnum.x_okr_assemble_control] = data.x_okr_assemble_control
+        }
+        if(data.x_bbs_assemble_control != null) {
+            apiDistribute[APIDistributeTypeEnum.x_bbs_assemble_control] = data.x_bbs_assemble_control
+        }
+        if(data.x_cms_assemble_control != null) {
+            apiDistribute[APIDistributeTypeEnum.x_cms_assemble_control] = data.x_cms_assemble_control
+        }
+        if(data.x_hotpic_assemble_control != null) {
+            apiDistribute[APIDistributeTypeEnum.x_hotpic_assemble_control] = data.x_hotpic_assemble_control
+        }
+        if(data.x_organization_assemble_control != null) {
+            apiDistribute[APIDistributeTypeEnum.x_organization_assemble_control] = data.x_organization_assemble_control
+        }
+        if(data.x_collaboration_assemble_websocket != null) {
+            apiDistribute[APIDistributeTypeEnum.x_collaboration_assemble_websocket] = data.x_collaboration_assemble_websocket
+        }
+        if(data.x_organization_assemble_custom != null) {
+            apiDistribute[APIDistributeTypeEnum.x_organization_assemble_custom] = data.x_organization_assemble_custom
+        }
+        if(data.x_processplatform_assemble_surface != null) {
+            apiDistribute[APIDistributeTypeEnum.x_processplatform_assemble_surface] = data.x_processplatform_assemble_surface
+        }
+        if(data.x_organization_assemble_express != null) {
+            apiDistribute[APIDistributeTypeEnum.x_organization_assemble_express] = data.x_organization_assemble_express
+        }
+        if(data.x_organization_assemble_personal != null) {
+            apiDistribute[APIDistributeTypeEnum.x_organization_assemble_personal] = data.x_organization_assemble_personal
+        }
+        if(data.x_component_assemble_control != null) {
+            apiDistribute[APIDistributeTypeEnum.x_component_assemble_control] = data.x_component_assemble_control
+        }
+        if(data.x_organization_assemble_authentication != null) {
+            apiDistribute[APIDistributeTypeEnum.x_organization_assemble_authentication] = data.x_organization_assemble_authentication
+        }
+        if(data.x_portal_assemble_surface != null) {
+            apiDistribute[APIDistributeTypeEnum.x_portal_assemble_surface] = data.x_portal_assemble_surface
+        }
+        if(data.x_calendar_assemble_control != null) {
+            apiDistribute[APIDistributeTypeEnum.x_calendar_assemble_control] = data.x_calendar_assemble_control
+        }
+        if(data.x_mind_assemble_control != null) {
+            apiDistribute[APIDistributeTypeEnum.x_mind_assemble_control] = data.x_mind_assemble_control
+        }
+        if(data.x_jpush_assemble_control != null) {
+            apiDistribute[APIDistributeTypeEnum.x_jpush_assemble_control] = data.x_jpush_assemble_control
+        }
+
+    }
+
+    fun getAPIDistribute(typeEnum: APIDistributeTypeEnum): String {
+        var bean = apiDistribute[typeEnum]
+        return if (typeEnum == APIDistributeTypeEnum.x_collaboration_assemble_websocket) {
+            bean?.let { "$webSocketHead${it.host}:${it.port}${it.context}/" } ?: ""
+        } else {
+            bean?.let { "$httpHead${it.host}:${it.port}${it.context}/" } ?: ""
+        }
+
+    }
+}

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

@@ -0,0 +1,59 @@
+package net.muliba.accounting.app
+
+
+import android.content.Context
+import android.util.Log
+import android.widget.Toast
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2SDKManager
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiErrorResponse
+import retrofit2.adapter.rxjava.HttpException
+import rx.functions.Action1
+import java.net.ConnectException
+import java.net.SocketTimeoutException
+import java.util.concurrent.TimeoutException
+
+/**
+ * Created by fancy on 2017/5/12.
+ */
+
+class ExceptionHandler(val context: Context?,
+                       val onFailure: (Throwable) -> Unit) : Action1<Throwable> {
+
+
+    override fun call(t: Throwable) {
+        when (t) {
+            is TimeoutException -> showConnectionErrorMessage()
+            is SocketTimeoutException -> showConnectionErrorMessage()
+            is ConnectException -> showConnectionErrorMessage()
+            is HttpException -> showO2ErrorMessage(t)
+            else -> Log.e("ExceptionHandler", "", t)
+        }
+
+        onFailure(t)
+    }
+
+    private fun showO2ErrorMessage(exception:HttpException) {
+        val buffer = StringBuffer()
+        buffer.append("响应代码:"+exception.code())
+        try {
+            val json = exception.response().errorBody()?.string()
+            Log.e("ExceptionHandler","http error body:$json")
+            val errorResponse = O2SDKManager.instance().gson.fromJson(json, ApiErrorResponse::class.java)
+            if (errorResponse!=null) {
+                buffer.append(", 反馈信息:"+errorResponse.message)
+            }
+        }catch (e1:Exception){
+            Log.e("ExceptionHandler","", e1)
+        }
+        if (context!=null){
+            Toast.makeText(context, buffer.toString(),  Toast.LENGTH_SHORT).show()
+        }
+
+    }
+
+    private fun showConnectionErrorMessage() {
+        if (context!=null) {
+            Toast.makeText(context, "网络连接异常,请检查您的网络连接是否正确!", Toast.LENGTH_SHORT).show()
+        }
+    }
+}

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

@@ -0,0 +1,29 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api
+
+import android.text.TextUtils
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2SDKManager
+import okhttp3.Interceptor
+import okhttp3.Response
+
+/**
+ * Created by fancy on 2017/6/5.
+ */
+
+class O2Interceptor : Interceptor {
+    override fun intercept(chain: Interceptor.Chain): Response {
+        val original = chain.request()
+        val originalHttpUrl = original.url()
+        val url = originalHttpUrl.newBuilder().addQueryParameter("o", (Math.random()*100).toString()).build()
+        val xToken = O2SDKManager.instance().zToken
+        val requestBuilder = original.newBuilder()
+        if (!TextUtils.isEmpty(xToken)) {
+            requestBuilder.addHeader("x-token", xToken)
+        }
+//        XLog.debug("url: $url")
+        val request = requestBuilder.addHeader("x-client", O2.DEVICE_TYPE)
+                .method(original.method(), original.body())
+                .url(url).build()
+        return chain.proceed(request)
+    }
+}

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

@@ -0,0 +1,15 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import rx.functions.Action1
+
+/**
+ * Created by fancy on 2017/6/7.
+ */
+
+class ResponseHandler<T>( val onHandler: (T) -> Unit) : Action1<ApiResponse<T>>  {
+
+    override fun call(t: ApiResponse<T>) {
+        onHandler(t.data)
+    }
+}

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

@@ -0,0 +1,493 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.text.TextUtils
+import com.google.gson.Gson
+import com.google.gson.GsonBuilder
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2SDKManager
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service.*
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.enums.APIDistributeTypeEnum
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.download.DownloadBean
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.download.DownloadProgressHandler
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.download.ProgressListener
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.download.ProgressResponseBody
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.HttpCacheUtil
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils.HttpsTrustManager
+import okhttp3.Interceptor
+import okhttp3.OkHttpClient
+import retrofit2.Retrofit
+import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
+import retrofit2.converter.gson.GsonConverterFactory
+import java.lang.NullPointerException
+import java.util.concurrent.TimeUnit
+
+
+/**
+ * Created by fancy on 2017/6/5.
+ */
+
+class RetrofitClient private constructor() {
+
+    companion object {
+
+        @SuppressLint("StaticFieldLeak")
+        private var INSTANCE: RetrofitClient? = null
+
+        fun instance(): RetrofitClient {
+            if (INSTANCE == null) {
+                INSTANCE = RetrofitClient()
+            }
+            return INSTANCE!!
+        }
+    }
+
+
+    private val gson: Gson by lazy { GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create() }
+    private val helper: APIAddressHelper by lazy { APIAddressHelper.instance() }
+    private lateinit var o2HttpClient: OkHttpClient
+    private lateinit var httpClientOutSide: OkHttpClient
+    private lateinit var context: Context
+
+
+    /*在Application onCreate 中初始化 */
+    fun init(context: Context) {
+        this.context = context
+        val httpProtocol = O2SDKManager.instance().prefs().getString(O2.PRE_CENTER_HTTP_PROTOCOL_KEY, "")
+        o2HttpClient = if (!TextUtils.isEmpty(httpProtocol) && httpProtocol == "https") {
+            OkHttpClient.Builder()
+                    .sslSocketFactory(HttpsTrustManager.createSSLSocketFactory())
+                    .hostnameVerifier { _, _ -> true }
+                    .cache(HttpCacheUtil.getOkHttpCacheInstance(context))
+                    .addInterceptor(O2Interceptor())
+                    .retryOnConnectionFailure(true)
+                    .connectTimeout(60, TimeUnit.SECONDS).build()
+        } else {
+            OkHttpClient.Builder()
+                    .cache(HttpCacheUtil.getOkHttpCacheInstance(context))
+                    .addInterceptor(O2Interceptor())
+                    .retryOnConnectionFailure(true)
+                    .connectTimeout(60, TimeUnit.SECONDS).build()
+        }
+        httpClientOutSide = OkHttpClient.Builder()
+                .cache(HttpCacheUtil.getOkHttpCacheInstance(context))
+                .connectTimeout(60, TimeUnit.SECONDS).build()
+    }
+
+
+    /**
+     * o2 http client
+     */
+    fun getO2HttpClient() : OkHttpClient? {
+        if (::o2HttpClient.isInitialized) {
+            return o2HttpClient
+        }
+        return null
+    }
+
+
+
+
+    /**
+     * 设置o2服务器的http协议
+     */
+    fun setO2ServerHttpProtocol(httpProtocol: String) {
+        o2HttpClient = if (httpProtocol == "https") {
+            OkHttpClient.Builder()
+                    .sslSocketFactory(HttpsTrustManager.createSSLSocketFactory())
+                    .hostnameVerifier { _, _ -> true }
+                    .cache(HttpCacheUtil.getOkHttpCacheInstance(context))
+                    .addInterceptor(O2Interceptor())
+                    .retryOnConnectionFailure(true)
+                    .connectTimeout(60, TimeUnit.SECONDS).build()
+        } else {
+            OkHttpClient.Builder()
+                    .cache(HttpCacheUtil.getOkHttpCacheInstance(context))
+                    .addInterceptor(O2Interceptor())
+                    .retryOnConnectionFailure(true)
+                    .connectTimeout(60, TimeUnit.SECONDS).build()
+        }
+    }
+
+
+    fun updateApiService(url: String, builder: OkHttpClient.Builder): PgyUpdateApiService {
+        val retrofit = Retrofit.Builder()
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .baseUrl(url)
+                .client(builder.build())
+                .build()
+        return retrofit.create(PgyUpdateApiService::class.java)
+    }
+
+    private val TULING123_BASE_URL = "http://www.tuling123.com/openapi/"
+
+    fun tuling123Service(): Tuling123Service {
+        val retrofit = Retrofit.Builder()
+                .baseUrl(TULING123_BASE_URL)
+                .client(httpClientOutSide)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(Tuling123Service::class.java)
+    }
+
+    /**
+     * @param baseUrl http://dev.o2oa.io:8888/x_faceset_control/
+     */
+    fun faceppApiService(baseUrl: String): FaceppApiService {
+        val retrofit = Retrofit.Builder()
+                .baseUrl(baseUrl)
+                .client(httpClientOutSide)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(FaceppApiService::class.java)
+    }
+
+    /**
+     * 下载皮肤服务
+     */
+    fun skinDownloadService(url: String, handler: DownloadProgressHandler): SkinDownLoadService {
+        val retrofit = Retrofit.Builder()
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .baseUrl(url)
+                .client(progressClient(handler).build())
+                .build()
+        return retrofit.create(SkinDownLoadService::class.java)
+    }
+
+    /**
+     * 带进度客户端
+     */
+    private fun progressClient(handler: DownloadProgressHandler): OkHttpClient.Builder {
+        val builder = OkHttpClient.Builder()
+        val listener = ProgressListener { progress, total, done ->
+            val bean = DownloadBean()
+            bean.bytesRead = progress
+            bean.contentLength = total
+            bean.isDone = done
+            handler.sendMessage(bean)
+        }
+        //添加拦截器,自定义ResponseBody,添加下载进度
+        builder.networkInterceptors()
+                .add(Interceptor { chain ->
+                    val xToken = O2SDKManager.instance().zToken
+                    val original = chain.request()
+                    val requestBuilder = original.newBuilder()
+                    if (!TextUtils.isEmpty(xToken)) {
+                        requestBuilder.addHeader("x-token", xToken)
+                    }
+                    val originalHttpUrl = original.url()
+                    val url = originalHttpUrl.newBuilder().addQueryParameter("o", (Math.random()*100).toString()).build()
+                    val request = requestBuilder.addHeader("x-client", O2.DEVICE_TYPE)
+                            .method(original.method(), original.body())
+                            .url(url).build()
+
+                    val originalResponse = chain.proceed(request)
+            originalResponse.newBuilder().body(
+                    ProgressResponseBody(originalResponse.body(), listener))
+                    .build()
+        })
+
+        return builder
+    }
+
+    /**
+     * o2platform 中心服务器
+     * @return
+     */
+    fun collectApi(): CollectService {
+        val retrofit = Retrofit.Builder()
+                .baseUrl(O2.O2_COLLECT_URL)
+                .client(httpClientOutSide)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(CollectService::class.java)
+    }
+
+    /**
+     * center服务 获取各个应用地址的服务
+     * @param baseUrl
+     * @return
+     */
+    fun api(baseUrl: String): ApiService {
+        val retrofit = Retrofit.Builder()
+                .baseUrl(baseUrl)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(ApiService::class.java)
+    }
+
+
+    /**
+     * 门户模块
+     */
+    fun portalAssembleSurfaceService(): PortalAssembleSurfaceService? {
+        return try {
+            val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_portal_assemble_surface)
+            val retrofit = Retrofit.Builder()
+                    .baseUrl(url)
+                    .client(o2HttpClient)
+                    .addConverterFactory(GsonConverterFactory.create(gson))
+                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                    .build()
+            retrofit.create(PortalAssembleSurfaceService::class.java)
+        } catch (e: Exception) {
+            null
+        }
+    }
+
+
+    /**
+     * 新版人员组织管理
+     */
+    fun organizationAssembleControlApi(): OrganizationAssembleControlAlphaService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_organization_assemble_control)
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(OrganizationAssembleControlAlphaService::class.java)
+
+    }
+
+
+    /**
+     * 查询模块
+     */
+    fun queryAssembleSurfaceServiceAPI(): QueryAssembleSurfaceService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_query_assemble_surface)
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(QueryAssembleSurfaceService::class.java)
+
+    }
+
+
+
+    /**
+     * 人员管理
+     * @return
+     */
+    fun assemblePersonalApi(): OrgAssemblePersonalService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_organization_assemble_personal)
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(OrgAssemblePersonalService::class.java)
+    }
+
+
+    /**
+     * 认证
+     * @return
+     */
+    fun assembleAuthenticationApi(): OrgAssembleAuthenticationService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_organization_assemble_authentication)
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(OrgAssembleAuthenticationService::class.java)
+    }
+
+    /**
+     * 组织
+     * @return
+     */
+    fun assembleExpressApi(): OrgAssembleExpressService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_organization_assemble_express)
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(OrgAssembleExpressService::class.java)
+    }
+
+    /**
+     * 流程
+     * @return
+     */
+    fun processAssembleSurfaceServiceAPI(): ProcessAssembleSurfaceService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_processplatform_assemble_surface)
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(ProcessAssembleSurfaceService::class.java)
+    }
+
+    /**
+     * 云盘
+     * @return
+     */
+    fun fileAssembleControlApi(): FileAssembleControlService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_file_assemble_control)
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(FileAssembleControlService::class.java)
+    }
+
+    /**
+     * 新版云盘服务
+     *
+     */
+    fun cloudFileControlApi(): CloudFileControlService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_file_assemble_control)
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(CloudFileControlService::class.java)
+    }
+
+    /**
+     * 会议室管理
+     * @return
+     */
+    fun meetingAssembleControlApi(): MeetingAssembleControlService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_meeting_assemble_control)
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(MeetingAssembleControlService::class.java)
+    }
+
+    /**
+     * 考勤管理
+     * @return
+     */
+    fun attendanceAssembleControlApi(): AttendanceAssembleControlService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_attendance_assemble_control)
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(AttendanceAssembleControlService::class.java)
+    }
+
+    /**
+     * 论坛
+     * @return
+     */
+    fun bbsAssembleControlServiceApi(): BBSAssembleControlService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_bbs_assemble_control)
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                //                .addConverterFactory(MyGsonConverterFactory.create(gson))
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(BBSAssembleControlService::class.java)
+    }
+
+    /**
+     * 热图
+     * @return
+     */
+    fun hotpicAssembleControlServiceApi(): HotpicAssembleControlService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_hotpic_assemble_control)
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(HotpicAssembleControlService::class.java)
+    }
+
+
+    /**
+     * 内容管理
+     * @return
+     */
+    fun cmsAssembleControlService(): CMSAssembleControlService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_cms_assemble_control)
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(CMSAssembleControlService::class.java)
+    }
+
+    /**
+     * 公共配置服务
+     * @return
+     */
+    fun organizationAssembleCustomService(): OrganizationAssembleCustomService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_organization_assemble_custom)
+        if (TextUtils.isEmpty(url)) {
+            throw NullPointerException("没有公共服务模块!!!!")
+        }
+        val retrofit = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofit.create(OrganizationAssembleCustomService::class.java)
+    }
+
+    /**
+     * 日程
+     */
+    fun calendarAssembleControlService(): CalendarAssembleControlService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_calendar_assemble_control)
+        val retrofitClient = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofitClient.create(CalendarAssembleControlService::class.java)
+    }
+
+
+    fun jPushControlService(): JPushControlService {
+        val url = helper.getAPIDistribute(APIDistributeTypeEnum.x_jpush_assemble_control)
+        val retrofitClient = Retrofit.Builder()
+                .baseUrl(url)
+                .client(o2HttpClient)
+                .addConverterFactory(GsonConverterFactory.create(gson))
+                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+                .build()
+        return retrofitClient.create(JPushControlService::class.java)
+    }
+
+
+}

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

@@ -0,0 +1,38 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.APIDistributeData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.CustomStyleData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.CustomStyleUpdateData
+import retrofit2.http.GET
+import retrofit2.http.Path
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/6.
+ */
+
+interface ApiService {
+
+    /**
+     * 获取服务器分发地址
+     * @param source 访问的host 也就是外网地址
+     * *
+     * @return
+     */
+    @GET("jaxrs/distribute/webserver/assemble/source/{source}")
+    fun getWebserverDistributeWithSource(@Path("source") source: String): Observable<ApiResponse<APIDistributeData>>
+
+    /**
+     * 服务端 应用自定义图片样式获取
+     */
+    @GET("jaxrs/appstyle/current/style")
+    fun getCustomStyle(): Observable<ApiResponse<CustomStyleData>>
+
+    /**
+     * 服务端 应用自定义图片样式更新时间
+     */
+    @GET("jaxrs/appstyle/current/update")
+    fun getCustomStyleUpdateDate():  Observable<ApiResponse<CustomStyleUpdateData>>
+}

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

@@ -0,0 +1,165 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.IdData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.attendance.*
+import okhttp3.RequestBody
+import retrofit2.http.*
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/6.
+ */
+interface AttendanceAssembleControlService {
+
+
+    /**
+     * 获取当前用户的考勤周期
+     */
+    @GET("jaxrs/attendancestatisticalcycle/cycleDetail/{year}/{month}")
+    fun myAttendanceStatisticCycle(@Path("year") year: String, @Path("month") month: String):
+            Observable<ApiResponse<AttendanceStatisticCycle>>
+
+    /**
+     * 当月考勤明细列表
+     * @param filter
+     * *
+     * @param id
+     * *
+     * @param count
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/attendancedetail/filter/list/{id}/next/{count}")
+    fun myAttendanceDetailListByMonth(@Body filter: AttendanceDetailQueryFilterJson,
+                                      @Path("id") id: String, @Path("count") count: String): Observable<ApiResponse<List<AttendanceDetailInfoJson>>>
+
+    /**
+     * 当月考勤饼图数据
+     * @param filter
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/attendancedetail/filter/list/user")
+    fun myAttendanceDetailChartList(@Body filter: AttendanceDetailQueryFilterJson): Observable<ApiResponse<List<AttendanceDetailInfoJson>>>
+
+    /**
+     * 申诉审批状态启用开关.png
+     * @return  configValue = true
+     */
+    @GET("jaxrs/attendancesetting/code/APPEALABLE")
+    fun getAppealableValue(): Observable<ApiResponse<SettingInfoJson>>
+
+    /**
+     * 考勤审核人确定方式
+     * @return configValue = 所属部门职务 申诉的时候需要选择身份
+     */
+    @GET("jaxrs/attendancesetting/code/APPEAL_AUDITOR_TYPE")
+    fun getAppealAuditorType(): Observable<ApiResponse<SettingInfoJson>>
+
+    /**
+     * 申诉申请表单提交
+     * @param data
+     * *
+     * @param id
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/attendanceappealInfo/appeal/{id}")
+    fun submitAppeal(@Body data: AttendanceDetailInfoJson, @Path("id") id: String): Observable<ApiResponse<BackInfoJson>>
+
+    /**
+     * 申诉审批列表 分页查询
+     * @param id    (0)
+     * *
+     * @param limit 每页显示数据
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/attendanceappealInfo/filter/list/{id}/next/{limit}")
+    fun findAttendanceAppealInfoListByPage(@Path("id") id: String, @Path("limit") limit: Int, @Body filter: AppealApprovalQueryFilterJson): Observable<ApiResponse<List<AppealInfoJson>>>
+
+    /**
+     * 考勤申诉审批提交
+     * @param id
+     * *
+     * @param body  同意:{"status":"1"} 不同意:{"status":"-1"}
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/attendanceappealInfo/process/{id}")
+    fun approvalAppealInfo(@Path("id") id: String, @Body body: Map<String, String>): Observable<ApiResponse<BackInfoJson>>
+
+
+    /**
+     * 考勤申诉审批提交
+     * @param body
+     */
+    @PUT("jaxrs/attendanceappealInfo/audit")
+    fun approvalAppealInfo(@Body body: AppealApprovalFormJson): Observable<ApiResponse<BackInfoJson>>
+
+    /**
+     * 打卡
+     * @param body  MobileCheckInJson
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/attendancedetail/mobile/recive")
+    fun attendanceDetailCheckIn(@Body body: RequestBody): Observable<ApiResponse<IdData>>
+
+    /**
+     * 分页查询手机端打卡记录
+
+     * @param body  MobileCheckInQueryFilterJson
+     * *
+     * @param page
+     * *
+     * @param count
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/attendancedetail/mobile/filter/list/page/{page}/count/{count}")
+    fun findAttendanceDetailMobileByPage(@Body body: RequestBody, @Path("page") page: Int, @Path("count") count: Int): Observable<ApiResponse<List<MobileCheckInJson>>>
+
+
+    /**
+     * 获取所有工作场所
+     * @return
+     */
+    @GET("jaxrs/workplace/list/all")
+    fun findAllWorkplace(): Observable<ApiResponse<List<MobileCheckInWorkplaceInfoJson>>>
+
+    /**
+     * 新增工作场所
+     * @param body  { "placeName":"场所名称", "longitude":"经度", "latitude":"纬度", "errorRange":100, "description":"说明备注"}
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/workplace")
+    fun attendanceWorkplace(@Body body: RequestBody): Observable<ApiResponse<IdData>>
+
+    /**
+     * 删除工作场所
+     * @param id
+     * *
+     * @return
+     */
+    @DELETE("jaxrs/workplace/{id}")
+    fun deleteAttendanceWorkplace(@Path("id") id: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 考勤管理员列表
+     * @return
+     */
+    @GET("jaxrs/attendanceadmin/list/all")
+    fun attendanceAdmin(): Observable<ApiResponse<List<AdministratorInfoJson>>>
+}

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

@@ -0,0 +1,149 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.IdData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.bbs.*
+import okhttp3.MultipartBody
+import okhttp3.RequestBody
+import okhttp3.ResponseBody
+import retrofit2.Call
+import retrofit2.http.*
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/6.
+ */
+
+interface BBSAssembleControlService {
+    /**
+     * 获取分区列表 以及 分区下所有板块
+
+     * @return
+     */
+    @GET("jaxrs/mobile/view/all")
+    fun forumAll(): Observable<ApiResponse<List<ForumInfoJson>>>
+
+
+    /**
+     * 某一个板块下 置顶帖列表
+
+     * @param sectionId
+     * *
+     * @return
+     */
+    @GET("jaxrs/subject/top/{sectionId}")
+    fun topSubjectListBySectionId(
+            @Path("sectionId") sectionId: String): Observable<ApiResponse<List<SubjectInfoJson>>>
+
+
+    /**
+     * 获取版块信息
+     * @param sectionId
+     * *
+     * @return
+     */
+    @GET("jaxrs/section/{sectionId}")
+    fun querySectionById(@Path("sectionId") sectionId: String): Observable<ApiResponse<SectionInfoJson>>
+
+    /**
+     * 分页查询帖子
+
+     * @param pageNumber
+     * *
+     * @param limit
+     * *
+     * @param body       {"sectionId":"1e532b82-f0a0-47b7-9d15-d1e10b4f915c"} 指定板块
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/subject/filter/list/page/{pageNumber}/count/{limit}")
+    fun subjectListByPage(
+            @Path("pageNumber") pageNumber: Int, @Path("limit") limit: Int, @Body body: RequestBody): Observable<ApiResponse<List<SubjectInfoJson>>>
+
+
+    /**
+     * 用户是否能发帖
+
+     * @param sectionId
+     * *
+     * @return
+     */
+    @GET("jaxrs/permission/subjectPublishable/{sectionId}")
+    fun subjectPublishableInSection(
+            @Path("sectionId") sectionId: String): Observable<ApiResponse<SubjectPublishPermissionCheckJson>>
+
+    /**
+     * 用户回帖权限
+
+     * @param subjectId
+     * *
+     * @return
+     */
+    @GET("jaxrs/permission/subject/{subjectId}")
+    fun replyAbleInSubject(@Path("subjectId") subjectId: String): Observable<ApiResponse<SubjectReplyPermissionCheckJson>>
+
+
+    /**
+     * 上传附件
+
+     * @param body
+     * *
+     * @return
+     */
+    @Multipart
+    @POST("jaxrs/attachment/upload/subject/{subjectId}")
+    fun uploadBBSSubjectAttachment(@Part body: MultipartBody.Part, @Part("site") site: RequestBody, @Path("subjectId") subjectId: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 发表帖子
+
+     * @param body SubjectPublishFormJson
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/user/subject")
+    fun publishSubject(@Body body: RequestBody): Observable<ApiResponse<IdData>>
+
+    /**
+     * 查询回复详细
+     * @param id
+     * *
+     * @return
+     */
+    @GET("jaxrs/reply/{id}")
+    fun getSubjectReplyInfo(@Path("id") id: String): Observable<ApiResponse<SubjectReplyInfoJson>>
+
+
+    /**
+     * 回复
+     * @param body ReplyFormJson
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/user/reply")
+    fun publishReply(@Body body: RequestBody): Observable<ApiResponse<IdData>>
+
+
+    /**
+     * 主题附件列表
+     * @param id
+     * *
+     * @return
+     */
+    @GET("jaxrs/subjectattach/list/subject/{id}")
+    fun getSubjectAttachList(@Path("id") id: String): Observable<ApiResponse<List<BBSSubjectAttachmentJson>>>
+
+
+    /**
+     * 附件下载
+     * @param attachId
+     * *
+     * @return
+     */
+    @GET("jaxrs/attachment/download/{id}/stream/{stream}")
+    fun downloadAttach(@Path("id") id: String,@Path("stream") stream: Boolean = true): Call<ResponseBody>
+}

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

@@ -0,0 +1,137 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.IdData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.cms.CMSApplicationInfoJson
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.cms.CMSCategoryInfoJson
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.cms.CMSDocumentAttachmentJson
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.cms.CMSDocumentInfoJson
+import okhttp3.MultipartBody
+import okhttp3.RequestBody
+import okhttp3.ResponseBody
+import retrofit2.Call
+import retrofit2.http.*
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/6.
+ */
+
+interface CMSAssembleControlService {
+
+
+    /**
+     * 查询有权限发布的应用和分类
+     */
+    @GET("jaxrs/appinfo/get/user/publish/{appId}")
+    fun canPublishCategories(@Path("appId") appId: String): Observable<ApiResponse<CMSApplicationInfoJson>>
+
+
+    /**
+     * 查询草稿
+     * @param filter {"categoryIdList":["36783507-3109-4701-a1bd-487e12340af5"],"creatorList":["楼国栋@louguodong@P"],"documentType":"全部"}
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/document/draft/list/(0)/next/1")
+    fun findDocumentDraftListWithCategory(@Body filter: RequestBody): Observable<ApiResponse<List<CMSDocumentInfoJson>>>
+
+
+    /**
+     * 保存文档
+     * @param body 启动的时候先创建一个草稿: {
+                "isNewDocument":true,
+                "title":"测试文档qqqq",
+                "creatorIdentity":"楼国栋@eaf80580-8ec7-43fc-b555-8863b47efa5f@I",
+                "appId":"fbc9c933-3dc4-4087-9b95-1ada4e30e1c9",
+                "categoryId":"cd29c6bc-e6f2-4987-bf39-d74db3b666e4",
+                "docStatus":"draft",
+                "categoryName":"qqqq",
+                "categoryAlias":"temp-qqqq"}
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/document")
+    fun documentPost(@Body body: RequestBody): Observable<ApiResponse<IdData>>
+
+    /**
+     * 内容管理应用列表
+     * @return
+     */
+    @GET("jaxrs/appinfo/list/user/view")
+    fun applicationList(): Observable<ApiResponse<List<CMSApplicationInfoJson>>>
+
+    /**
+     * 根据应用id查询 该应用下的分类列表
+     */
+    @GET("jaxrs/categoryinfo/list/publish/app/{appId}")
+    fun findCategorysByAppId(@Path("appId") appId: String): Observable<ApiResponse<List<CMSCategoryInfoJson>>>
+
+
+    /**
+     * 获取document列表
+     * @param filter   appIdList(专栏id)  categoryIdList(分类id)
+     * *
+     * @param lastId
+     * *
+     * @param count
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/document/filter/list/{lastId}/next/{count}")
+    fun filterDocumentList(@Body filter: RequestBody, @Path("lastId") lastId: String, @Path("count") count: Int): Observable<ApiResponse<List<CMSDocumentInfoJson>>>
+
+
+    /**
+     * 获取附件对象
+     * @param attachId 附件id
+     * @param documentId 文档id
+     */
+    @GET("jaxrs/fileinfo/{attachId}/document/{documentId}")
+    fun getDocumentAttachment(@Path("attachId") attachId: String, @Path("documentId") documentId: String): Observable<ApiResponse<CMSDocumentAttachmentJson>>
+
+    /**
+     * 获取文章的附件列表
+     * @param docId
+     * *
+     * @return
+     */
+    @GET("jaxrs/fileinfo/list/document/{docId}")
+    fun getDocumentAttachList(@Path("docId") docId: String): Observable<ApiResponse<List<CMSDocumentAttachmentJson>>>
+
+
+    /**
+     * 附件下载
+     * @param id 附件id
+     * *
+     * @return
+     */
+    @GET("jaxrs/fileinfo/download/document/{id}/stream")
+    fun downloadAttach(@Path("id") id: String): Call<ResponseBody>
+
+    /**
+     * 附件上传
+     * @param body
+     * *
+     * @param site
+     * *
+     * @param docId 文档id
+     */
+    @Multipart
+    @POST("jaxrs/fileinfo/upload/document/{docId}")
+    fun uploadAttachment(@Part body: MultipartBody.Part, @Part("site") site: RequestBody, @Path("docId")docId : String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 替换附件
+     * @param body
+     * *
+     * @param attachmentId
+     * *
+     * @param docId
+     */
+    @Multipart
+    @POST("jaxrs/fileinfo/update/document/{docId}/attachment/{attachmentId}")
+    fun replaceAttachment(@Part body: MultipartBody.Part, @Path("attachmentId") attachmentId: String, @Path("docId") docId: String): Observable<ApiResponse<IdData>>
+
+
+}

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

@@ -0,0 +1,123 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.IdData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ValueData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ValueNumberData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.calendar.*
+import retrofit2.http.*
+import rx.Observable
+
+/**
+ * Created by fancyLou on 14/06/2018.
+ * Copyright © 2018 O2. All rights reserved.
+ */
+
+
+interface CalendarAssembleControlService {
+
+    /**
+     * 获取我的日历列表
+     */
+    @GET("jaxrs/calendar/list/my")
+    fun myCalendarList(): Observable<ApiResponse<MyCalendarData>>
+
+    /**
+     * 获取事件列表
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/event/list/filter")
+    fun filterCalendarEventList(@Body filter: CalendarEventFilterInfo):Observable<ApiResponse<CalendarEventResponseData>>
+
+    /**
+     * 日历新增
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/calendar")
+    fun saveCalendar(@Body post:CalendarPostData):  Observable<ApiResponse<IdData>>
+
+    /**
+     * 日历广场
+     */
+    @GET("jaxrs/calendar/list/public")
+    fun getPublicCalendarList(): Observable<ApiResponse<List<CalendarPostData>>>
+
+    /**
+     * 关注
+     */
+    @GET("jaxrs/calendar/follow/{id}")
+    fun followCalendar(@Path("id") id: String): Observable<ApiResponse<ValueData>>
+
+    /**
+     * 取消关注
+     */
+    @GET("jaxrs/calendar/follow/{id}/cancel")
+    fun followCalendarCancel(@Path("id") id: String): Observable<ApiResponse<ValueData>>
+
+
+
+    /**
+     * 获取日历对象
+     */
+    @GET("jaxrs/calendar/{id}")
+    fun getCalendar(@Path("id") id: String): Observable<ApiResponse<CalendarPostData>>
+
+    /**
+     * 删除日历
+     */
+    @DELETE("jaxrs/calendar/{id}")
+    fun deleteCalendar(@Path("id") id: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 保存日程事件
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/event")
+    fun saveCalendarEvent(@Body event: CalendarEventInfoData): Observable<ApiResponse<IdData>>
+
+    /**
+     * 修改
+     * jaxrs/event/update/single/3af8c0f5-49ac-4a24-9583-6d453a124096
+     * @return id:
+     *
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/event/update/single/{id}")
+    fun updateCalendarEventSingle(@Path("id") id: String ,@Body event: CalendarEventInfoData): Observable<ApiResponse<ValueNumberData>>
+
+    /**
+     * 修改重复事件  之后
+     * jaxrs/event/update/after/6dafa82b-993f-4443-bb7f-75f5fd29548b
+     * @return value:18
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/event/update/after/{id}")
+    fun updateCalendarEventAfter(@Path("id") id: String ,@Body event: CalendarEventInfoData): Observable<ApiResponse<ValueNumberData>>
+
+    /**
+     * 修改重复事件 全部
+     * jaxrs/event/update/all/b7d877b4-38b1-4e5f-bcb6-a78ae6595379
+     * @return value:18
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/event/update/all/{id}")
+    fun updateCalendarEventAll(@Path("id") id: String ,@Body event: CalendarEventInfoData): Observable<ApiResponse<ValueNumberData>>
+
+    /**
+     * 删除单个日程
+     */
+    @DELETE("jaxrs/event/single/{id}")
+    fun deleteCalendarEventSingle(@Path("id") id: String): Observable<ApiResponse<ValueNumberData>>
+
+    /**
+     * 删除重复日程的之后的日程
+     */
+    @DELETE("jaxrs/event/after/{id}")
+    fun deleteCalendarEventAfter(@Path("id") id: String): Observable<ApiResponse<ValueNumberData>>
+
+    /**
+     * 删除重复日程的全部日程
+     */
+    @DELETE("jaxrs/event/all/{id}")
+    fun deleteCalendarEventAll(@Path("id") id: String): Observable<ApiResponse<ValueNumberData>>
+}

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

@@ -0,0 +1,130 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.IdData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.yunpan.*
+import okhttp3.MultipartBody
+import okhttp3.ResponseBody
+import retrofit2.Call
+import retrofit2.http.*
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/6.
+ */
+
+interface CloudFileControlService {
+
+
+    /**
+     * 顶层文件列表
+     */
+    @GET("jaxrs/attachment2/list/top")
+    fun listFileTop() : Observable<ApiResponse<List<FileJson>>>
+
+    /**
+     * 文件夹下的文件列表
+     */
+    @GET("jaxrs/attachment2/list/folder/{folderId}")
+    fun listFileByFolderId(@Path("folderId") folderId: String): Observable<ApiResponse<List<FileJson>>>
+
+    /**
+     * 顶层文件夹列表
+     */
+    @GET("jaxrs/folder2/list/top")
+    fun listFolderTop(): Observable<ApiResponse<List<FolderJson>>>
+
+    /**
+     * 文件夹下的文件夹列表
+     */
+    @GET("jaxrs/folder2/list/{folderId}")
+    fun listFolderByFolderId(@Path("folderId") folderId: String): Observable<ApiResponse<List<FolderJson>>>
+
+
+    /**
+     * 创建文件夹
+     *
+     * @param json name ,superior上级id (为空就是顶级)
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/folder2")
+    fun createFolder(@Body json: Map<String, String>): Observable<ApiResponse<IdData>>
+
+
+    /**
+     * 上传文件
+     * @param body
+     *
+     * @param folderId 顶级目录用:O2.FIRST_PAGE_TAG
+     */
+    @Multipart
+    @POST("jaxrs/attachment2/upload/folder/{folderId}")
+    fun uploadFile2Folder(@Part body: MultipartBody.Part, @Path("folderId") folderId: String): Observable<ApiResponse<IdData>>
+
+
+    /**
+     * 更新文件信息
+     * @param item
+     * *
+     * @param id
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/attachment2/{id}")
+    fun updateFile(@Body item: FileJson, @Path("id") id: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 删除文件
+     * @param id
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @DELETE("jaxrs/attachment2/{id}")
+    fun deleteFile(@Path("id") id: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 获取文件
+     */
+    @GET("jaxrs/attachment2/{id}")
+    fun getFile(@Path("id") id: String): Observable<ApiResponse<FileJson>>
+
+
+    /**
+     * 重命名文件夹
+     * @param folderId
+     * *
+     * @param folder
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/folder2/{folderId}")
+    fun updateFolder(@Path("folderId") folderId: String, @Body folder: FolderJson): Observable<ApiResponse<IdData>>
+
+    /**
+     * 删除文件夹
+     * @param folderId
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @DELETE("jaxrs/folder2/{folderId}")
+    fun deleteFolder(@Path("folderId") folderId: String): Observable<ApiResponse<IdData>>
+
+
+    /**
+     * 下载文件
+     * @param id
+     * *
+     * @return
+     */
+    @GET("jaxrs/attachment2/{id}/download/stream")
+    fun downloadFile(@Path("id") id: String): Call<ResponseBody>
+
+
+}

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

@@ -0,0 +1,105 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.APILogData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.IdData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ValueData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.CollectCodeData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.CollectDeviceData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.CollectUnitData
+import retrofit2.http.*
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/6.
+ */
+
+interface CollectService {
+
+    /**
+     * 给手机号码发送短信验证码
+     * @param data
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/code")
+    fun getCode(@Body data: CollectCodeData): Observable<ApiResponse<CollectCodeData>>
+
+    /**
+     * 根据手机号码和短信验证码获取单位列表
+     * @param phone
+     * *
+     * @param code
+     * *
+     * @return
+     */
+    @GET("jaxrs/unit/list/account/{phone}/code/{code}")
+    fun getUnitList(@Path("phone") phone: String, @Path("code") code: String): Observable<ApiResponse<List<CollectUnitData>>>
+
+    /**
+     * 绑定用户和设备
+     * @param body
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/device/account/bind")
+    fun bindDevice(@Body body: CollectDeviceData): Observable<ApiResponse<IdData>>
+
+    /**
+     * 解绑设备
+     * @param token
+     * *
+     * @return
+     */
+    @DELETE("jaxrs/device/name/{token}/unbind")
+    fun unBindDevice(@Path("token") token: String): Observable<ApiResponse<IdData>>
+
+
+    /**
+     * Unit下所有的Device
+     * @param unit 单位id
+     * @param account 账号 可以用手机号码
+     * @param token 当前手机的token,就是device name
+     */
+    @GET("jaxrs/device/list/unit/{unit}/account/{account}/device/{token}")
+    fun getBindDeviceList(@Path("unit") unit: String, @Path("account") account: String, @Path("token") token: String): Observable<ApiResponse<List<CollectDeviceData>>>
+
+    /**
+     * 检查绑定是否正确
+     * @param name
+     * *
+     * @param phone
+     * *
+     * @param unitName
+     *
+     * @return
+     */
+    @GET("jaxrs/unit/find/{unitName}/{phone}/{name}")
+    fun checkBindDevice(@Path("name") name: String, @Path("phone") phone: String, @Path("unitName") unitName: String): Observable<ApiResponse<CollectUnitData>>
+
+    /**
+     * 检查绑定是否正确
+     * @param name
+     * *
+     * @param phone
+     * *
+     * @param unitName
+     *
+     * @param deviceType
+     * *
+     * @return
+     */
+    @GET("jaxrs/unit/find/{unitName}/{phone}/{name}/{deviceType}")
+    fun checkBindDeviceNew(@Path("name") name: String, @Path("phone") phone: String, @Path("unitName") unitName: String, @Path("deviceType") deviceType:String): Observable<ApiResponse<CollectUnitData>>
+
+
+    /**
+     * 收集日志
+     */
+    @PUT("jaxrs/collect/applog/receive")
+    fun collectLog(@Body log: APILogData):Observable<ApiResponse<ValueData>>
+
+}

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

@@ -0,0 +1,26 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.face.FaceSearchResponse
+import okhttp3.MultipartBody
+import retrofit2.http.Multipart
+import retrofit2.http.POST
+import retrofit2.http.Part
+import retrofit2.http.Path
+import rx.Observable
+
+/**
+ * Created by fancyLou on 2018/10/11.
+ * Copyright © 2018 O2. All rights reserved.
+ */
+
+
+interface FaceppApiService {
+
+    /**
+     * http://dev.o2oa.io:8888/x_faceset_control/search/dev_o2oa_io
+     */
+    @Multipart
+    @POST("search/{faceset}")
+    fun searchFace(@Part body: MultipartBody.Part,  @Path("faceset") faceset: String): Observable<FaceSearchResponse>
+
+}

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

@@ -0,0 +1,179 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.IdData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.yunpan.*
+import okhttp3.MultipartBody
+import okhttp3.ResponseBody
+import retrofit2.Call
+import retrofit2.http.*
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/6.
+ */
+
+interface FileAssembleControlService {
+
+    /**
+     * 下载文件
+     * @param fileId
+     * *
+     * @return
+     */
+    @GET("jaxrs/attachment/{id}/download/stream")
+    fun downloadFile(@Path("id") id: String): Call<ResponseBody>
+
+    /**
+     * 上传文件
+     * @param body
+     * *
+     * @param folderName
+     */
+    @Multipart
+    @POST("jaxrs/attachment/upload/folder/{folderId}")
+    fun uploadFile2Folder(@Part body: MultipartBody.Part, @Path("folderId") folderId: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 上传文件
+     * @param body
+     */
+    @Multipart
+    @POST("jaxrs/attachment/upload/folder/{folderId}")
+    fun uploadFile2Root(@Part body: MultipartBody.Part,
+                        @Path("folderId") folderId: String = O2.FIRST_PAGE_TAG): Observable<ApiResponse<IdData>>
+
+    /**
+     * 上传文件到特定的业务模块区域
+     * @param referencetype 业务模块代号
+     * @param reference 业务关联id
+     * @param scale 缩放大小 比如800 :宽高比不变 大的那条边会压缩到小于等于800
+     */
+    @Multipart
+    @PUT("jaxrs/file/upload/referencetype/{referencetype}/reference/{reference}/scale/{scale}")
+    fun uploadFile2ReferenceZone(@Part body: MultipartBody.Part,
+                                 @Path("referencetype") referencetype: String,
+                                 @Path("reference") reference: String,
+                                 @Path("scale") scale: Int ): Observable<ApiResponse<IdData>>
+
+    /**
+     * 更新文件信息
+     * @param item
+     * *
+     * @param id
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/attachment/{id}")
+    fun updateFile(@Body item: FileJson, @Path("id") id: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 顶级文件列表
+     * @return
+     */
+    @GET("jaxrs/complex/top")
+    fun getFileTopList(): Observable<ApiResponse<YunpanJson>>
+
+    /**
+     * 获取某个文件夹下的文件列表
+
+     * @param folderName
+     * *
+     * @return
+     */
+    @GET("jaxrs/complex/folder/{folderName}")
+    fun getFileListByFolder(@Path("folderName") folderName: String): Observable<ApiResponse<YunpanJson>>
+
+
+    /**
+     * 创建文件夹
+     * json key:superior value:上级id (为空就是顶级)
+     * @param json
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/folder")
+    fun createFolder(@Body json: Map<String, String>): Observable<ApiResponse<IdData>>
+
+
+    /**
+     * 重命名文件夹
+     * @param folderId
+     * *
+     * @param folder
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/folder/{folderId}")
+    fun reNameFolder(@Path("folderId") folderId: String, @Body folder: FolderJson): Observable<ApiResponse<IdData>>
+
+    /**
+     * 删除文件夹
+     * @param folderName
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @DELETE("jaxrs/folder/{folderName}")
+    fun deleteFolder(@Path("folderName") folderName: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 重命名文件
+     * @param fileId
+     * *
+     * @param file
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/attachment/{fileId}")
+    fun reNameFile(@Path("fileId") fileId: String, @Body file: FileJson): Observable<ApiResponse<IdData>>
+
+    /**
+     * 删除文件
+     * @param fileName
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @DELETE("jaxrs/attachment/{fileName}")
+    fun deleteFile(@Path("fileName") fileName: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 接收列表顶级目录
+     * @return
+     */
+    @GET("jaxrs/editor/list")
+    fun getReceiveTopList(): Observable<ApiResponse<List<CooperationFolderJson>>>
+
+    /**
+     * 接收列表
+     * @param folder
+     * *
+     * @return
+     */
+    @GET("jaxrs/attachment/list/editor/{folder}")
+    fun getReceiveFileList(@Path("folder") folder: String): Observable<ApiResponse<List<CooperationFileJson>>>
+
+    /**
+     * 分享列表顶级目录
+     * @return
+     */
+    @GET("jaxrs/share/list")
+    fun getShareTopList(): Observable<ApiResponse<List<CooperationFolderJson>>>
+
+
+    /**
+     * 分享列表
+     * @param folder
+     * *
+     * @return
+     */
+    @GET("jaxrs/attachment/list/share/{folder}")
+    fun getShareFileList(@Path("folder") folder: String): Observable<ApiResponse<List<CooperationFileJson>>>
+}

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

@@ -0,0 +1,41 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.HotPictureBase64Data
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.HotPictureOutData
+import okhttp3.RequestBody
+import retrofit2.http.*
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/6.
+ */
+
+interface HotpicAssembleControlService {
+
+    /**
+     * 查询热图列表
+     * @param page
+     * *
+     * @param count
+     * *
+     * @param body  过滤条件{  application: 应用名称:CMS|BBS等等.  infoId: 信息ID .  title: 信息标题,模糊查询.}
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/user/hotpic/filter/list/page/{page}/count/{count}")
+    fun findHotPictureList(@Path("page") page: Int, @Path("count") count: Int, @Body
+    body: RequestBody): Observable<ApiResponse<List<HotPictureOutData>>>
+
+
+    /**
+     * 获取热图的base64字符串
+     * @param id
+     * *
+     * @return
+     */
+    @GET("jaxrs/user/hotpic/{id}")
+    fun loadPicBase64(@Path("id") id: String): Observable<ApiResponse<HotPictureBase64Data>>
+}

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

@@ -0,0 +1,29 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.JPushDeviceForm
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ValueData
+import retrofit2.http.*
+import rx.Observable
+
+
+interface JPushControlService {
+    /**
+     * 绑定设备到个人属性中
+     * @param body
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/device/bind")
+    fun deviceBind(@Body body: JPushDeviceForm) : Observable<ApiResponse<ValueData>>
+
+
+    /**
+     * 删除 绑定的设备号
+     * @param deviceName
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @DELETE("jaxrs/device/unbind/{deviceName}/android")
+    fun deviceUnBind(@Path("deviceName") deviceName: String): Observable<ApiResponse<ValueData>>
+}

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

@@ -0,0 +1,209 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.IdData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.meeting.BuildingInfoJson
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.meeting.MeetingInfoJson
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.meeting.RoomInfoJson
+import okhttp3.MultipartBody
+import okhttp3.RequestBody
+import okhttp3.ResponseBody
+import retrofit2.Call
+import retrofit2.http.*
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/6.
+ */
+
+interface MeetingAssembleControlService {
+
+    /**
+     * 获取所有大楼
+     * 包含大楼内会议室的列表
+     * @return
+     */
+    @GET("jaxrs/building/list")
+    fun listBuildings(): Observable<ApiResponse<List<BuildingInfoJson>>>
+
+    /**
+     * 根据start 和 completed 查询所有的会议室情况 是否空闲
+     * @param start yyyy-MM-dd HH:mm
+     * *
+     * @param completed yyyy-MM-dd HH:mm
+     * *
+     * @return
+     */
+    @GET("jaxrs/building/list/start/{start}/completed/{completed}")
+    fun listBuildingsByTime(@Path("start") start: String, @Path("completed") completed: String): Observable<ApiResponse<List<BuildingInfoJson>>>
+
+    /**
+     * 列示我参与的指定月份的会议,或者被邀请,或者是申请人.
+     * 按月
+     * @param year
+     * *
+     * @param month
+     * *
+     * @return
+     */
+    @GET("jaxrs/meeting/list/year/{year}/month/{month}")
+    fun findMyMeetingByMonth(@Path("year") year: String, @Path("month") month: String): Observable<ApiResponse<List<MeetingInfoJson>>>
+
+    /**
+     * 管理员权限 全部会议
+     * 列示我参与的指定月份的会议,或者被邀请,或者是申请人.
+     * 按月
+     * @param year
+     * *
+     * @param month
+     * *
+     * @return
+     */
+    @GET("jaxrs/meeting/list/year/{year}/month/{month}/all")
+    fun findMyMeetingByMonthAll(@Path("year") year: String, @Path("month") month: String): Observable<ApiResponse<List<MeetingInfoJson>>>
+    /**
+     * 列示我参与的指定日期的会议,或者被邀请,或者是申请人.
+     * 按日
+     * @param year
+     * *
+     * @param month
+     * *
+     * @param day
+     * *
+     * @return
+     */
+    @GET("jaxrs/meeting/list/year/{year}/month/{month}/day/{day}")
+    fun findMyMeetingByDay(@Path("year") year: String, @Path("month") month: String, @Path("day") day: String): Observable<ApiResponse<List<MeetingInfoJson>>>
+    /**
+     * 管理员权限 全部会议
+     * 列示我参与的指定日期的会议,或者被邀请,或者是申请人.
+     * 按日
+     * @param year
+     * *
+     * @param month
+     * *
+     * @param day
+     * *
+     * @return
+     */
+    @GET("jaxrs/meeting/list/year/{year}/month/{month}/day/{day}/all")
+    fun findMyMeetingByDayAll(@Path("year") year: String, @Path("month") month: String, @Path("day") day: String): Observable<ApiResponse<List<MeetingInfoJson>>>
+
+    /**
+     * 等待我确认是否参加的会议.
+     * @return
+     */
+    @GET("jaxrs/meeting/list/wait/accept")
+    fun myWaitAcceptMeetingList(): Observable<ApiResponse<List<MeetingInfoJson>>>
+
+    /**
+     * 接受会议邀请
+     * @param id
+     * *
+     * @return
+     */
+    @GET("jaxrs/meeting/{id}/accept")
+    fun acceptMeeting(@Path("id") id: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 拒绝会议邀请
+     * @param id
+     * *
+     * @return
+     */
+    @GET("jaxrs/meeting/{id}/reject")
+    fun rejectMeeting(@Path("id") id: String): Observable<ApiResponse<IdData>>
+
+
+    @GET("jaxrs/room/{id}")
+    fun getRoomById(@Path("id") id: String): Observable<ApiResponse<RoomInfoJson>>
+
+    /**
+     * 申请会议
+     * @param taskBody
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/meeting")
+    fun saveMeeting(@Body taskBody: RequestBody): Observable<ApiResponse<IdData>>
+
+    /**
+     * 保存会议材料
+     * @param id
+     * *
+     * @return
+     */
+    @Multipart
+    @POST("jaxrs/attachment/meeting/{meetingId}/upload/{summary}")
+    fun saveMeetingFile(@Part body: MultipartBody.Part,@Path("meetingId") id: String,
+                        @Path("summary") summary: Boolean = false): Observable<ApiResponse<IdData>>
+
+    /**
+     * 删除会议材料
+     * @param id
+     * *
+     * @return
+     */
+    @DELETE("jaxrs/attachment/{id}")
+    fun deleteMeetingFile(@Path("id") id: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 下载会议材料
+     * @param fileId
+     *
+     * @return
+     */
+    @GET("jaxrs/attachment/{id}/download/{stream}")
+    fun downloadMeetingFile(@Path("id") fileId: String,@Path("stream") stream: Boolean = true): Call<ResponseBody>
+
+    /**
+     * 更新会议
+     * @param taskBody
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/meeting/{id}")
+    fun updateMeeting(@Body taskBody: RequestBody, @Path("id") id: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 取消会议
+     * @param id
+     * *
+     * @return
+     */
+    @DELETE("jaxrs/meeting/{id}")
+    fun deleteMeeting(@Path("id") id: String): Observable<ApiResponse<IdData>>
+
+
+    /**
+     * 获取会议信息
+     * @param id
+     * *
+     * @return
+     */
+    @GET("jaxrs/meeting/{id}")
+    fun getMeetingById(@Path("id") id: String): Observable<ApiResponse<MeetingInfoJson>>
+
+    /**
+     * 获取全部会议室列表
+     */
+
+    @GET("jaxrs/room/list")
+    fun getAllMeetingRoomList(): Observable<ApiResponse<List<RoomInfoJson>>>
+
+    /**
+     * 我发起的未开始的会议.
+     * @return
+     */
+    @GET("jaxrs/meeting/list/applied/wait")
+    fun myOriginatorMeetingList(): Observable<ApiResponse<List<MeetingInfoJson>>>
+
+    /**
+     *根据大楼ID获取大楼信息
+     */
+    @GET("jaxrs/building/{id}")
+    fun getBuildingDetail(@Path("id") id : String): Observable<ApiResponse<BuildingInfoJson>>
+}

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

@@ -0,0 +1,84 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.IdData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ValueData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.AuthenticationInfoJson
+import retrofit2.http.*
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/6.
+ */
+
+
+interface OrgAssembleAuthenticationService{
+
+    /**
+     * 登陆
+     * @param json
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/authentication")
+    fun login(@Body json: Map<String, String>): Observable<ApiResponse<AuthenticationInfoJson>>
+
+
+    /**
+     * 人脸识别的时候登录: body = {"client":"oa","token":"6OH6cis+8Y9yrqBReLOB+XLCpatZAyVY+PY0cPj301s="}
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/sso")
+    fun sso(@Body body: Map<String, String>): Observable<ApiResponse<AuthenticationInfoJson>>
+
+
+    /**
+     * 检查当前用户
+     * @return
+     */
+    @GET("jaxrs/authentication")
+    fun who(@Header("x-token") token: String): Observable<ApiResponse<AuthenticationInfoJson>>
+
+    /**
+     * 用手机验证码登录
+     * @param json credential=xxxx,codeAnswer=xxxx,使用短信验证码登录.
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/authentication/code")
+    fun loginWithPhoneCode(@Body json: Map<String, String>): Observable<ApiResponse<AuthenticationInfoJson>>
+
+
+    /**
+     * 获取登录验证码
+     * @param credential
+     * *
+     * @return
+     */
+    @GET("jaxrs/authentication/code/credential/{credential}")
+    fun getPhoneCode(@Path("credential") credential: String): Observable<ApiResponse<ValueData>>
+
+
+    /**
+     * 扫一扫 确认登录
+     * @param meta
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/authentication/bind/meta/{meta}")
+    fun scanConfirmWebLogin(@Path("meta") meta: String): Observable<ApiResponse<AuthenticationInfoJson>>
+
+    /**
+     * 登出
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @DELETE("jaxrs/authentication")
+    fun logout(): Observable<ApiResponse<IdData>>
+
+
+}

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

@@ -0,0 +1,174 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.identity.IdentityJson
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.identity.IdentityLevelForm
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.identity.UnitDutyIdentityForm
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.person.PersonList
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.person.PersonUnitList
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.unit.UnitJson
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.o2.*
+import okhttp3.RequestBody
+import okhttp3.ResponseBody
+import retrofit2.Call
+import retrofit2.http.*
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/6.
+ */
+
+interface OrgAssembleExpressService {
+
+
+    /**
+     * 上下查询 某个人的所属组织 包括递归
+     * @param personList  如: {"personList":["楼国栋"]}
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/unit/list/person/sup/nested")
+    fun listUnitPersonSup(@Body personList: RequestBody): Observable<ApiResponse<PersonUnitList>>
+
+
+    /**
+     * 获取下级部门列表
+     * @param deptName
+     * *
+     * @return
+     */
+    @GET("jaxrs/complex/department/{deptName}")
+    fun getDepartmentSubList(@Path("deptName") deptName: String): Observable<ApiResponse<ContactDataBean>>
+
+    /**
+     * 查询个人的直接群组对象
+     * @param personName 姓名
+     * *
+     * @return
+     */
+    @GET("jaxrs/group/list/person/{personName}/sup/direct")
+    fun getPersonalGroupList(@Path("personName") personName: String): Observable<ApiResponse<List<PersonalGroupData>>>
+
+    /**
+     * 批量获取person的DN
+     * @param body {"personList":["4b9df3c7-c0fa-4b64-9f98-034da8bb8f92"]}
+     */
+    @POST("jaxrs/person/list")
+    fun searchPersonDNList(@Body personList: PersonList): Observable<ApiResponse<PersonList>>
+    /**
+     * 中文姓名模糊查询
+     * @param name 姓名
+     * *
+     * @return
+     */
+    @GET("jaxrs/person/list/like/{name}")
+    fun searchPersonByName(@Path("name") name: String): Observable<ApiResponse<List<SearchPersonData>>>
+
+    /**
+     * 分页查询人员
+     * 人员选择器使用
+     * @param lastId
+     * *
+     * @param limit
+     * *
+     * @return
+     */
+    @GET("jaxrs/person/list/{lastId}/next/{limit}")
+    fun searchPersonByPage(@Path("lastId") lastId: String, @Path("limit") limit: Int): Observable<ApiResponse<List<SearchPersonData>>>
+
+    /**
+     * 根据拼音或首字母查询通讯录
+     * @param name 拼音或者首字母
+     * *
+     * @return
+     */
+    @GET("jaxrs/person/list/like/pinyin/{name}")
+    fun searchPersonByPinyin(@Path("name") name: String): Observable<ApiResponse<List<SearchPersonData>>>
+
+    /**
+     * 查询群组详细
+     * 成员列表等
+     * @param groupName
+     * *
+     * @return
+     */
+    @GET("jaxrs/group/{groupName}")
+    fun getGroupInfoData(@Path("groupName") groupName: String): Observable<ApiResponse<PersonalGroupData>>
+
+    /**
+     * 获取个人详细信息
+     * 包含企业信息
+     * @param name
+     * *
+     * @return
+     */
+    @GET("jaxrs/complex/person/{name}")
+    fun getPersonInfoData(@Path("name") name: String): Observable<ApiResponse<PersonInfoData>>
+
+
+    /**
+     * 获取当前登录用户的部门公司等信息
+     * 放入本地存储 方便后续使用
+     * @param person
+     * *
+     * @return
+     */
+    @GET("jaxrs/department/list/person/{person}")
+    fun getLoginPersonDeptAndCompany(@Path("person") person: String): Observable<ApiResponse<List<PersonDeptData>>>
+
+
+    /**
+     * 获取用户属性
+     * @param attribute 如: 直接主管
+     * *
+     * @param person 如: 胡起
+     * *
+     * @return
+     */
+    @GET("jaxrs/personattribute/{attribute}/person/{person}")
+    fun personattribute(@Path("attribute") attribute: String, @Path("person") person: String): Observable<ApiResponse<PersonattributeData>>
+
+    /**
+     * 根据identity获取用户详细
+     * @param identity 如:胡起(开发部)
+     * *
+     * @return
+     */
+    @GET("jaxrs/person/identity/{identity}")
+    fun personIdentity(@Path("identity") identity: String): Observable<ApiResponse<PersonalData>>
+
+
+    /**
+     * 获取用户的身份
+     * @param person
+     * *
+     * @return
+     */
+    @GET("jaxrs/identity/list/person/{person}")
+    fun personIdentityByPerson(@Path("person") person: String): Observable<ApiResponse<List<PersonIdentityData>>>
+
+
+    /**
+     * 根据职务、组织查询身份列表
+     * @param body {"nameList":["测试职务"],"unit":"人力资源部@2812170000@U"}
+     */
+    @POST("jaxrs/unitduty/list/identity/unit/name/object")
+    fun identityListByUnitAndDuty(@Body body: UnitDutyIdentityForm): Observable<ApiResponse<List<IdentityJson>>>
+
+    /**
+     * 获取用户头像
+     * @param person
+     * *
+     * @return
+     */
+    @GET("servlet/icon/{person}")
+    @Headers("Content-Type: application/octet-stream")
+    fun loadPersonAvatar(@Path("person") person: String): Call<ResponseBody>
+
+    /**
+     * 根据身份查询和层级查询组织
+     * @param body identity level
+     */
+    @POST("jaxrs/unit/identity/level/object")
+    fun unitByIdentityAndLevel(@Body body: IdentityLevelForm): Observable<ApiResponse<UnitJson>>
+}

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

@@ -0,0 +1,48 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.IdData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ValueData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.person.PersonJson
+import okhttp3.MultipartBody
+import retrofit2.http.*
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/6.
+ */
+
+interface OrgAssemblePersonalService {
+
+    /**
+     * 当前登录用户详细信息
+     * @return
+     */
+    @GET("jaxrs/person")
+    fun getCurrentPersonInfo(): Observable<ApiResponse<PersonJson>>
+
+    /**
+     * 修改当前登录用户信息
+     * @param person
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/person")
+    fun modifyCurrentPerson(@Body person: PersonJson): Observable<ApiResponse<IdData>>
+
+    /**
+     * 修改用户头像
+     */
+    @Multipart
+    @PUT("jaxrs/person/icon")
+    fun modifyCurrentPersonIcon(@Part body: MultipartBody.Part): Observable<ApiResponse<ValueData>>
+
+
+    /**
+     * 获取会议配置
+     */
+    @GET("jaxrs/definition/meetingConfig")
+    fun getMeetingConfig() : Observable<ApiResponse<String>>
+}

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

@@ -0,0 +1,96 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.group.O2Group
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.identity.IdentityJson
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.person.PersonJson
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.person.PersonListLikeForm
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.unit.UnitJson
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.unit.UnitListForm
+import retrofit2.http.*
+import rx.Observable
+
+/**
+ * Created by fancy on 2017/7/10.
+ * Copyright © 2017 O2. All rights reserved.
+ */
+
+
+interface OrganizationAssembleControlAlphaService {
+
+    /**
+     * 列示顶层组织
+     */
+    @GET("jaxrs/unit/list/top")
+    fun unitListTop() : Observable<ApiResponse<List<UnitJson>>>
+
+    /**
+     * 列示某组织下的子组织列表
+     * @param unit 组织
+     */
+    @GET("jaxrs/unit/list/{unit}/sub/direct")
+    fun unitSubDirectList(@Path("unit") unit: String): Observable<ApiResponse<List<UnitJson>>>
+
+    /**
+     * 根据请求id返回组织列表
+     * @param body {"unitList":[]}
+     */
+    @POST("jaxrs/unit/list")
+    fun unitList(@Body body: UnitListForm): Observable<ApiResponse<List<UnitJson>>>
+
+
+    /**
+     * 根据组织类型查询组织, 如果没有组织类型 用上面两个接口 ,有组织类型就用这个接口
+     * body:{"type":"一级部门","unitList":[]}
+     */
+    @PUT("jaxrs/unit/list/unit/type")
+    fun unitListByType(@Body body: UnitListForm): Observable<ApiResponse<List<UnitJson>>>
+
+    /**
+     * 根据给定的人员,列示其所有的身份.
+     * @param person 人员
+     */
+    @GET("jaxrs/identity/list/person/{person}")
+    fun identityListWithPerson(@Path("person") person:String): Observable<ApiResponse<List<IdentityJson>>>
+
+    /**
+     * 列示某组织下的身份列表
+     * @param unit 组织
+     */
+    @GET("jaxrs/identity/list/unit/{unit}")
+    fun identityListWithUnit(@Path("unit") unit:String): Observable<ApiResponse<List<IdentityJson>>>
+
+
+    /**
+     * 个人详细信息
+     */
+    @GET("jaxrs/person/{person}")
+    fun person(@Path("person") person: String): Observable<ApiResponse<PersonJson>>
+
+    /**
+     * 模糊查询
+     * key 支持 中文 拼音等
+     */
+    @PUT("jaxrs/person/list/like")
+    fun personListLike(@Body body: PersonListLikeForm): Observable<ApiResponse<List<PersonJson>>>
+
+
+    /**
+     * 	查找人员所在的群组,包括嵌套的下级群组.
+     */
+    @GET("jaxrs/group/list/person/{person}/sup/nested")
+    fun groupListWithPerson(@Path("person") person: String): Observable<ApiResponse<List<O2Group>>>
+
+    /**
+     * 分页查询群组列表
+     */
+    @GET("jaxrs/group/list/{lastId}/next/{pageSize}")
+    fun groupListByPage(@Path("lastId") lastId: String, @Path("pageSize") pageSize: Int): Observable<ApiResponse<List<O2Group>>>
+
+    /**
+     * 分页查询人员
+     */
+    @GET("jaxrs/person/list/{lastId}/next/{pageSize}")
+    fun personListByPage(@Path("lastId") lastId: String, @Path("pageSize") pageSize: Int): Observable<ApiResponse<List<PersonJson>>>
+
+}

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

@@ -0,0 +1,17 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import retrofit2.http.GET
+import rx.Observable
+
+/**
+ * Created by 73419 on 2017/12/18 0018.
+ */
+interface OrganizationAssembleCustomService {
+
+    /**
+     * 获取会议配置
+     */
+    @GET("jaxrs/definition/meetingConfig")
+    fun getMeetingConfig() : Observable<ApiResponse<String>>
+}

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

@@ -0,0 +1,19 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import okhttp3.ResponseBody
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.Streaming
+import retrofit2.http.Url
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/5.
+ */
+
+interface PgyUpdateApiService {
+    @Streaming
+    @GET
+    fun apkDownload(@Url url: String): Observable<Response<ResponseBody>>
+}

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

@@ -0,0 +1,19 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.portal.PortalData
+import retrofit2.http.GET
+import rx.Observable
+
+/**
+ * Created by fancyLou on 2018/3/16.
+ * Copyright © 2018 O2. All rights reserved.
+ */
+
+
+interface PortalAssembleSurfaceService {
+
+
+    @GET("jaxrs/portal/list")
+    fun portalList(): Observable<ApiResponse<List<PortalData>>>
+}

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

@@ -0,0 +1,344 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.IdData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ValueData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.main.AttachmentInfo
+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.*
+import okhttp3.MultipartBody
+import okhttp3.RequestBody
+import okhttp3.ResponseBody
+import retrofit2.Call
+import retrofit2.http.*
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/6.
+ */
+
+interface ProcessAssembleSurfaceService {
+
+    /**
+     * 获取应用列表
+     * @return
+     */
+    @GET("jaxrs/application/list")
+    fun getApplicationList(): Observable<ApiResponse<List<ApplicationData>>>
+
+    /**
+     * 获取应用下的流程
+     * @param appId
+     * *
+     * @return
+     */
+    @GET("jaxrs/process/list/application/{appId}")
+    fun getApplicationProcess(@Path("appId") appId: String): Observable<ApiResponse<List<ProcessInfoData>>>
+
+    /**
+     * 获取应用列表 包含应用下的流程数据
+     * @return
+     */
+    @GET("jaxrs/application/list/complex")
+    fun getApplicationProcessList(): Observable<ApiResponse<List<ApplicationWithProcessData>>>
+
+
+    /**
+     * 获取当前流程的可用身份列表
+     */
+    @GET("jaxrs/process/list/available/identity/process/{processId}")
+    fun availableIdentityWithProcess(@Path("processId") processId:String): Observable<ApiResponse<List<ProcessWOIdentityJson>>>
+
+    /**
+     * 保存工作
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @PUT("jaxrs/data/work/{workId}")
+    fun saveTaskForm(@Body body: RequestBody, @Path("workId") workId: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 删除工作
+     */
+    @DELETE("jaxrs/work/{workId}")
+    fun deleteWorkForm(@Path("workId") workId: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 已阅列表
+     * @param lastId
+     * *
+     * @param limit
+     * *
+     * @return
+     */
+    @GET("jaxrs/readcompleted/list/{lastId}/next/{limit}")
+    fun getReadCompleteListByPage(@Path("lastId") lastId: String, @Path("limit") limit: Int): Observable<ApiResponse<List<ReadCompleteData>>>
+
+    @GET("jaxrs/readcompleted/list/{lastId}/next/{limit}/application/{applicationId}")
+    fun getReadCompleteListByPageWithApplication(@Path("lastId") lastId: String, @Path("limit") limit: Int, @Path("applicationId") applicationId: String): Observable<ApiResponse<List<ReadCompleteData>>>
+
+    /**
+     * 获取已阅的详细信息
+     * @param id
+     * *
+     * @return
+     */
+    @GET("jaxrs/readcompleted/{id}/reference")
+    fun getReadCompleteInfo(@Path("id") id: String): Observable<ApiResponse<ReadCompleteInfoData>>
+
+    /**
+     * 设为已阅
+     * @param id
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/read/{id}/processing")
+    fun setReadComplete(@Path("id") id: String, @Body readBody: RequestBody): Observable<ApiResponse<IdData>>
+
+    /**
+     * 待阅列表
+     * @param lastId
+     * *
+     * @param limit
+     * *
+     * @return
+     */
+    @GET("jaxrs/read/list/{lastId}/next/{limit}")
+    fun getReadListByPage(@Path("lastId") lastId: String, @Path("limit") limit: Int): Observable<ApiResponse<List<ReadData>>>
+
+    @GET("jaxrs/read/list/{lastId}/next/{limit}/application/{applicationId}")
+    fun getReadListByPageWithApplication(@Path("lastId") lastId: String, @Path("limit") limit: Int, @Path("applicationId") applicationId: String): Observable<ApiResponse<List<ReadData>>>
+
+    /**
+     * 待阅详细信息
+     * @param id read id
+     * *
+     * @return
+     */
+    @GET("jaxrs/read/{id}/reference")
+    fun getReadInfo(@Path("id") id: String): Observable<ApiResponse<ReadInfoData>>
+
+    /**
+     * 待阅信息
+     * @param readId
+     * *
+     * @return
+     */
+    @GET("jaxrs/read/{readId}")
+    fun getRead(@Path("readId") readId: String): Observable<ApiResponse<ReadData>>
+
+    /**
+     * 已办列表
+     * @param lastId
+     * *
+     * @param limit
+     * *
+     * @return
+     */
+    @GET("jaxrs/taskcompleted/list/{lastId}/next/{limit}")
+    fun getTaskCompleteListByPage(@Path("lastId") lastId: String, @Path("limit") limit: Int): Observable<ApiResponse<List<TaskCompleteData>>>
+
+    @GET("jaxrs/taskcompleted/list/{lastId}/next/{limit}/application/{applicationId}")
+    fun getTaskCompleteListByPageWithApplication(@Path("lastId") lastId: String, @Path("limit") limit: Int, @Path("applicationId") applicationId: String): Observable<ApiResponse<List<TaskCompleteData>>>
+
+    /**
+     * 搜索已办
+     * @param lastId
+     * *
+     * @param limit
+     * *
+     * @param body {"key":"关键字"}
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/taskcompleted/list/{lastId}/next/{limit}/filter")
+    fun searchTaskCompleteListByPage(@Path("lastId") lastId: String, @Path("limit") limit: Int, @Body body: RequestBody): Observable<ApiResponse<List<TaskCompleteData>>>
+
+    /**
+     * 已办详细信息
+     * @param id
+     * *
+     * @return
+     */
+    @GET("jaxrs/taskcompleted/{id}/reference")
+    fun getTaskCompleteInfo(@Path("id") id: String): Observable<ApiResponse<TaskCompleteInfoData>>
+
+
+
+    /**
+     * 已办详细信息
+     * @param id
+     * *
+     * @return
+     */
+    @GET("jaxrs/taskcompleted/{id}/reference/control")
+    fun getTaskCompleteInfoWithControl(@Path("id") id: String): Observable<ApiResponse<TaskCompleteInfoDataWithControl>>
+
+    /**
+     *
+     */
+    @GET("jaxrs/taskcompleted/list/count/application")
+    fun getTaskCompletedApplicationList(): Observable<ApiResponse<List<TaskApplicationData>>>
+
+    /**
+     * 获取应用列表
+     * @return
+     */
+    @GET("jaxrs/task/list/count/application")
+    fun getTaskApplicationList(): Observable<ApiResponse<List<TaskApplicationData>>>
+
+    /**
+     * 分页获取任务列表
+     * @param lastId (0) 第一条开始 、 传入最后一个任务id就是从这条任务开始
+     * *
+     * @param limit 每页展现数量
+     * *
+     * @return
+     */
+    @GET("jaxrs/task/list/{lastId}/next/{limit}")
+    fun getTaskListByPage(@Path("lastId") lastId: String, @Path("limit") limit: Int): Observable<ApiResponse<List<TaskData>>>
+
+    /**
+     * 应用内分页获取任务列表
+     * @param lastId (0) 第一条开始 、 传入最后一个任务id就是从这条任务开始
+     * *
+     * @param limit 每页展现数量
+     * *
+     * @param applicationId 应用id
+     * *
+     * @return
+     */
+    @GET("jaxrs/task/list/{lastId}/next/{limit}/application/{applicationId}")
+    fun getTaskListByPageWithApplication(@Path("lastId") lastId: String, @Path("limit") limit: Int, @Path("applicationId") applicationId: String): Observable<ApiResponse<List<TaskData>>>
+
+    /**
+     * 继续流转
+     * @param taskBody {'routeName': routeName, 'opinion': opinion}
+     * @param taskId 任务id
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/task/{taskId}/processing")
+    fun postTask(@Body taskBody: RequestBody, @Path("taskId") taskId: String): Observable<ApiResponse<List<WorkLog>>>
+
+
+    /**
+     * 神经网络自动处理任务
+     * @param taskBody type:神经网络类型 可以为空
+     * @param taskId 任务id
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/task/{taskId}/processing/neural")
+    fun postTaskNeural(@Body taskBody: RequestBody, @Path("taskId") taskId: String): Observable<ApiResponse<TaskNeuralResponseData>>
+
+    /**
+     * 获取task
+     * @param taskId
+     * *
+     * @return
+     */
+    @GET("jaxrs/task/{taskId}")
+    fun getTask(@Path("taskId") taskId: String): Observable<ApiResponse<TaskData>>
+
+
+    /**
+     * 启动流程
+     * @param processId
+     * *
+     * @param body
+     * *
+     * @return
+     */
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("jaxrs/work/process/{processId}")
+    fun startProcess(@Path("processId") processId: String, @Body body: ProcessStartBo): Observable<ApiResponse<List<ProcessWorkData>>>
+
+    /**
+     * 已办撤回
+     * @param workId
+     * *
+     * @return
+     */
+    @PUT("jaxrs/work/{workId}/retract")
+    fun retractWork(@Path("workId") workId: String): Observable<ApiResponse<IdData>>
+
+
+    /**
+     * 获取附件信息
+     * @param attachId
+     * *
+     * @param workId
+     * *
+     * @return
+     */
+    @GET("jaxrs/attachment/{attachId}/work/{workId}")
+    fun getWorkAttachmentInfo(@Path("attachId") attachId: String, @Path("workId") workId: String): Observable<ApiResponse<AttachmentInfo>>
+
+
+    /**
+     * 获取附件信息
+     * @param attachId
+     * *
+     * @param workCompletedId
+     * *
+     * @return
+     */
+    @GET("jaxrs/attachment/{attachId}/workcompleted/{workCompletedId}")
+    fun getWorkCompletedAttachmentInfo(@Path("attachId") attachId: String, @Path("workCompletedId") workCompletedId: String): Observable<ApiResponse<AttachmentInfo>>
+
+    /**
+     * 上传附件
+     * @param body
+     * *
+     * @param site
+     * *
+     * @param workId
+     */
+    @Multipart
+    @POST("jaxrs/attachment/upload/work/{workId}")
+    fun uploadAttachment(@Part body: MultipartBody.Part, @Part("site") site: RequestBody, @Path("workId") workId: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 替换附件
+     * @param body
+     * *
+     * @param attachmentId
+     * *
+     * @param workId
+     */
+    @Multipart
+    @PUT("jaxrs/attachment/update/{attachmentId}/work/{workId}")
+    fun replaceAttachment(@Part body: MultipartBody.Part, @Path("attachmentId") attachmentId: String, @Path("workId") workId: String): Observable<ApiResponse<IdData>>
+
+    /**
+     * 附件下载
+     * @param attachId
+     * *
+     * @return
+     */
+    @GET("jaxrs/attachment/download/{attachId}/work/{workId}/stream")
+    @Headers("Content-Type: application/json; charset=utf-8")
+    fun downloadWorkAttachment(@Path("attachId") attachId: String, @Path("workId") workId: String): Call<ResponseBody>
+
+    /**
+     * 附件下载
+     * @param attachId
+     * *
+     * @return
+     */
+    @GET("jaxrs/attachment/download/{attachId}/workcompleted/{workCompletedId}/stream")
+    @Headers("Content-Type: application/json; charset=utf-8")
+    fun downloadWorkCompletedAttachment(@Path("attachId") attachId: String, @Path("workCompletedId") workCompletedId: String): Call<ResponseBody>
+
+    /**
+     * 测试附件是否可用
+     * @param attachId
+     * *
+     * @return
+     */
+    @GET("jaxrs/attachment/{attachId}/available")
+    fun checkAttachmentAvailable(@Path("attachId") attachId: String): Observable<ApiResponse<ValueData>>
+}

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

@@ -0,0 +1,18 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.ApiResponse
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.TestObject
+import retrofit2.http.PUT
+import retrofit2.http.Path
+import rx.Observable
+
+
+interface QueryAssembleSurfaceService {
+
+    /**
+     * 执行视图
+     * 返回视图结果
+     */
+    @PUT("jaxrs/view/{id}/execute")
+    fun excuteView(@Path("id") id: String) : Observable<ApiResponse<TestObject>>
+}

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

@@ -0,0 +1,19 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import okhttp3.ResponseBody
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.Streaming
+import retrofit2.http.Url
+import rx.Observable
+
+
+/**
+ * Created by fancy on 2017/6/5.
+ */
+
+interface SkinDownLoadService {
+    @Streaming
+    @GET
+    fun skinDownload(@Url url: String): Observable<Response<ResponseBody>>
+}

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

@@ -0,0 +1,23 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.api.service
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.TulingPostData
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.TulingResponse
+import retrofit2.http.Body
+import retrofit2.http.Headers
+import retrofit2.http.POST
+import rx.Observable
+
+/**
+ * Created by fancyLou on 17/05/2018.
+ * Copyright © 2018 O2. All rights reserved.
+ */
+
+
+interface Tuling123Service{
+
+
+    @Headers("Content-Type:application/json;charset=UTF-8")
+    @POST("api")
+    fun api(@Body body: TulingPostData):Observable<TulingResponse>
+
+}

+ 48 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/component/enums/APIDistributeTypeEnum.java

@@ -0,0 +1,48 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.enums;
+
+
+/**
+ * api地址分发类型
+ *
+ * Created by FancyLou on 2015/12/15.
+ */
+public enum APIDistributeTypeEnum {
+    x_processplatform_assemble_surface_script,
+    x_processplatform_assemble_surface_task,
+    x_processplatform_assemble_surface_worklog,
+    x_processplatform_assemble_surface_workcompleted,
+    x_processplatform_assemble_surface_attachment,
+    x_processplatform_assemble_surface_work,
+    x_file_assemble_control,//云文件
+    x_meeting_assemble_control,//会议管理
+    x_attendance_assemble_control,//考勤管理
+    x_okr_assemble_control,//OKR
+    x_bbs_assemble_control,//BBS
+    x_hotpic_assemble_control,//热图展现
+    x_processplatform_assemble_surface_applicationdict,
+    x_cms_assemble_control,
+    x_organization_assemble_control,//新组织人员管理
+    x_collaboration_assemble_websocket,
+    x_organization_assemble_custom,
+    x_processplatform_assemble_surface,
+    x_processplatform_assemble_surface_read,
+    x_processplatform_assemble_surface_readcompleted,
+    x_organization_assemble_express,
+    x_organization_assemble_personal,
+    x_processplatform_assemble_surface_taskcompleted,
+    x_processplatform_assemble_surface_process,
+    x_component_assemble_control,
+    x_processplatform_assemble_surface_application,
+    x_processplatform_assemble_surface_data,
+    x_processplatform_assemble_designer,
+    x_processplatform_assemble_surface_review,
+    x_organization_assemble_authentication,
+    x_portal_assemble_surface,   //门户模块
+    x_calendar_assemble_control, //日程
+    x_jpush_assemble_control, //极光推送
+    x_mind_assemble_control, //脑图
+
+    x_query_assemble_surface //查询模块包含 视图、统计、自定义表等
+
+
+}

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

@@ -0,0 +1,18 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.component.enums
+
+/**
+ * Created by fancyLou on 2018/11/30.
+ * Copyright © 2018 O2. All rights reserved.
+ */
+
+enum class LaunchState {
+    ConnectO2Collect,
+    ConnectO2Server,
+    CheckMobileConfig,
+    DownloadMobileConfig,
+    AutoLogin,
+    NoBindError,
+    NoLoginError,
+    UnknownError,
+    Success
+}

+ 36 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/DownloadBean.java

@@ -0,0 +1,36 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.download;
+
+/**
+ * Created by FancyLou on 2016/4/21.
+ */
+public class DownloadBean {
+
+    private long contentLength;
+    private long bytesRead;
+    private boolean done;
+
+
+    public long getContentLength() {
+        return contentLength;
+    }
+
+    public void setContentLength(long contentLength) {
+        this.contentLength = contentLength;
+    }
+
+    public long getBytesRead() {
+        return bytesRead;
+    }
+
+    public void setBytesRead(long bytesRead) {
+        this.bytesRead = bytesRead;
+    }
+
+    public boolean isDone() {
+        return done;
+    }
+
+    public void setDone(boolean done) {
+        this.done = done;
+    }
+}

+ 28 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/DownloadProgressHandler.java

@@ -0,0 +1,28 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.download;
+
+import android.os.Looper;
+import android.os.Message;
+
+/**
+ * Created by FancyLou on 2016/4/21.
+ */
+public abstract class DownloadProgressHandler extends ProgressHandler {
+
+    private static final int DOWNLOAD_PROGRESS = 1;
+    protected ResponseHandler mHandler = new ResponseHandler(this, Looper.getMainLooper());
+
+    @Override
+    public void sendMessage(DownloadBean progressBean) {
+        mHandler.obtainMessage(DOWNLOAD_PROGRESS,progressBean).sendToTarget();
+
+    }
+
+    @Override
+    public void handleMessage(Message message){
+        switch (message.what){
+            case DOWNLOAD_PROGRESS:
+                DownloadBean progressBean = (DownloadBean)message.obj;
+                onProgress(progressBean.getBytesRead(),progressBean.getContentLength(),progressBean.isDone());
+        }
+    }
+}

+ 30 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/ProgressHandler.java

@@ -0,0 +1,30 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.download;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+/**
+ * Created by FancyLou on 2016/4/21.
+ */
+public abstract class ProgressHandler {
+
+    public abstract void sendMessage(DownloadBean progressBean);
+
+    public abstract void handleMessage(Message message);
+
+    public abstract void onProgress(long progress, long total, boolean done);
+
+    public static class ResponseHandler extends Handler{
+        private ProgressHandler mProgressHandler;
+        public ResponseHandler(ProgressHandler mProgressHandler, Looper looper) {
+            super(looper);
+            this.mProgressHandler = mProgressHandler;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            mProgressHandler.handleMessage(msg);
+        }
+    }
+}

+ 59 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/ProgressHelper.java

@@ -0,0 +1,59 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.download;
+
+
+import android.util.Log;
+
+import java.io.IOException;
+
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+
+/**
+ * Created by FancyLou on 2016/4/21.
+ */
+public class ProgressHelper {
+
+    private static ProgressHandler mHandler;
+    private static DownloadBean bean = new DownloadBean();
+
+    public static void setProgressHander(ProgressHandler hander) {
+        mHandler = hander;
+    }
+
+    public static OkHttpClient.Builder addProgress(OkHttpClient.Builder builder){
+        if (builder == null) {
+            builder = new OkHttpClient.Builder();
+        }
+
+        final ProgressListener progressListener = new ProgressListener() {
+            //该方法在子线程中运行
+            @Override
+            public void onProgress(long progress, long total, boolean done) {
+                //Log.d("progress:",String.format("%d%% done\n",(100 * progress) / total));
+                if (mHandler == null){
+                    Log.e("ProgressHelper","progress error, handler is null");
+                    return;
+                }
+                bean.setBytesRead(progress);
+                bean.setContentLength(total);
+                bean.setDone(done);
+                mHandler.sendMessage(bean);
+            }
+        };
+        //添加拦截器,自定义ResponseBody,添加下载进度
+        builder.networkInterceptors().add(new Interceptor() {
+            @Override
+            public okhttp3.Response intercept(Chain chain) throws IOException {
+                okhttp3.Response originalResponse = chain.proceed(chain.request());
+                return originalResponse.newBuilder().body(
+                        new ProgressResponseBody(originalResponse.body(), progressListener))
+                        .build();
+
+            }
+        });
+
+        return builder;
+    }
+
+
+}

+ 9 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/ProgressListener.java

@@ -0,0 +1,9 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.download;
+
+/**
+ * Created by FancyLou on 2016/4/21.
+ */
+public interface ProgressListener {
+
+    void onProgress(long progress, long total, boolean done);
+}

+ 59 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/download/ProgressResponseBody.java

@@ -0,0 +1,59 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.download;
+
+import java.io.IOException;
+
+import okhttp3.MediaType;
+import okhttp3.ResponseBody;
+import okio.Buffer;
+import okio.BufferedSource;
+import okio.ForwardingSource;
+import okio.Okio;
+import okio.Source;
+
+/**
+ * 重写ResponseBody类 把下载进度 通过ProgressListener 传递出来
+ * Created by FancyLou on 2016/4/21.
+ */
+public class ProgressResponseBody extends ResponseBody {
+
+    private final ResponseBody responseBody;
+    private final ProgressListener progressListener;
+    private BufferedSource bufferedSource;
+
+
+    public ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
+        this.responseBody = responseBody;
+        this.progressListener = progressListener;
+    }
+
+    @Override
+    public MediaType contentType() {
+        return responseBody.contentType();
+    }
+
+    @Override
+    public long contentLength() {
+        return responseBody.contentLength();
+    }
+
+    @Override
+    public BufferedSource source() {
+        if (bufferedSource == null) {
+            bufferedSource = Okio.buffer(source(responseBody.source()));
+        }
+        return bufferedSource;
+    }
+
+    private Source source(Source source) {
+        return new ForwardingSource(source) {
+            long totalBytesRead = 0L;
+            @Override
+            public long read(Buffer sink, long byteCount) throws IOException {
+                long bytesRead = super.read(sink, byteCount);
+                totalBytesRead += (bytesRead != -1 ? bytesRead : 0);
+                progressListener.onProgress(totalBytesRead, contentLength(), bytesRead == -1);
+                return bytesRead;
+            }
+        };
+    }
+}

+ 10 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/exception/NoBindException.kt

@@ -0,0 +1,10 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.exception
+
+import java.lang.RuntimeException
+
+/**
+ * Created by fancyLou on 2018/11/30.
+ * Copyright © 2018 O2. All rights reserved.
+ */
+
+class NoBindException(message: String?) : RuntimeException(message)

+ 8 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/exception/NoLoginException.kt

@@ -0,0 +1,8 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.exception
+
+/**
+ * Created by fancyLou on 2018/11/30.
+ * Copyright © 2018 O2. All rights reserved.
+ */
+
+class NoLoginException(message: String?) : RuntimeException(message)

+ 8 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/core/exception/O2ResponseException.kt

@@ -0,0 +1,8 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.core.exception
+
+import java.lang.Exception
+
+/**
+ * o2 请求反馈的错误信息
+ */
+class O2ResponseException(message: String): Exception(message)

+ 38 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/DepartmentItem.java

@@ -0,0 +1,38 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo;
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.item.ContactItem;
+
+/**
+ * departmentList对象
+ *
+ * Created by FancyLou on 2015/10/16.
+ */
+public class DepartmentItem extends ContactItem {
+    private String name;
+    private int departmentCount;
+    private int identityCount;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public int getDepartmentCount() {
+        return departmentCount;
+    }
+
+    public void setDepartmentCount(int departmentCount) {
+        this.departmentCount = departmentCount;
+    }
+
+    public int getIdentityCount() {
+        return identityCount;
+    }
+
+    public void setIdentityCount(int identityCount) {
+        this.identityCount = identityCount;
+    }
+}

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

@@ -0,0 +1,328 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api;
+
+/**
+ * Created by FancyLou on 2015/12/15.
+ */
+public class APIAssemblesData {
+
+    private APIDataBean x_processplatform_assemble_surface_script;
+    private APIDataBean x_processplatform_assemble_surface_task;
+    private APIDataBean x_processplatform_assemble_surface_worklog;
+    private APIDataBean x_processplatform_assemble_surface_workcompleted;
+    private APIDataBean x_processplatform_assemble_surface_attachment;
+    private APIDataBean x_processplatform_assemble_surface_work;
+    private APIDataBean x_file_assemble_control;
+    private APIDataBean x_okr_assemble_control;
+    private APIDataBean x_bbs_assemble_control;
+    private APIDataBean x_hotpic_assemble_control;
+    private APIDataBean x_attendance_assemble_control;
+    private APIDataBean x_meeting_assemble_control;
+    private APIDataBean x_processplatform_assemble_surface_applicationdict;
+    private APIDataBean x_cms_assemble_control;
+    private APIDataBean x_organization_assemble_control;
+    private APIDataBean x_collaboration_assemble_websocket;
+    private APIDataBean x_organization_assemble_custom;
+    private APIDataBean x_processplatform_assemble_surface;
+    private APIDataBean x_processplatform_assemble_surface_read;
+    private APIDataBean x_processplatform_assemble_surface_readcompleted;
+    private APIDataBean x_organization_assemble_express;
+    private APIDataBean x_organization_assemble_personal;
+    private APIDataBean x_processplatform_assemble_surface_taskcompleted;
+    private APIDataBean x_processplatform_assemble_surface_process;
+    private APIDataBean x_component_assemble_control;
+    private APIDataBean x_processplatform_assemble_surface_application;
+    private APIDataBean x_processplatform_assemble_surface_data;
+    private APIDataBean x_processplatform_assemble_designer;
+    private APIDataBean x_processplatform_assemble_surface_review;
+    private APIDataBean x_organization_assemble_authentication;
+    private APIDataBean x_portal_assemble_surface;
+    private APIDataBean x_calendar_assemble_control; //日程
+    private APIDataBean x_mind_assemble_control; //脑图
+    private APIDataBean x_jpush_assemble_control; //极光推送服务
+
+
+    private APIDataBean  x_query_assemble_surface;//查询模块包含 视图、统计、自定义表等
+
+    public APIDataBean getX_query_assemble_surface() {
+        return x_query_assemble_surface;
+    }
+
+    public void setX_query_assemble_surface(APIDataBean x_query_assemble_surface) {
+        this.x_query_assemble_surface = x_query_assemble_surface;
+    }
+
+
+
+    public APIDataBean getX_jpush_assemble_control() {
+        return x_jpush_assemble_control;
+    }
+
+    public void setX_jpush_assemble_control(APIDataBean x_jpush_assemble_control) {
+        this.x_jpush_assemble_control = x_jpush_assemble_control;
+    }
+
+    public APIDataBean getX_mind_assemble_control() {
+        return x_mind_assemble_control;
+    }
+
+    public void setX_mind_assemble_control(APIDataBean x_mind_assemble_control) {
+        this.x_mind_assemble_control = x_mind_assemble_control;
+    }
+
+    public APIDataBean getX_calendar_assemble_control() {
+        return x_calendar_assemble_control;
+    }
+
+    public void setX_calendar_assemble_control(APIDataBean x_calendar_assemble_control) {
+        this.x_calendar_assemble_control = x_calendar_assemble_control;
+    }
+
+    public APIDataBean getX_hotpic_assemble_control() {
+        return x_hotpic_assemble_control;
+    }
+
+    public void setX_hotpic_assemble_control(APIDataBean x_hotpic_assemble_control) {
+        this.x_hotpic_assemble_control = x_hotpic_assemble_control;
+    }
+
+    public APIDataBean getX_bbs_assemble_control() {
+        return x_bbs_assemble_control;
+    }
+
+    public void setX_bbs_assemble_control(APIDataBean x_bbs_assemble_control) {
+        this.x_bbs_assemble_control = x_bbs_assemble_control;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface() {
+        return x_processplatform_assemble_surface;
+    }
+
+    public void setX_processplatform_assemble_surface(
+            APIDataBean x_processplatform_assemble_surface) {
+        this.x_processplatform_assemble_surface = x_processplatform_assemble_surface;
+    }
+
+    public APIDataBean getX_meeting_assemble_control() {
+        return x_meeting_assemble_control;
+    }
+
+    public void setX_meeting_assemble_control(APIDataBean x_meeting_assemble_control) {
+        this.x_meeting_assemble_control = x_meeting_assemble_control;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_script() {
+        return x_processplatform_assemble_surface_script;
+    }
+
+    public void setX_processplatform_assemble_surface_script(APIDataBean x_processplatform_assemble_surface_script) {
+        this.x_processplatform_assemble_surface_script = x_processplatform_assemble_surface_script;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_task() {
+        return x_processplatform_assemble_surface_task;
+    }
+
+    public void setX_processplatform_assemble_surface_task(APIDataBean x_processplatform_assemble_surface_task) {
+        this.x_processplatform_assemble_surface_task = x_processplatform_assemble_surface_task;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_worklog() {
+        return x_processplatform_assemble_surface_worklog;
+    }
+
+    public void setX_processplatform_assemble_surface_worklog(APIDataBean x_processplatform_assemble_surface_worklog) {
+        this.x_processplatform_assemble_surface_worklog = x_processplatform_assemble_surface_worklog;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_workcompleted() {
+        return x_processplatform_assemble_surface_workcompleted;
+    }
+
+    public void setX_processplatform_assemble_surface_workcompleted(APIDataBean x_processplatform_assemble_surface_workcompleted) {
+        this.x_processplatform_assemble_surface_workcompleted = x_processplatform_assemble_surface_workcompleted;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_attachment() {
+        return x_processplatform_assemble_surface_attachment;
+    }
+
+    public void setX_processplatform_assemble_surface_attachment(APIDataBean x_processplatform_assemble_surface_attachment) {
+        this.x_processplatform_assemble_surface_attachment = x_processplatform_assemble_surface_attachment;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_work() {
+        return x_processplatform_assemble_surface_work;
+    }
+
+    public void setX_processplatform_assemble_surface_work(APIDataBean x_processplatform_assemble_surface_work) {
+        this.x_processplatform_assemble_surface_work = x_processplatform_assemble_surface_work;
+    }
+
+    public APIDataBean getX_file_assemble_control() {
+        return x_file_assemble_control;
+    }
+
+    public void setX_file_assemble_control(APIDataBean x_file_assemble_control) {
+        this.x_file_assemble_control = x_file_assemble_control;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_applicationdict() {
+        return x_processplatform_assemble_surface_applicationdict;
+    }
+
+    public void setX_processplatform_assemble_surface_applicationdict(APIDataBean x_processplatform_assemble_surface_applicationdict) {
+        this.x_processplatform_assemble_surface_applicationdict = x_processplatform_assemble_surface_applicationdict;
+    }
+
+    public APIDataBean getX_cms_assemble_control() {
+        return x_cms_assemble_control;
+    }
+
+    public void setX_cms_assemble_control(APIDataBean x_cms_assemble_control) {
+        this.x_cms_assemble_control = x_cms_assemble_control;
+    }
+
+    public APIDataBean getX_organization_assemble_control() {
+        return x_organization_assemble_control;
+    }
+
+    public void setX_organization_assemble_control(APIDataBean x_organization_assemble_control) {
+        this.x_organization_assemble_control = x_organization_assemble_control;
+    }
+
+    public APIDataBean getX_collaboration_assemble_websocket() {
+        return x_collaboration_assemble_websocket;
+    }
+
+    public void setX_collaboration_assemble_websocket(APIDataBean x_collaboration_assemble_websocket) {
+        this.x_collaboration_assemble_websocket = x_collaboration_assemble_websocket;
+    }
+
+    public APIDataBean getX_organization_assemble_custom() {
+        return x_organization_assemble_custom;
+    }
+
+    public void setX_organization_assemble_custom(APIDataBean x_organization_assemble_custom) {
+        this.x_organization_assemble_custom = x_organization_assemble_custom;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_read() {
+        return x_processplatform_assemble_surface_read;
+    }
+
+    public void setX_processplatform_assemble_surface_read(APIDataBean x_processplatform_assemble_surface_read) {
+        this.x_processplatform_assemble_surface_read = x_processplatform_assemble_surface_read;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_readcompleted() {
+        return x_processplatform_assemble_surface_readcompleted;
+    }
+
+    public void setX_processplatform_assemble_surface_readcompleted(APIDataBean x_processplatform_assemble_surface_readcompleted) {
+        this.x_processplatform_assemble_surface_readcompleted = x_processplatform_assemble_surface_readcompleted;
+    }
+
+    public APIDataBean getX_organization_assemble_express() {
+        return x_organization_assemble_express;
+    }
+
+    public void setX_organization_assemble_express(APIDataBean x_organization_assemble_express) {
+        this.x_organization_assemble_express = x_organization_assemble_express;
+    }
+
+    public APIDataBean getX_organization_assemble_personal() {
+        return x_organization_assemble_personal;
+    }
+
+    public void setX_organization_assemble_personal(APIDataBean x_organization_assemble_personal) {
+        this.x_organization_assemble_personal = x_organization_assemble_personal;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_taskcompleted() {
+        return x_processplatform_assemble_surface_taskcompleted;
+    }
+
+    public void setX_processplatform_assemble_surface_taskcompleted(APIDataBean x_processplatform_assemble_surface_taskcompleted) {
+        this.x_processplatform_assemble_surface_taskcompleted = x_processplatform_assemble_surface_taskcompleted;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_process() {
+        return x_processplatform_assemble_surface_process;
+    }
+
+    public void setX_processplatform_assemble_surface_process(APIDataBean x_processplatform_assemble_surface_process) {
+        this.x_processplatform_assemble_surface_process = x_processplatform_assemble_surface_process;
+    }
+
+    public APIDataBean getX_component_assemble_control() {
+        return x_component_assemble_control;
+    }
+
+    public void setX_component_assemble_control(APIDataBean x_component_assemble_control) {
+        this.x_component_assemble_control = x_component_assemble_control;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_application() {
+        return x_processplatform_assemble_surface_application;
+    }
+
+    public void setX_processplatform_assemble_surface_application(APIDataBean x_processplatform_assemble_surface_application) {
+        this.x_processplatform_assemble_surface_application = x_processplatform_assemble_surface_application;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_data() {
+        return x_processplatform_assemble_surface_data;
+    }
+
+    public void setX_processplatform_assemble_surface_data(APIDataBean x_processplatform_assemble_surface_data) {
+        this.x_processplatform_assemble_surface_data = x_processplatform_assemble_surface_data;
+    }
+
+    public APIDataBean getX_processplatform_assemble_designer() {
+        return x_processplatform_assemble_designer;
+    }
+
+    public void setX_processplatform_assemble_designer(APIDataBean x_processplatform_assemble_designer) {
+        this.x_processplatform_assemble_designer = x_processplatform_assemble_designer;
+    }
+
+    public APIDataBean getX_processplatform_assemble_surface_review() {
+        return x_processplatform_assemble_surface_review;
+    }
+
+    public void setX_processplatform_assemble_surface_review(APIDataBean x_processplatform_assemble_surface_review) {
+        this.x_processplatform_assemble_surface_review = x_processplatform_assemble_surface_review;
+    }
+
+    public APIDataBean getX_organization_assemble_authentication() {
+        return x_organization_assemble_authentication;
+    }
+
+    public void setX_organization_assemble_authentication(APIDataBean x_organization_assemble_authentication) {
+        this.x_organization_assemble_authentication = x_organization_assemble_authentication;
+    }
+
+    public APIDataBean getX_attendance_assemble_control() {
+        return x_attendance_assemble_control;
+    }
+
+    public void setX_attendance_assemble_control(APIDataBean x_attendance_assemble_control) {
+        this.x_attendance_assemble_control = x_attendance_assemble_control;
+    }
+
+    public APIDataBean getX_okr_assemble_control() {
+        return x_okr_assemble_control;
+    }
+
+    public void setX_okr_assemble_control(APIDataBean x_okr_assemble_control) {
+        this.x_okr_assemble_control = x_okr_assemble_control;
+    }
+
+    public APIDataBean getX_portal_assemble_surface() {
+        return x_portal_assemble_surface;
+    }
+
+    public void setX_portal_assemble_surface(APIDataBean x_portal_assemble_surface) {
+        this.x_portal_assemble_surface = x_portal_assemble_surface;
+    }
+}

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

@@ -0,0 +1,55 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api;
+
+/**
+ * http://xc01.zoneland.net:30080/x_program_center/jaxrs/distribute/assemble
+ *
+ * Created by FancyLou on 2015/12/15.
+ */
+public class APIDataBean {
+
+    private String host;
+    private int port;
+    private String proxyHost;
+    private int proxyPort;
+    private String context;
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public String getContext() {
+        return context;
+    }
+
+    public void setContext(String context) {
+        this.context = context;
+    }
+
+    public String getProxyHost() {
+        return proxyHost;
+    }
+
+    public void setProxyHost(String proxyHost) {
+        this.proxyHost = proxyHost;
+    }
+
+    public int getProxyPort() {
+        return proxyPort;
+    }
+
+    public void setProxyPort(int proxyPort) {
+        this.proxyPort = proxyPort;
+    }
+}

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

@@ -0,0 +1,26 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api;
+
+/**
+ * Created by FancyLou on 2016/1/12.
+ */
+public class APIDistributeData {
+
+    private APIWebServerData webServer;
+    private APIAssemblesData assembles;
+
+    public APIWebServerData getWebServer() {
+        return webServer;
+    }
+
+    public void setWebServer(APIWebServerData webServer) {
+        this.webServer = webServer;
+    }
+
+    public APIAssemblesData getAssembles() {
+        return assembles;
+    }
+
+    public void setAssembles(APIAssemblesData assembles) {
+        this.assembles = assembles;
+    }
+}

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

@@ -0,0 +1,30 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api
+
+/**
+ * 日志收集信息对象
+ * Created by fancyLou on 12/06/2018.
+ * Copyright © 2018 O2. All rights reserved.
+ */
+
+data class APILogData(
+        var unit:String = "",//绑定的单位id
+        var unitName:String = "",
+        var centerHost:String = "",//中心服务器host
+        var centerContext:String = "",
+        var centerPort:String = "",
+        var deviceToken:String = "",//手机设备号
+        var distinguishedName:String = "",//当前用户的distinguishedName
+        var name:String = "",//当前用户的姓名
+        var mobile:String = "",
+        var o2Version:String = "",//当前O2应用版本号
+        var osType:String = "",//android ios
+        var osVersion:String = "",//当前手机系统版本
+        var osCpu:String = "",//cpu 信息
+        var osMemory:String = "",//内存信息
+        var osDpi:String = "",//手机分辨率
+        var androidManufacturer:String = "",//android手机制造商
+        var manufacturerOsVersion:String = "",//android 定制系统版本
+        var logDate:String = "",//日志记录日期
+        var logContent:String = ""//这个是日志信息 内容比较大 有可能是几M的
+
+)

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

@@ -0,0 +1,86 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api;
+
+import android.text.TextUtils;
+
+
+/**
+ * Created by FancyLou on 2016/1/12.
+ */
+public class APIWebServerData {
+    private String host;
+    private int port;
+    private String proxyHost;
+    private int proxyPort;
+    private String username;
+    private String password;
+    private int order;
+    private String name;
+
+
+    public String getProxyHost() {
+        if (TextUtils.isEmpty(proxyHost) || proxyHost.equals("127.0.0.1")){
+            return host;
+        }
+        return proxyHost;
+    }
+
+    public void setProxyHost(String proxyHost) {
+        this.proxyHost = proxyHost;
+    }
+
+    public int getProxyPort() {
+        return proxyPort;
+    }
+
+    public void setProxyPort(int proxyPort) {
+        this.proxyPort = proxyPort;
+    }
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public int getOrder() {
+        return order;
+    }
+
+    public void setOrder(int order) {
+        this.order = order;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

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

@@ -0,0 +1,82 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api;
+
+/**
+ * Created by fancy on 2017/3/23.
+ */
+
+public class ApiErrorResponse {
+
+    private String type;//success
+    private String date;
+    private int spent;
+    private int size;
+    private int count;
+    private int position;
+    private String message;
+    private String prompt;
+
+
+    public String getPrompt() {
+        return prompt;
+    }
+
+    public void setPrompt(String prompt) {
+        this.prompt = prompt;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getDate() {
+        return date;
+    }
+
+    public void setDate(String date) {
+        this.date = date;
+    }
+
+    public int getSpent() {
+        return spent;
+    }
+
+    public void setSpent(int spent) {
+        this.spent = spent;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public void setSize(int size) {
+        this.size = size;
+    }
+
+    public int getCount() {
+        return count;
+    }
+
+    public void setCount(int count) {
+        this.count = count;
+    }
+
+    public int getPosition() {
+        return position;
+    }
+
+    public void setPosition(int position) {
+        this.position = position;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}

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

@@ -0,0 +1,83 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api;
+
+/**
+ * http api response object
+ * Created by FancyLou on 2015/12/23.
+ */
+public class ApiResponse<T> {
+
+    private String type;//success
+    private String date;
+    private int spent;
+    private int size;
+    private int count;
+    private int position;
+    private String message;
+
+    private T data;
+
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getDate() {
+        return date;
+    }
+
+    public void setDate(String date) {
+        this.date = date;
+    }
+
+    public int getSpent() {
+        return spent;
+    }
+
+    public void setSpent(int spent) {
+        this.spent = spent;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public void setSize(int size) {
+        this.size = size;
+    }
+
+    public int getCount() {
+        return count;
+    }
+
+    public void setCount(int count) {
+        this.count = count;
+    }
+
+    public int getPosition() {
+        return position;
+    }
+
+    public void setPosition(int position) {
+        this.position = position;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+}

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

@@ -0,0 +1,16 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api;
+
+/**
+ * Created by FancyLou on 2016/2/22.
+ */
+public class IdData {
+    private String id;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+}

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

@@ -0,0 +1,6 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api
+
+
+//极光推送 设备绑定对象
+data class JPushDeviceForm(var deviceName: String = "",
+                           var deviceType: String = "android")

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

@@ -0,0 +1,6 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api
+
+
+
+data class TestObject(var id: String = "",
+                      var name: String = "")

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

@@ -0,0 +1,13 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api
+
+/**
+ * Created by fancyLou on 17/05/2018.
+ * Copyright © 2018 O2. All rights reserved.
+ */
+
+
+data class TulingPostData(
+        var key: String = "", //api的key
+        var info: String = "" //问答内容
+)
+

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

@@ -0,0 +1,12 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api
+
+/**
+ * Created by fancyLou on 17/05/2018.
+ * Copyright © 2018 O2. All rights reserved.
+ */
+
+
+data class TulingResponse(
+        var code: String = "",
+        var text: String = ""
+)

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

@@ -0,0 +1,17 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api;
+
+/**
+ * Created by FancyLou on 2016/2/22.
+ */
+public class ValueData {
+
+    private boolean value;
+
+    public boolean isValue() {
+        return value;
+    }
+
+    public void setValue(boolean value) {
+        this.value = value;
+    }
+}

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

@@ -0,0 +1,31 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api;
+
+/**
+ * Created by FancyLou on 2016/2/22.
+ */
+public class ValueNumberData {
+
+    private int value;
+    private String id;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public int getValue() {
+        return value;
+    }
+
+    public void setValue(int value) {
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return "id:"+ id + " , value:"+value;
+    }
+}

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

@@ -0,0 +1,14 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api
+
+/**
+ * Created by fancyLou on 2018/8/22.
+ * Copyright © 2018 O2. All rights reserved.
+ */
+class WorkControl(
+        var allowVisit:Boolean = false,
+        var allowProcessing:Boolean = false,
+        var allowReadProcessing:Boolean = false,
+        var allowSave:Boolean = false,
+        var allowRetract:Boolean = false,
+        var allowDelete: Boolean = false
+)

+ 235 - 0
o2android/o2_auth_sdk/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/model/bo/api/attendance/AttendanceJSON.kt

@@ -0,0 +1,235 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.model.bo.api.attendance
+
+import net.zoneland.x.bpm.mobile.v1.zoneXBPM.O2
+import java.io.Serializable
+
+/**
+ * 考勤api 数据对象集合
+ * Created by fancy on 2017/3/28.
+ */
+
+/**
+ * 管理员
+ */
+data class AdministratorInfoJson(
+        var id: String = "",
+        var createTime: String = "",
+        var updateTime: String = "",
+        var sequence: String = "",
+        var organizationName: String = "",
+        var organizationOu: String = "",
+        var adminName: String = "",
+        var adminLevel: String = "",
+        var distributeFactor: Int = 0
+
+)
+
+/**
+ * 查询审批的过滤条件
+ */
+data class AppealApprovalQueryFilterJson(
+        var status: String = "", // 0待审批 1审批通过 -1审批未通过 999所有
+        var yearString: String = "", //年份 2016
+        var monthString: String = "",
+        var processPerson1: String = "", //审批人 就是当前用户
+        var appealReason: String = "",
+        var departmentName: String = "",
+        var empName: String = ""
+)
+
+/**
+ * 审批申诉对象
+ */
+data class AppealApprovalFormJson(
+        var ids: ArrayList<String> = ArrayList(),
+        var opinion: String = "", //审核意见
+        var status: String = ""//审核状态:1-通过;2-需要进行复核;-1-不通过
+)
+
+/**
+ * 考勤统计周期
+ */
+data class AttendanceStatisticCycle(
+        var id: String = "",
+        var createTime: String = "",
+        var updateTime: String = "",
+        var topUnitName: String = "",
+        var unitName: String = "",
+        var cycleYear: String = "",
+        var cycleMonth: String = "",
+        var cycleStartDateString: String = "",
+        var cycleEndDateString: String = "",
+        var cycleStartDate: String = "",
+        var cycleEndDate: String = "",
+        var description: String = ""
+)
+
+/**
+ * 申诉对象
+ */
+data class AppealInfoJson(
+        var id: String = "",
+        var createTime: String = "",
+        var updateTime: String = "",
+        var sequence: String = "",
+        var detailId: String = "",
+        var empName: String = "", //distinguishedName
+        var topUnitName: String = "", //distinguishedName
+        var unitName: String = "", //distinguishedName
+        var companyName: String = "",
+        var departmentName: String = "",
+        var yearString: String = "",
+        var monthString: String = "",
+        var appealDateString: String = "",
+        var recordDateString: String = "",
+        var recordDate: String = "",
+        var status: Int = 0,
+        var startTime: String = "",
+        var endTime: String = "",
+        var appealReason: String = "",
+        var selfHolidayType: String = "",
+        var address: String = "",
+        var appealDescription: String = "",
+        var currentProcessor: String = "",
+        var processPerson1: String = "",
+        var processPersonDepartment1: String = "",
+        var processPersonCompany1: String = ""
+)
+
+/**
+ * 反馈对象 status:SUCCESS
+ */
+data class BackInfoJson(
+        var message: String = "",
+        var status: String = ""
+)
+
+/**
+ * 考勤信息查询过滤条件
+ */
+data class AttendanceDetailQueryFilterJson(
+        var cycleYear: String = "", //年份 如 2016
+        var cycleMonth: String = "", //月份 如 04
+        var key: String = "", //recordDateString
+        var order: String = "", //排序 desc asc
+        var q_empName: String = ""//当前用户
+)
+
+/**
+ * 考勤详细信息
+ */
+data class AttendanceDetailInfoJson(
+        var id: String = "",
+        var createTime: String = "",
+        var updateTime: String = "",
+        var sequence: String = "",
+        var empNo: String = "",
+        var empName: String = "",
+        var companyName: String = "",
+        var departmentName: String = "",
+        var yearString: String = "",
+        var monthString: String = "",
+        var recordDateString: String = "",
+        var recordDate: String = "",
+        var cycleYear: String = "",
+        var cycleMonth: String = "",
+        var isHoliday: Boolean = false,
+        var isWorkday: Boolean = false,
+        var isGetSelfHolidays: Boolean = false,
+        var selfHolidayDayTime: String = "",
+        var absentDayTime: String = "",
+        var abnormalDutyDayTime: String = "",
+        var getSelfHolidayDays: Double = 0.0,
+        var isWeekend: Boolean = false,
+        var onWorkTime: String = "",
+        var offWorkTime: String = "",
+        var onDutyTime: String = "",
+        var offDutyTime: String = "",
+        var isLate: Boolean = false,
+        var lateTimeDuration: Long = 0L,
+        var isLeaveEarlier: Boolean = false,
+        var leaveEarlierTimeDuration: Long = 0L,
+        var isAbsent: Boolean = false,
+        var isAbnormalDuty: Boolean = false,
+        var isLackOfTime: Boolean = false,
+        var isWorkOvertime: Boolean = false,
+        var workOvertimeTimeDuration: Long = 0L,
+        var workTimeDuration: Long = 0L,
+        var attendance: Double = 0.0,
+        var absence: Double = 0.0,
+        var recordStatus: Int = 0,
+        var batchName: String = "",
+        var description: String = "",
+        //申诉相关信息
+        var identity: String = "", //多身份的时候选择的身份dn
+        var appealStatus: Int = 0, //申诉状态:0-未申诉,1-申诉中,-1-申诉未通过,9-申诉通过
+        var appealReason: String = "", //原因  临时请假  出差 因公外出 其他
+        var appealDescription: String = "", //事由
+        var selfHolidayType: String = "", //如果原因是临时请假 这里需要选择一个请假类型 :带薪年休假 带薪病假 带薪福利假 扣薪事假 其他
+        var address: String = "", //外出地址
+        var startTime: String = "", // yyyy-MM-dd HH:mm
+        var endTime: String = "", // yyyy-MM-dd HH:mm
+        var appealProcessor: String = "",//申诉审批人
+        var processPerson1: String = ""// 审批人一
+) : Serializable
+
+/**
+ * 手机打卡对象
+ */
+data class MobileCheckInJson(
+        var id: String = "",
+        var createTime: String = "",
+        var updateTime: String = "",
+        var empNo: String = "", //员工号
+        var empName: String = "", //姓名
+        var recordDateString: String = "", //打卡记录日期字符串:yyyy-mm-dd, 必须填写.
+        var signTime: String = "", //打卡时间: hh24:mi:ss, 必须填写.
+        var signDescription: String = "", //打卡说明:上班打卡,下班打卡, 可以为空.
+        var description: String = "",
+        var recordAddress: String = "", //打卡地点描述, 可以为空.
+        var longitude: String = "", //经度, 可以为空.
+        var latitude: String = "", //纬度, 可以为空.
+        var optMachineType: String = "", //操作设备类别:手机品牌|PAD|PC|其他, 可以为空.
+        var optSystemName: String = O2.DEVICE_TYPE, //操作设备类别:Mac|Windows|IOS|Android|其他, 可以为空.
+        var recordStatus: Int = 0//记录状态:0-未分析 1-已分析
+)
+
+/**
+ * 查询手机打卡的过滤条件
+ */
+data class MobileCheckInQueryFilterJson(
+        var empNo: String = "",
+        var empName: String = "",
+        var startDate: String = "",
+        var endDate: String = "",
+        var signDescription: String = ""//打卡说明:上班打卡,下班打卡, 可以为空.
+)
+
+/**
+ * 工作场所对象
+ */
+data class MobileCheckInWorkplaceInfoJson(
+        var id: String = "",
+        var updateTime: String = "",
+        var placeName: String = "",
+        var placeAlias: String = "",
+        var creator: String = "",
+        var longitude: String = "",
+        var latitude: String = "",
+        var errorRange: Int = 0,
+        var description: String = ""
+)
+
+/**
+ * 考勤设置信息
+ */
+data class SettingInfoJson(
+        var id: String = "",
+        var createTime: String = "",
+        var updateTime: String = "",
+        var sequence: String = "",
+        var configCode: String = "",
+        var configName: String = "",
+        var configValue: String = "",
+        var ordernumber: Int = 0
+)

Некоторые файлы не были показаны из-за большого количества измененных файлов