Browse Source

add poc2.0需求

lihao1 3 years ago
parent
commit
906cb339f3
44 changed files with 1115 additions and 290 deletions
  1. 2 1
      demo/src/main/java/com/sybotan/android/demo/bean/result/Photos.java
  2. 7 0
      cadengine/src/main/java/cn/sagacloud/android/cadengine/types/Point.kt
  3. 24 1
      cadengine/src/main/java/cn/sagacloud/android/cadengine/types/TunableSpace.kt
  4. 2 0
      demo/build.gradle
  5. 14 0
      demo/src/main/AndroidManifest.xml
  6. 3 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/FileDao.kt
  7. 3 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/InfosConfigDao.kt
  8. 3 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/QrCodeDao.kt
  9. 14 4
      demo/src/main/java/com/framework/mvvm/model/db/entity/ObjectEntity.kt
  10. 1 1
      demo/src/main/java/com/framework/mvvm/model/db/entity/ProblemArchEntity.kt
  11. 33 1
      demo/src/main/java/com/framework/mvvm/model/repository/AdmRepository.kt
  12. 11 9
      demo/src/main/java/com/sybotan/android/demo/activities/EquipDetailActivity.kt
  13. 140 47
      demo/src/main/java/com/sybotan/android/demo/activities/GraphyActivity.kt
  14. 23 6
      demo/src/main/java/com/sybotan/android/demo/activities/PocActivity.kt
  15. 42 8
      demo/src/main/java/com/sybotan/android/demo/activities/SpaceDetailActivity.kt
  16. 1 1
      demo/src/main/java/com/sybotan/android/demo/activities/poc/DeviceActivity.kt
  17. 1 1
      demo/src/main/java/com/sybotan/android/demo/activities/poc/DeviceTypeActivity.kt
  18. 2 2
      demo/src/main/java/com/sybotan/android/demo/activities/poc/RelationActivity.kt
  19. 2 1
      demo/src/main/java/com/sybotan/android/demo/activities/poc/SceneActivity.kt
  20. 2 1
      demo/src/main/java/com/sybotan/android/demo/activities/poc/SpaceActivity.kt
  21. 6 12
      demo/src/main/java/com/sybotan/android/demo/adapter/PictureAdapter.java
  22. 20 7
      demo/src/main/java/com/sybotan/android/demo/adapter/SelectPopListAdapter.java
  23. 175 41
      demo/src/main/java/com/sybotan/android/demo/adapter/StaticInfoAdapter.java
  24. 3 2
      demo/src/main/java/com/sybotan/android/demo/adapter/ViewPagerImageAdapter.java
  25. 6 0
      demo/src/main/java/com/sybotan/android/demo/bean/result/ProblemsModel.java
  26. 1 1
      demo/src/main/java/com/sybotan/android/demo/retrofit/API.java
  27. 72 0
      demo/src/main/java/com/sybotan/android/demo/tools/IdGenerator.java
  28. 65 0
      demo/src/main/java/com/sybotan/android/demo/tools/MyGlideModules.java
  29. 9 0
      demo/src/main/java/com/sybotan/android/demo/tools/MyProvider.java
  30. 28 9
      demo/src/main/java/com/sybotan/android/demo/view/SelectListPopupWindow.java
  31. 11 6
      demo/src/main/java/com/sybotan/android/demo/viewmodel/BaseViewModel.java
  32. 3 1
      demo/src/main/java/com/sybotan/android/demo/viewmodel/BuildVM.kt
  33. 2 1
      demo/src/main/java/com/sybotan/android/demo/viewmodel/DeviceVM.kt
  34. 257 56
      demo/src/main/java/com/sybotan/android/demo/viewmodel/GraphyVM.kt
  35. 4 3
      demo/src/main/java/com/sybotan/android/demo/viewmodel/RelationVM.kt
  36. 1 0
      demo/src/main/res/layout/activity_equip_detail.xml
  37. 1 0
      demo/src/main/res/layout/activity_graphy.xml
  38. 1 0
      demo/src/main/res/layout/activity_space_detail.xml
  39. 1 1
      demo/src/main/res/layout/dialog_list_choice.xml
  40. 10 2
      demo/src/main/res/layout/personal_select_text_item.xml
  41. 2 3
      demo/src/main/res/layout/static_info.xml
  42. 1 1
      demo/src/main/res/layout/view_enum.xml
  43. 5 0
      demo/src/main/res/xml/file_paths.xml
  44. 101 60
      sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/SGraphyView.kt

+ 2 - 1
demo/src/main/java/com/sybotan/android/demo/bean/result/Photos.java

@@ -1,4 +1,4 @@
-package com.sybotan.android.demo.bean.result;
+package cn.sagacloud.android.cadengine.types;
 
 import android.graphics.Bitmap;
 
@@ -8,6 +8,7 @@ import java.io.Serializable;
  * created by lihao on 2018/11/19
  */
 public class Photos implements Serializable {
+    public String id;
     public String type;
     public String name;
     public String key;

+ 7 - 0
cadengine/src/main/java/cn/sagacloud/android/cadengine/types/Point.kt

@@ -1,5 +1,7 @@
 package cn.sagacloud.android.cadengine.types
 
+import java.util.ArrayList
+
 /**
  * Created by lihao.
  * Date: 2021/6/4
@@ -18,4 +20,9 @@ class Point {
     var remark: String? = null
     var type: String? = null
     var position: String? = null
+
+    var spaceId: String? = null
+    var content: String? = null
+    var floorId: String? = null
+    var photos: ArrayList<Photos> = ArrayList()
 }

+ 24 - 1
cadengine/src/main/java/cn/sagacloud/android/cadengine/types/TunableSpace.kt

@@ -10,7 +10,30 @@ class TunableSpace {
     /** 轮廓线  */
     var outLine: ArrayList<ArrayList<PointZ>>? = null
     var name: String? = null
-    var jobStatus: String? = null
+
+    /**
+     *  {
+    "name": "有结构核查任务",
+    "code": "01"
+    },
+    {
+    "name": "有结构问题",
+    "code": "02"
+    },
+    {
+    "name": "结构核查完毕",
+    "code": "03"
+    },
+    {
+    "name": "有现场勘测任务",
+    "code": "04"
+    },
+    {
+    "name": "已完成勘测任务",
+    "code": "05"
+    }
+     */
+    var jobStatus: String = ""
     var id: String? = null
     var localName: String? = null
 }

+ 2 - 0
demo/build.gradle

@@ -254,4 +254,6 @@ dependencies {
     implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0-rc01'
     implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
     implementation 'com.squareup.okhttp3:logging-interceptor:3.14.4'
+
+    debugImplementation 'com.amitshekhar.android:debug-db:1.0.4'
 }

+ 14 - 0
demo/src/main/AndroidManifest.xml

@@ -13,6 +13,8 @@
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 摄像头 -->
     <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.CALL_PHONE" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
 
     <uses-feature android:name="android.hardware.camera" />
     <uses-feature android:name="android.hardware.camera.autofocus" />
@@ -24,9 +26,21 @@
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"
         android:networkSecurityConfig="@xml/network_security_config"
+        android:requestLegacyExternalStorage="true"
         android:roundIcon="@mipmap/ic_launcher_round"
         android:supportsRtl="true"
         android:theme="@style/AppTheme">
+
+        <provider
+            android:name=".tools.MyProvider"
+            android:authorities="com.sybotan.android.demo.fileProvider"
+            android:exported="false"
+            android:grantUriPermissions="true">
+            <meta-data
+                android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/file_paths" />
+        </provider>
+
         <activity
             android:name=".activities.PocActivity"
             android:exported="true">

+ 3 - 0
demo/src/main/java/com/framework/mvvm/model/db/dao/FileDao.kt

@@ -14,6 +14,9 @@ interface FileDao {
     @Query("select * from file where id = :id")
     suspend fun getFileById(id: String): FileEntity
 
+    @Query("select * from file where ref_obj_id = :id")
+    suspend fun getFileByRefId(id: String): List<FileEntity>
+
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     suspend fun insFile(vararg file: FileEntity)
 

+ 3 - 0
demo/src/main/java/com/framework/mvvm/model/db/dao/InfosConfigDao.kt

@@ -14,6 +14,9 @@ interface InfosConfigDao {
     @Query("select * from infos_config where id = :id")
     suspend fun getConfigById(id: String): InfosConfigEntity
 
+    @Query("select * from infos_config where obj_type = :type")
+    suspend fun getConfigByObjType(type: String): List<InfosConfigEntity>
+
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     suspend fun insConfig(vararg config: InfosConfigEntity)
 

+ 3 - 0
demo/src/main/java/com/framework/mvvm/model/db/dao/QrCodeDao.kt

@@ -14,6 +14,9 @@ interface QrCodeDao {
     @Query("select * from qr_code where id = :id")
     suspend fun getQrCodeById(id: String): QrCodeEntity
 
+    @Query("select * from qr_code where obj_id = :id")
+    suspend fun getQrCodeByObjId(id: String): List<QrCodeEntity>
+
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     suspend fun insQrCode(vararg qrCode: QrCodeEntity)
 

+ 14 - 4
demo/src/main/java/com/framework/mvvm/model/db/entity/ObjectEntity.kt

@@ -1,5 +1,6 @@
 package com.framework.mvvm.model.db.entity
 
+import android.graphics.Outline
 import androidx.annotation.NonNull
 import androidx.room.ColumnInfo
 import androidx.room.Entity
@@ -47,15 +48,24 @@ data class ObjectEntity(
     @ColumnInfo(name = "str_infos") var strInfos: String?               // 信息点数据: Json 数据格式
 )
 
-/*
+
 data class Infos(
     val bimId: String,
     val bimLocation: String,
     val codeType: Int,
     val height: Int,
     val modelId: String,
-    val outline: List<List<List<Outline>>>,
+//    val outline: List<List<List<Outline>>>,
     val schemeId: String,
-    val state: String
+    val state: String,
+    val RoomLocalName: String,
+    val unit: String,
+    val group: String,
+    val label: String,
+    val options: ArrayList<Options>,
+    val dataType: String,
+    val inputType: String,
+    val code: String
 )
- */
+
+data class Options(val txt: String, val `val`: String)

+ 1 - 1
demo/src/main/java/com/framework/mvvm/model/db/entity/ProblemArchEntity.kt

@@ -16,7 +16,7 @@ data class ProblemArchEntity(
     @ColumnInfo(name = "geom_type") val geomType: String?,          // 问题记录的几何类型(point|line|polygon)
     @ColumnInfo(name = "work_id") val workId: String?,              // 交付工作流程id
     @ColumnInfo(name = "problem_type") val problemType: String?,    // 问题类型
-    @ColumnInfo(name = "problem_state") val problemState: Int?,     // 建筑结构核查任务状态(0:删除;1:有效;2:已解决)
+    @ColumnInfo(name = "problem_state") var problemState: Int?,     // 建筑结构核查任务状态(0:删除;1:有效;2:已解决)
     @ColumnInfo(name = "message") val message: String?,             // 问题描述
     @ColumnInfo(name = "creator") val creator: String?,             // 创建人
     @ColumnInfo(name = "creation_time") val creationTime: String?,  // 创建时间

+ 33 - 1
demo/src/main/java/com/framework/mvvm/model/repository/AdmRepository.kt

@@ -9,7 +9,7 @@ import com.framework.mvvm.model.data.dataSource
 import com.framework.mvvm.model.data.request
 import com.framework.mvvm.model.data.toDb
 import com.framework.mvvm.model.db.AdmDatabase
-import com.framework.mvvm.model.db.entity.ProjectEntity
+import com.framework.mvvm.model.db.entity.*
 import com.framework.mvvm.model.vo.AdmRequest
 
 class AdmRepository(
@@ -46,6 +46,38 @@ class AdmRepository(
         return db.projectDao().insProject(projects)
     }
 
+    suspend fun insProblem(problem: ProblemArchEntity) {
+        return db.problemArchDao().insProblem(problem)
+    }
+
+    suspend fun getProblem(): List<ProblemArchEntity> {
+        return db.problemArchDao().getProblems()
+    }
+
+    suspend fun getProblemById(id: String): ProblemArchEntity {
+        return db.problemArchDao().getProblemById(id)
+    }
+
+    suspend fun insFile(file: FileEntity) {
+        return db.fileDao().insFile(file)
+    }
+
+    suspend fun getRefFile(refId: String): List<FileEntity> {
+        return db.fileDao().getFileByRefId(refId)
+    }
+
+    suspend fun insQrcode(qrcode: QrCodeEntity) {
+        return db.qrCodeDao().insQrCode(qrcode)
+    }
+
+    suspend fun getQrcode(objId: String): List<QrCodeEntity> {
+        return db.qrCodeDao().getQrCodeByObjId(objId)
+    }
+
+    suspend fun getInfosConfigByObjType(type: String): List<InfosConfigEntity> {
+        return db.infosConfigDao().getConfigByObjType(type)
+    }
+
     suspend fun requestDict(request: AdmRequest) {
         toDb(
             from = { api.getDict(request) },

+ 11 - 9
demo/src/main/java/com/sybotan/android/demo/activities/EquipDetailActivity.kt

@@ -10,22 +10,21 @@ import android.view.MotionEvent
 import android.view.View
 import android.widget.EditText
 import android.widget.ImageView
-import android.widget.TextView
+import androidx.core.widget.NestedScrollView
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.bumptech.glide.Glide
 import com.sybotan.android.demo.R
 import com.sybotan.android.demo.adapter.StaticInfoAdapter
-import com.sybotan.android.demo.bean.result.Photos
+import cn.sagacloud.android.cadengine.types.Photos
+import com.framework.mvvm.model.db.entity.Infos
 import com.sybotan.android.demo.retrofit.Constant
-import com.sybotan.android.demo.tools.LocalDataOperation
 import com.sybotan.android.demo.tools.LocalDataOperation.*
 import com.sybotan.android.demo.tools.PictureUtils
 import com.sybotan.android.demo.tools.ToastUtils
 import com.sybotan.android.demo.tools.UploadImage
 import com.yuyh.library.imgsel.ImageLoader
 import com.yuyh.library.imgsel.ImgSelConfig
-import com.yuyh.library.imgsel.utils.LogUtils
 import io.reactivex.ObservableEmitter
 import org.json.JSONException
 import org.json.JSONObject
@@ -41,6 +40,8 @@ class EquipDetailActivity : BaseActivity(), View.OnTouchListener {
 
     private lateinit var recycler: RecyclerView
     private lateinit var mtextContent: EditText
+    private lateinit var root: NestedScrollView
+    var list = ArrayList<Infos>()
 
     // 自定义图片加载器
     private val loader =
@@ -61,6 +62,7 @@ class EquipDetailActivity : BaseActivity(), View.OnTouchListener {
     private fun initView() {
         recycler = findViewById(R.id.recycler)
         mtextContent = findViewById(R.id.mtextContent)
+        root = findViewById(R.id.root)
         recycler.layoutManager = LinearLayoutManager(this)
         mtextContent.setOnTouchListener(this)
     }
@@ -90,9 +92,7 @@ class EquipDetailActivity : BaseActivity(), View.OnTouchListener {
     }
 
     private fun initData() {
-        var list = ArrayList<Object>()
-        list.add(Object())
-        val adapter = StaticInfoAdapter(this, list as List<Any>?)
+        val adapter = StaticInfoAdapter(this, list)
         adapter.setOnAddPic { addPic() }
         recycler.adapter = adapter
     }
@@ -151,7 +151,8 @@ class EquipDetailActivity : BaseActivity(), View.OnTouchListener {
                                         e.printStackTrace()
                                     }
                                     if ("success" == resultString) {
-                                        val photos = Photos()
+                                        val photos =
+                                            Photos()
                                         photos.itemType = 2
                                         photos.path = path
                                         photos.key = key
@@ -160,7 +161,8 @@ class EquipDetailActivity : BaseActivity(), View.OnTouchListener {
                                     }
                                 }
                             } else {
-                                val photos = Photos()
+                                val photos =
+                                    Photos()
                                 photos.itemType = 2
                                 photos.path = path
                                 photos.key = key

+ 140 - 47
demo/src/main/java/com/sybotan/android/demo/activities/GraphyActivity.kt

@@ -40,6 +40,7 @@ import android.webkit.WebViewClient
 import android.widget.TextView
 import android.widget.Toast
 import android.widget.*
+import androidx.appcompat.widget.AppCompatEditText
 import androidx.appcompat.widget.LinearLayoutCompat
 import androidx.recyclerview.widget.GridLayoutManager
 import androidx.recyclerview.widget.LinearLayoutManager
@@ -56,6 +57,7 @@ import com.arashivision.sdkcamera.camera.InstaCameraManager
 import com.arashivision.sdkcamera.camera.callback.ICameraChangedCallback
 import com.arashivision.sdkcamera.camera.callback.ICaptureStatusListener
 import com.bumptech.glide.Glide
+import com.framework.mvvm.mv.AdmViewModel
 import com.google.gson.Gson
 import com.lzy.okgo.OkGo
 import com.lzy.okgo.callback.FileCallback
@@ -86,6 +88,10 @@ import org.jetbrains.anko.textColor
 import org.jetbrains.anko.uiThread
 import org.json.JSONException
 import org.json.JSONObject
+import org.kodein.di.DI
+import org.kodein.di.DIAware
+import org.kodein.di.android.closestDI
+import org.kodein.di.android.x.viewmodel.viewModel
 import java.io.*
 import java.text.SimpleDateFormat
 import java.util.*
@@ -94,7 +100,7 @@ import kotlin.collections.ArrayList
 
 
 @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
-class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCallback {
+class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCallback, DIAware {
     companion object {
         private val TAG = GraphyActivity::class.java.name
 
@@ -111,6 +117,10 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
         var isAddBaseMap: Boolean = false
     }
 
+    override val di: DI by closestDI()
+
+    private val mVm: AdmViewModel by viewModel()
+
     //选择图片
     private val REQUEST_CODE_PIC = 0X102
 
@@ -131,6 +141,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
 
     /** 楼层Id */
     private lateinit var floorId: String
+    private lateinit var projectId: String
 
     /** 楼层地图 */
     private lateinit var floorMap: String
@@ -234,6 +245,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
     private lateinit var problemSave: TextView
     private lateinit var equipDetail: TextView
     private lateinit var equipDelete: TextView
+    private lateinit var problemDesc: AppCompatEditText
 
     /**
      * 创建Activity时的回调函数
@@ -411,6 +423,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
         problemSave = findViewById(R.id.problemSave)
         equipDetail = findViewById(R.id.equipDetail)
         equipDelete = findViewById(R.id.equipDelete)
+        problemDesc = findViewById(R.id.problemDesc)
 
     }
 
@@ -423,6 +436,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
         floorId = floor.getString("floorId")!!
         floorMap = floor.getString("floorMap")!!
         from = floor.getString("from")!!
+        projectId = floor.getString("projectId")!!
     }
 
     private fun addPic() {
@@ -468,7 +482,8 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
                                         e.printStackTrace()
                                     }
                                     if ("success" == resultString) {
-                                        val photos = Photos()
+                                        val photos =
+                                            Photos()
                                         photos.itemType = 0
                                         photos.path = path
                                         photos.key = key
@@ -477,7 +492,8 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
                                     }
                                 }
                             } else {
-                                val photos = Photos()
+                                val photos =
+                                    Photos()
                                 photos.itemType = 0
                                 photos.path = path
                                 photos.key = key
@@ -789,9 +805,41 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
                             spaceStructure.visibility = View.VISIBLE
                             doneSpaceStructure.visibility = View.GONE
                             graphyVM.getProblem(scene.choseSpace)
+                            /** 跳转空间详情 */
+                            addSpaceDetail.setOnClickListener {
+                                val intent =
+                                    Intent(this@GraphyActivity, SpaceDetailActivity::class.java)
+                                val bundle = Bundle()
+                                bundle.putString("buildingId", buildingId)
+                                bundle.putString("floorId", floorId)
+                                bundle.putString("projectId", projectId)
+                                bundle.putString("spaceId", scene.choseSpace!!.data.id)
+                                intent.putExtra("floor", bundle)
+                                startActivity(intent)
+                            }
                         } else {
                             doneSpaceStructure.visibility = View.VISIBLE
                             spaceStructure.visibility = View.GONE
+                            /** 重置空间状态 */
+                            resetSpaceState.setOnClickListener {
+                                if ("space".equals(from)) {
+                                    graphyVM.setJob(scene.choseSpace, "01")
+                                } else {
+                                    graphyVM.setJob(scene.choseSpace, "04")
+                                }
+                            }
+                            /** 跳转空间详情 */
+                            addSpaceDetail2.setOnClickListener {
+                                val intent =
+                                    Intent(this@GraphyActivity, SpaceDetailActivity::class.java)
+                                val bundle = Bundle()
+                                bundle.putString("buildingId", buildingId)
+                                bundle.putString("floorId", floorId)
+                                bundle.putString("projectId", projectId)
+                                bundle.putString("spaceId", scene.choseSpace!!.data.id)
+                                intent.putExtra("floor", bundle)
+                                startActivity(intent)
+                            }
                         }
                         spaceName.text = scene.choseSpace!!.data.localName
                         spaceName3.text = scene.choseSpace!!.data.localName
@@ -953,9 +1001,12 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
         /** 打点按钮 */
         addDot.setOnClickListener {
             scene.type = "dot"
+            ProblemDot.mX = 0f
+            ProblemDot.mY = 0f
             spaceStructure.visibility = View.GONE
             problemLl.visibility = View.VISIBLE
-            initProblemPicture()
+            showDotDetail(null)
+            initProblemPicture(null)
 
         }
 
@@ -1076,38 +1127,16 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
         eqEqVv.setOnClickListener { skipRelationship("eq_eq_vv", "eq_eq") }
         /** 连接 */
         eqPipeCnct.setOnClickListener { skipRelationship("eq_pipe_cnct", "eq_pipe") }
-        /** 跳转空间详情 */
-        addSpaceDetail.setOnClickListener { startActivity<SpaceDetailActivity>() }
-        /** 跳转空间详情 */
-        addSpaceDetail2.setOnClickListener { startActivity<SpaceDetailActivity>() }
-        /** 重置空间状态 */
-        resetSpaceState.setOnClickListener { }
-        /** 问题-关闭 */
-        problemClose.setOnClickListener {
-            if (addPoint != null) {
-                scene.removeItem(addPoint!!)
-                scene.pointItemList.remove(addPoint)
-            }
-            scene.type = "normal"
-            problemLl.visibility = View.GONE
-        }
-        /** 问题-已解决 */
-        problemDone.setOnClickListener {
-
-        }
-        /** 问题-保存 */
-        problemSave.setOnClickListener {
-            scene.choseSpace?.let { graphyVM.addProblem(it, ProblemDot.mX, ProblemDot.mY) }
-            scene.type = "normal"
-            problemLl.visibility = View.GONE
-        }
     }
 
-    private fun initProblemPicture() {
+    private fun initProblemPicture(point: PointItem?) {
         beans.clear()
         val photo = Photos()
         photo.itemType = 1
         beans.add(photo)
+        if (point != null) {
+            beans.addAll(point.data.photos)
+        }
         pictureAdapter = PictureAdapter(this, beans, "", false, 0, 85)
         pictureAdapter.setOnPicAdd { addPic() }
         problemPicRecycler.setLayoutManager(GridLayoutManager(this, 3))
@@ -1128,7 +1157,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
      * 初始化viewModel
      */
     private fun initViewModel() {
-        graphyVM = GraphyVM(BaseViewModelInterface { name, params ->
+        graphyVM = GraphyVM(this.application, BaseViewModelInterface { name, params ->
             when (name) {
                 /** 查询空间和任务 */
                 GraphyVM.SPACE_JOB -> {
@@ -1137,9 +1166,10 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
                     }
                     scene.tunableSpaceList.clear()
 
+//                    val list = params as (List<SpaceEntity>)
                     val list = params as (List<SpaceJobModel>)
                     for (model in list) {
-                        if (!model.outline.isEmpty()) {
+                        if (!model.outline!!.isEmpty()) {
                             val space = Space()
                             space.outLine = model.outline.get(0)
                             space.name = model.name
@@ -1153,6 +1183,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
                             tunableSpace.apply {
                                 outLine = model.outline.get(0)
                                 this.name = model.name
+//                                initSpaceState(tunableSpace, model.archState!!, model.equipState!!)
                                 jobStatus = model.job
                                 id = model.id
                                 localName = model.localName
@@ -1177,6 +1208,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
 
                 /** 添加空间核查问题 */
                 GraphyVM.ADD_PROBLEM -> {
+                    problemDesc.setText("")
                     Toast.makeText(this, "记录成功", Toast.LENGTH_SHORT).show()
                     graphyVM.getProblem(scene.choseSpace)
                     graphyVM.getSpaceJob(from)
@@ -1214,6 +1246,8 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
                             point.mX = position.x.toFloat()
                             point.mY = position.y.toFloat()
                             point.id = model.id
+                            point.content = model.content
+                            point.photos = model.photos
                             val addPoint = graphyHelper.addPoint(point)
                             addPoint.setOnActionMove(object : PointItem.ActionMove {
                                 override fun onActionMove(event: MotionEvent) {
@@ -1259,7 +1293,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
 
                 /** 设置空间的任务状态(新建和修改) */
                 GraphyVM.SET_JOB -> {
-                    Toast.makeText(this, "核查成功", Toast.LENGTH_SHORT).show()
+                    Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show()
                     refreshAll()
                     graphyVM.getSpaceJob(from)
                 }
@@ -1379,10 +1413,33 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
                     refreshPipe(spacePipeModel)
                 }
             }
-        }, this, buildingId, floorId)
+        }, this, buildingId, floorId, projectId)
         graphyVM.getSpaceJob(from)
     }
 
+    private fun initSpaceState(space: TunableSpace, archState: Int, equipState: Int) {
+        //space 结构核查
+        //survey 空间勘测
+        if ("space".equals(from)) {
+            if (archState == 1) {
+                space.jobStatus = "01";
+            } else if (archState == 2) {
+                space.jobStatus = "03";
+            }
+        } else if ("survey".equals(from)) {
+            if (archState == 1) {
+                space.jobStatus = "01";
+            } else if (archState == 2) {
+                if (equipState == 1) {
+                    space.jobStatus = "04"
+                } else if (equipState == 2) {
+                    space.jobStatus = "05"
+                }
+            }
+        }
+
+    }
+
     val graphyHelper: GraphyHelper = GraphyHelper(scene, this)
 
     /**
@@ -1525,7 +1582,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
     /**
      * 显示点位信息框
      */
-    private fun showDotDetail(point: PointItem) {
+    private fun showDotDetail(point: PointItem?) {
         spaceStructure.visibility = View.GONE
         doneSpaceStructure.visibility = View.GONE
 //        quesDetail.visibility = View.VISIBLE
@@ -1541,23 +1598,59 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
 //        }
 
         problemLl.visibility = View.VISIBLE
-        initProblemPicture()
+        if (point != null) {
+            problemDesc.setText(point.data.content)
+        }
+        initProblemPicture(point)
 
         /** 问题已解决按钮 */
         problemDone.setOnClickListener {
-            graphyVM.closeProblem(point, scene.choseSpace)
-            spaceStructure.visibility = View.VISIBLE
-            quesDetail.visibility = View.GONE
-            problemLl.visibility = View.GONE
-            scene.pointItemList.remove(point)
-            scene.removeItem(point)
-            if (scene.pointItemList.isEmpty()) {
-                for (item in scene.tunableSpaceList) {
-                    scene.removeItem(item)
+            if (point != null) {
+                graphyVM.closeProblem(point, scene.choseSpace)
+                spaceStructure.visibility = View.VISIBLE
+                quesDetail.visibility = View.GONE
+                problemLl.visibility = View.GONE
+                scene.pointItemList.remove(point)
+                scene.removeItem(point)
+                if (scene.pointItemList.isEmpty()) {
+                    for (item in scene.tunableSpaceList) {
+                        scene.removeItem(item)
+                    }
                 }
+                quesDetail.visibility = View.GONE
+                graphyVM.getSpaceJob(from)
+            }
+        }
+
+        /** 问题-关闭 */
+        problemClose.setOnClickListener {
+            if (addPoint != null) {
+                scene.removeItem(addPoint!!)
+                scene.pointItemList.remove(addPoint)
+            }
+            scene.type = "normal"
+            problemLl.visibility = View.GONE
+            spaceStructure.visibility = View.VISIBLE
+        }
+
+        /** 问题-保存 */
+        problemSave.setOnClickListener {
+            if ((point == null || point.data.mX == 0f) && ProblemDot.mX == 0f) {
+                ToastUtils.showMyToast("请扎点")
+                return@setOnClickListener
             }
-            quesDetail.visibility = View.GONE
-            graphyVM.getSpaceJob(from)
+            scene.choseSpace?.let {
+                graphyVM.addProblem(
+                    point,
+                    beans,
+                    problemDesc.text.toString(),
+                    it,
+                    ProblemDot.mX,
+                    ProblemDot.mY
+                )
+            }
+            scene.type = "normal"
+            problemLl.visibility = View.GONE
         }
     }
 

+ 23 - 6
demo/src/main/java/com/sybotan/android/demo/activities/PocActivity.kt

@@ -1,10 +1,13 @@
 package com.sybotan.android.demo.activities
 
 import android.Manifest
+import android.accounts.AccountManager
+import android.content.pm.PackageManager
 import android.os.Bundle
 import androidx.appcompat.app.AppCompatActivity
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.core.app.ActivityCompat
+import androidx.core.content.PermissionChecker.PERMISSION_GRANTED
 import com.framework.mvvm.model.vo.AdmRequest
 import com.framework.mvvm.mv.AdmViewModel
 import com.sybotan.android.demo.R
@@ -71,13 +74,27 @@ class PocActivity : AppCompatActivity(), DIAware {
     }
 
     private fun checkStoragePermission() {
-        ActivityCompat.requestPermissions(
-            this, arrayOf(
-                Manifest.permission.READ_EXTERNAL_STORAGE,
+//        ActivityCompat.requestPermissions(
+//            this, arrayOf(
+//                Manifest.permission.READ_EXTERNAL_STORAGE,
+//                Manifest.permission.WRITE_EXTERNAL_STORAGE
+//            ),
+//            REQUEST_EXTERNAL_STORAGE
+//        )
+        if (ActivityCompat.checkSelfPermission(
+                this,
                 Manifest.permission.WRITE_EXTERNAL_STORAGE
-            ),
-            REQUEST_EXTERNAL_STORAGE
-        )
+            ) != PackageManager.PERMISSION_GRANTED
+        ) {
+            ActivityCompat.requestPermissions(
+                this,
+                arrayOf(
+                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                    Manifest.permission.READ_PHONE_STATE
+                ),
+                1
+            )
+        }
     }
 
 }

+ 42 - 8
demo/src/main/java/com/sybotan/android/demo/activities/SpaceDetailActivity.kt

@@ -7,17 +7,20 @@ import android.os.Bundle
 import android.text.TextUtils
 import android.util.Log
 import android.widget.ImageView
+import androidx.core.widget.NestedScrollView
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.bumptech.glide.Glide
 import com.sybotan.android.demo.R
 import com.sybotan.android.demo.adapter.StaticInfoAdapter
-import com.sybotan.android.demo.bean.result.Photos
+import cn.sagacloud.android.cadengine.types.Photos
+import com.framework.mvvm.model.db.entity.Infos
 import com.sybotan.android.demo.retrofit.Constant
 import com.sybotan.android.demo.tools.LocalDataOperation
 import com.sybotan.android.demo.tools.PictureUtils
 import com.sybotan.android.demo.tools.ToastUtils
 import com.sybotan.android.demo.tools.UploadImage
+import com.sybotan.android.demo.viewmodel.GraphyVM
 import com.yuyh.library.imgsel.ImageLoader
 import com.yuyh.library.imgsel.ImgSelConfig
 import io.reactivex.ObservableEmitter
@@ -30,10 +33,23 @@ import java.io.File
  * Date: 2021/9/27
  */
 class SpaceDetailActivity : BaseActivity() {
+    /** 建筑Id */
+    private lateinit var buildingId: String
+
+    /** 楼层Id */
+    private lateinit var floorId: String
+
+    /** 项目Id */
+    private lateinit var projectId: String
+    private lateinit var spaceId: String
 
     //选择图片
     private val REQUEST_CODE_PIC = 0X102
 
+    /** viewModel */
+    lateinit var graphyVM: GraphyVM
+    var list = ArrayList<Infos>()
+
     // 自定义图片加载器
     private val loader =
         ImageLoader { context: Context?, path: String?, imageView: ImageView? ->
@@ -42,6 +58,7 @@ class SpaceDetailActivity : BaseActivity() {
             ).load(path).into(imageView)
         }
     private lateinit var recycler: RecyclerView
+    private lateinit var root: NestedScrollView
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -51,17 +68,32 @@ class SpaceDetailActivity : BaseActivity() {
         return
     } // Function onCreate()
 
+    private lateinit var staticInfoAdapter: StaticInfoAdapter
+
     private fun initData() {
-        var list = ArrayList<Object>()
-        list.add(Object())
-        val adapter = StaticInfoAdapter(this, list as List<Any>?)
-        adapter.setOnAddPic { addPic() }
-        recycler.adapter = adapter
+        staticInfoAdapter.setOnAddPic { addPic() }
+        recycler.adapter = staticInfoAdapter
+        graphyVM = GraphyVM(this.application, { name, params ->
+            when (name) {
+                GraphyVM.SPACE_INFO -> {
+                    list.addAll(params as ArrayList<Infos>)
+                    staticInfoAdapter.notifyDataSetChanged()
+                }
+            }
+        }, this, buildingId, floorId, projectId)
+        graphyVM.getInfosConfig(spaceId)
     }
 
     private fun initView() {
+        val floor = intent.getBundleExtra("floor")!!
+        buildingId = floor.getString("buildingId")!!
+        floorId = floor.getString("floorId")!!
+        projectId = floor.getString("projectId")!!
+        spaceId = floor.getString("spaceId")!!
         recycler = findViewById(R.id.recycler)
+        root = findViewById(R.id.root)
         recycler.layoutManager = LinearLayoutManager(this)
+        staticInfoAdapter = StaticInfoAdapter(this, list)
     }
 
     private fun addPic() {
@@ -118,7 +150,8 @@ class SpaceDetailActivity : BaseActivity() {
                                         e.printStackTrace()
                                     }
                                     if ("success" == resultString) {
-                                        val photos = Photos()
+                                        val photos =
+                                            Photos()
                                         photos.itemType = 0
                                         photos.path = path
                                         photos.key = key
@@ -127,7 +160,8 @@ class SpaceDetailActivity : BaseActivity() {
                                     }
                                 }
                             } else {
-                                val photos = Photos()
+                                val photos =
+                                    Photos()
                                 photos.itemType = 0
                                 photos.path = path
                                 photos.key = key

+ 1 - 1
demo/src/main/java/com/sybotan/android/demo/activities/poc/DeviceActivity.kt

@@ -115,7 +115,7 @@ class DeviceActivity : BaseActivity() {
 
     private lateinit var mDeviceModel: DeviceVM
     private fun initViewModel() {
-        mDeviceModel = DeviceVM(BaseViewModelInterface { name, params ->
+        mDeviceModel = DeviceVM(this.application, BaseViewModelInterface { name, params ->
             if (name == DeviceVM.DEVICE_ADD) {
                 setResult(RESULT_OK)
                 finish()

+ 1 - 1
demo/src/main/java/com/sybotan/android/demo/activities/poc/DeviceTypeActivity.kt

@@ -38,7 +38,7 @@ class DeviceTypeActivity : BaseActivity() {
     var mType: DeviceType? = null
 
     private fun initViewModel() {
-        val deviceVM = DeviceVM(BaseViewModelInterface { name, params ->
+        val deviceVM = DeviceVM(this.application, BaseViewModelInterface { name, params ->
             val types = params as List<DeviceType>
             val adapter = DeviceTypeAdapter(types, this@DeviceTypeActivity) {
                 mType = it

+ 2 - 2
demo/src/main/java/com/sybotan/android/demo/activities/poc/RelationActivity.kt

@@ -190,7 +190,7 @@ class RelationActivity : BaseActivity() {
     private var mPipe: SpacePipe? = null
     private var mPipeVM: RelationVM? = null
     private fun initViewModel() {
-        mVm = RelationVM(BaseViewModelInterface { name, params ->
+        mVm = RelationVM(this.application, BaseViewModelInterface { name, params ->
 
             when (name) {
                 EQ_SP_SERVE -> {
@@ -227,7 +227,7 @@ class RelationActivity : BaseActivity() {
 
         mVm.getEqs(mSpaceId, code)
 
-        mPipeVM = RelationVM(BaseViewModelInterface { name, params ->
+        mPipeVM = RelationVM(this.application, BaseViewModelInterface { name, params ->
             if (name == EQ_PIPE_CNCT) {
                 val pipes = params as List<SpacePipe>
                 println("pipes: $pipes")

+ 2 - 1
demo/src/main/java/com/sybotan/android/demo/activities/poc/SceneActivity.kt

@@ -29,6 +29,7 @@ class SceneActivity : BaseActivity() {
             bundle.putString("buildingId", floor.buildingId)
             bundle.putString("floorId", floor.id)
             bundle.putString("floorMap", floor.infos.floorMap)
+            bundle.putString("projectId", floor.projectId)
             bundle.putString("from", "scene")
             intent.putExtra("floor", bundle)
             startActivity(intent)
@@ -44,7 +45,7 @@ class SceneActivity : BaseActivity() {
 
     private lateinit var mBuilds: List<Build>
     private fun initViewModel() {
-        val vm = BuildVM(BaseViewModelInterface { name, params ->
+        val vm = BuildVM(this.application,BaseViewModelInterface { name, params ->
             mBuilds = params as List<Build>
             val floors = sep(mBuilds)
             val adapter = ExpandAdapter(this, mBuilds, floors)

+ 2 - 1
demo/src/main/java/com/sybotan/android/demo/activities/poc/SpaceActivity.kt

@@ -37,6 +37,7 @@ class SpaceActivity : BaseActivity() {
             bundle.putString("floorId", floor.id)
             bundle.putString("floorMap", floor.infos.floorMap)
             bundle.putString("from", "space")
+            bundle.putString("projectId", floor.projectId)
             intent.putExtra("floor", bundle)
             startActivity(intent)
             true
@@ -50,7 +51,7 @@ class SpaceActivity : BaseActivity() {
 
     private lateinit var mBuilds: List<Build>
     private fun initViewModel() {
-        val vm = BuildVM(BaseViewModelInterface { name, params ->
+        val vm = BuildVM(this.application, BaseViewModelInterface { name, params ->
             mBuilds = params as List<Build>
             val floors = sep(mBuilds)
             val adapter = ExpandAdapter(this, mBuilds, floors)

+ 6 - 12
demo/src/main/java/com/sybotan/android/demo/adapter/PictureAdapter.java

@@ -10,21 +10,16 @@ import android.view.ViewGroup;
 import android.widget.ImageView;
 
 
-import com.bumptech.glide.Glide;
-import com.bumptech.glide.load.engine.DiskCacheStrategy;
 import com.sybotan.android.demo.R;
 import com.sybotan.android.demo.activities.LookBigPicActivity;
-import com.sybotan.android.demo.bean.result.Photos;
+import cn.sagacloud.android.cadengine.types.Photos;
 import com.sybotan.android.demo.retrofit.Constant;
 import com.sybotan.android.demo.tools.CommonUtils;
 import com.sybotan.android.demo.tools.DensityUtils;
-import com.sybotan.android.demo.tools.LocalDataOperation;
+import com.sybotan.android.demo.tools.GlideApp;
 import com.tencent.smtt.sdk.ui.dialog.widget.RoundImageView;
 
-import org.greenrobot.eventbus.EventBus;
-
 import java.io.ByteArrayOutputStream;
-import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.util.List;
@@ -75,15 +70,14 @@ public class PictureAdapter extends BaseRecyclerViewAdapter<Photos> {
                 FileInputStream fis = null;
                 try {
                     fis = new FileInputStream(photos.path);
+                    Bitmap bitmap = BitmapFactory.decodeStream(fis);
+                    ImageView imageView = (ImageView) holder.getView(R.id.node_nine_pic_iv);
+                    imageView.setImageBitmap(bitmap);
                 } catch (FileNotFoundException e) {
                     e.printStackTrace();
                     loadImageViewCornersByPath(mContext, url, holder.getView(R.id.node_nine_pic_iv));
                 }
 
-                Bitmap bitmap = BitmapFactory.decodeStream(fis);
-                ImageView imageView = (ImageView) holder.getView(R.id.node_nine_pic_iv);
-                imageView.setImageBitmap(bitmap);
-
                 holder.getView(R.id.node_nine_pic_iv).setOnClickListener(v -> {
                     Intent intent = new Intent(mContext, LookBigPicActivity.class);
                     intent.putExtra("url", url);
@@ -139,7 +133,7 @@ public class PictureAdapter extends BaseRecyclerViewAdapter<Photos> {
             mImageView.setImageResource(R.mipmap.image_error_icon);
             return;
         }
-        Glide.with(mContext)
+        GlideApp.with(mContext)
                 .load(path)
                 .into(mImageView);
     }

+ 20 - 7
demo/src/main/java/com/sybotan/android/demo/adapter/SelectPopListAdapter.java

@@ -2,20 +2,22 @@ package com.sybotan.android.demo.adapter;
 
 import android.annotation.SuppressLint;
 import android.content.Context;
-import android.text.TextUtils;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
 import android.widget.LinearLayout;
+import android.widget.RadioButton;
 import android.widget.TextView;
 
 import androidx.recyclerview.widget.RecyclerView;
 
 
+import com.framework.mvvm.model.db.entity.Options;
 import com.sybotan.android.demo.R;
 import com.sybotan.android.demo.retrofit.Constant;
-import com.sybotan.android.demo.view.SelectListPopupWindow;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -51,7 +53,8 @@ public class SelectPopListAdapter extends RecyclerView.Adapter<SelectPopListAdap
     public void onBindViewHolder(final BuildViewHolder holder, @SuppressLint("RecyclerView") final int position) {
         final Object item = items.get(position);
         if (type.equals(Constant.TYPE1)) {
-            holder.choice_name.setText((String) item);
+            Options options = (Options) item;
+            holder.choice_name.setText(options.getTxt());
         }
         if (selectPosition > 0 && selectPosition - 1 == position) {
             holder.choice_name.setTextColor(context.getResources().getColor(R.color.blue_2f48b7));
@@ -63,14 +66,22 @@ public class SelectPopListAdapter extends RecyclerView.Adapter<SelectPopListAdap
         } else if (isRed) {
             holder.choice_name.setTextColor(context.getResources().getColor(R.color.black_272727));
         }
-        holder.choice_layout.setOnClickListener(new View.OnClickListener() {
+        holder.radioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
             @Override
-            public void onClick(View v) {
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                 if (mOnItemClickListener != null) {
-                    mOnItemClickListener.onItemClick(holder.choice_layout, position);
+                    mOnItemClickListener.onItemClick(holder.choice_layout, position, isChecked);
                 }
             }
         });
+//        holder.choice_layout.setOnClickListener(new View.OnClickListener() {
+//            @Override
+//            public void onClick(View v) {
+//                if (mOnItemClickListener != null) {
+//                    mOnItemClickListener.onItemClick(holder.choice_layout, position);
+//                }
+//            }
+//        });
 //        if (flag) {
 //            holder.choice_name.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
 //        } else {
@@ -98,11 +109,13 @@ public class SelectPopListAdapter extends RecyclerView.Adapter<SelectPopListAdap
     static class BuildViewHolder extends BaseViewHolder {
         TextView choice_name;
         LinearLayout choice_layout;
+        CheckBox radioButton;
 
         public BuildViewHolder(View mRootView) {
             super(mRootView);
             choice_name = (TextView) mRootView.findViewById(R.id.choice_name);
             choice_layout = (LinearLayout) mRootView.findViewById(R.id.choice_layout);
+            radioButton = (CheckBox) mRootView.findViewById(R.id.radioButton);
 
         }
     }
@@ -114,6 +127,6 @@ public class SelectPopListAdapter extends RecyclerView.Adapter<SelectPopListAdap
     }
 
     public interface OnRecyclerViewItemClickListener {
-        void onItemClick(View view, int position);
+        void onItemClick(View view, Integer position, boolean isChecked);
     }
 }

+ 175 - 41
demo/src/main/java/com/sybotan/android/demo/adapter/StaticInfoAdapter.java

@@ -1,29 +1,47 @@
 package com.sybotan.android.demo.adapter;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.graphics.Color;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.Gravity;
+import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.Button;
+import android.widget.EditText;
 
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.bigkoo.pickerview.builder.TimePickerBuilder;
 import com.bigkoo.pickerview.view.TimePickerView;
+import com.framework.mvvm.model.db.entity.Infos;
+import com.framework.mvvm.model.db.entity.Options;
 import com.sybotan.android.demo.R;
-import com.sybotan.android.demo.bean.result.Photos;
+
+import cn.sagacloud.android.cadengine.types.Photos;
+
+import com.sybotan.android.demo.retrofit.Constant;
+import com.sybotan.android.demo.tools.CommonUtils;
+import com.sybotan.android.demo.view.CommonNumberControl;
 import com.sybotan.android.demo.view.ListItemView;
+import com.sybotan.android.demo.view.SelectListPopupWindow;
 
 import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.HashMap;
 import java.util.List;
 
 /**
  * Created by lihao.
  * Date: 2021/9/26
  */
-public class StaticInfoAdapter extends BaseRecyclerViewAdapter<Object> {
+public class StaticInfoAdapter extends BaseRecyclerViewAdapter<Infos> {
+    /**
+     * text|textarea|radio|checkbox|picker|setpper|switch|date|photo|file
+     */
+    public HashMap<String, Object> hashMap = new HashMap<>();
     public static final int TEXT = 1;
     public static final int INT = 2;
     public static final int DOUBLE = 3;
@@ -35,7 +53,7 @@ public class StaticInfoAdapter extends BaseRecyclerViewAdapter<Object> {
     private TimePickerView pvTime;
     private AddPic addPic;
 
-    public StaticInfoAdapter(Context context, List<Object> beans) {
+    public StaticInfoAdapter(Context context, List<Infos> beans) {
         super(context, beans);
     }
 
@@ -63,64 +81,180 @@ public class StaticInfoAdapter extends BaseRecyclerViewAdapter<Object> {
     }
 
     @Override
-    protected void onBindDataToView(ViewHolder holder, Object o) {
-        List<Photos> beans = new ArrayList<>();
-        Photos photo = new Photos();
-        photo.itemType = 1;
-        beans.add(photo);
-        PictureAdapter pictureAdapter = new PictureAdapter(mContext, beans, "", false, holder.getCurrentPosition(), 85);
-        pictureAdapter.setOnPicAdd(new PictureAdapter.PicAdd() {
-            @Override
-            public void onPicAdd() {
-                if (addPic != null) {
-                    addPic.onAddPic();
+    protected void onBindDataToView(ViewHolder holder, Infos info) {
+        switch (info.getInputType()) {
+            case "text":
+                ListItemView textItemView = holder.getView(R.id.view_text);
+                textItemView.setTvLeft(info.getLabel());
+                EditText etRight = textItemView.findViewById(R.id.et_right);
+                initEditTextTouch(etRight, info);
+            case "textarea":
+                holder.setText(R.id.mtext_title, info.getLabel());
+                EditText mtextContent = holder.getView(R.id.mtextContent);
+                initEditTextTouch(mtextContent, info);
+            case "radio":
+            case "picker":
+                ListItemView enumItemView = holder.getView(R.id.view_enum);
+                enumItemView.setTvLeft(info.getLabel());
+                enumItemView.setTvRight("请选择");
+                enumItemView.getView(R.id.tv_right).setOnClickListener(v -> {
+                    SelectListPopupWindow popupWindow = new SelectListPopupWindow(mContext);
+                    popupWindow.setList(info.getOptions(), Constant.TYPE1);
+                    popupWindow.setOnCommit(new SelectListPopupWindow.Commit() {
+                        @Override
+                        public void onCommit(ArrayList<Integer> list) {
+                            ArrayList<Options> arrayList = new ArrayList<>();
+                            StringBuilder sb = new StringBuilder();
+                            for (int i = 0; i < list.size(); i++) {
+                                sb.append(info.getOptions().get(i).getTxt()).append("、");
+                                arrayList.add(info.getOptions().get(i));
+                            }
+                            hashMap.put(info.getCode(), arrayList);
+                            enumItemView.setTvRight(sb.toString());
+                        }
+                    });
+                    popupWindow.showAtLocation(enumItemView, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
+                });
+            case "setpper":
+//                return INT;
+                ListItemView intItemView = holder.getView(R.id.view_int);
+                intItemView.setTvLeft(info.getLabel());
+                CommonNumberControl numberControl = (CommonNumberControl) intItemView.getView(R.id.et_right);
+                initEditTextTouch(numberControl.getEditText(), info);
+            case "photo":
+                List<Photos> beans = new ArrayList<>();
+                Photos photo = new Photos();
+                photo.itemType = 1;
+                beans.add(photo);
+                PictureAdapter pictureAdapter = new PictureAdapter(mContext, beans, "", false, holder.getCurrentPosition(), 85);
+                pictureAdapter.setOnPicAdd(new PictureAdapter.PicAdd() {
+                    @Override
+                    public void onPicAdd() {
+                        if (addPic != null) {
+                            addPic.onAddPic();
+                        }
+                    }
+                });
+                RecyclerView recycler = holder.getView(R.id.recycler);
+                recycler.setLayoutManager(new GridLayoutManager(mContext, 3));
+                recycler.setAdapter(pictureAdapter);
+//                return PICTURE;
+            case "date":
+//                return DATE;
+                ListItemView listItemView = holder.getView(R.id.view_date);
+                listItemView.setTvLeft(info.getLabel());
+                listItemView.getView(R.id.tv_right).setOnClickListener(v -> {
+                    pvTime.show(true);
+                });
+                initTimePicker();
+            default:
+                if (!CommonUtils.IsNull(info.getOptions())) {
+//                    return ENUM;
+                    ListItemView enumItemView2 = holder.getView(R.id.view_enum);
+                    enumItemView2.setTvLeft(info.getLabel());
+                    enumItemView2.setTvRight("请选择");
+                    enumItemView2.getView(R.id.tv_right).setOnClickListener(v -> {
+                        SelectListPopupWindow popupWindow = new SelectListPopupWindow(mContext);
+                        popupWindow.setList(info.getOptions(), Constant.TYPE1);
+                        popupWindow.setOnCommit(new SelectListPopupWindow.Commit() {
+                            @Override
+                            public void onCommit(ArrayList<Integer> list) {
+                                ArrayList<Options> arrayList = new ArrayList<>();
+                                StringBuilder sb = new StringBuilder();
+                                for (int i = 0; i < list.size(); i++) {
+                                    sb.append(info.getOptions().get(i).getTxt()).append("、");
+                                    arrayList.add(info.getOptions().get(i));
+                                }
+                                hashMap.put(info.getCode(), arrayList);
+                                enumItemView2.setTvRight(sb.toString());
+                            }
+                        });
+                        popupWindow.showAtLocation(enumItemView2, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
+                    });
+                } else {
+//                    return MTEXT;
+                    holder.setText(R.id.mtext_title, info.getLabel());
+                    EditText mtextContent2 = holder.getView(R.id.mtextContent);
+                    initEditTextTouch(mtextContent2, info);
                 }
-            }
-        });
-        RecyclerView recycler = holder.getView(R.id.recycler);
-        recycler.setLayoutManager(new GridLayoutManager(mContext, 3));
-        recycler.setAdapter(pictureAdapter);
+
+        }
+
 //        switch (o.hashCode()) {
 //            case TEXT:
+//
 //                break;
 //            case INT:
+//
 //                break;
 //            case DOUBLE:
+//                ListItemView doubleItemView = holder.getView(R.id.view_double);
 //                break;
 //            case ENUM:
+//
 //                break;
 //            case DATE:
-//                ListItemView listItemView = holder.getView(R.id.view_date);
-//                listItemView.getView(R.id.tv_right).setOnClickListener(v -> {
-//                    pvTime.show(true);
-//                });
+//
 //                break;
 //            case MTEXT:
+//
 //                break;
 //            case PICTURE:
-//                List<Photos> beans = new ArrayList<>();
-//                Photos photo = new Photos();
-//                photo.itemType = 1;
-//                beans.add(photo);
-//                PictureAdapter pictureAdapter = new PictureAdapter(mContext, beans, "", false, holder.getCurrentPosition(), 85);
-//                pictureAdapter.setOnPicAdd(new PictureAdapter.PicAdd() {
-//                    @Override
-//                    public void onPicAdd() {
-//                        if (addPic != null) {
-//                            addPic.onAddPic();
-//                        }
-//                    }
-//                });
-//                RecyclerView recycler = holder.getView(R.id.recycler);
-//                recycler.setLayoutManager(new GridLayoutManager(mContext, 3));
-//                recycler.setAdapter(pictureAdapter);
+//
 //                break;
 //        }
     }
 
+    @SuppressLint("ClickableViewAccessibility")
+    private void initEditTextTouch(EditText editText, Infos info) {
+        editText.setOnTouchListener((v, event) -> {
+            if (MotionEvent.ACTION_DOWN == event.getAction()) {
+                v.getParent().requestDisallowInterceptTouchEvent(true);
+            } else if (MotionEvent.ACTION_UP == event.getAction()) {
+                v.getParent().requestDisallowInterceptTouchEvent(false);
+            }
+            return false;
+        });
+        editText.addTextChangedListener(new TextWatcher() {
+            @Override
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+            }
+
+            @Override
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+            }
+
+            @Override
+            public void afterTextChanged(Editable s) {
+                hashMap.put(info.getCode(), s.toString());
+            }
+        });
+    }
+
     @Override
     public int getItemViewType(int position) {
-        return PICTURE;
+        switch (mBeans.get(position).getInputType()) {
+            case "text":
+                return TEXT;
+            case "textarea":
+                return MTEXT;
+            case "radio":
+            case "picker":
+                return ENUM;
+            case "setpper":
+                return INT;
+            case "photo":
+                return PICTURE;
+            case "date":
+                return DATE;
+            default:
+                if (!CommonUtils.IsNull(mBeans.get(position).getOptions())) {
+                    return ENUM;
+                }
+                return MTEXT;
+        }
     }
 
     public void initTimePicker() {

+ 3 - 2
demo/src/main/java/com/sybotan/android/demo/adapter/ViewPagerImageAdapter.java

@@ -15,6 +15,7 @@ import com.bumptech.glide.Glide;
 import com.sybotan.android.demo.retrofit.API;
 import com.sybotan.android.demo.retrofit.Constant;
 import com.sybotan.android.demo.tools.CommonUtils;
+import com.sybotan.android.demo.tools.GlideApp;
 import com.sybotan.android.demo.tools.PhotoViewAttacher;
 import com.sybotan.android.demo.tools.ToastUtils;
 
@@ -98,14 +99,14 @@ public class ViewPagerImageAdapter extends PagerAdapter {
 
     public static void loadImage(Context context, String path, ImageView imageView, boolean isFile) {
         if (isFile) {
-            Glide.with(context)
+            GlideApp.with(context)
                     .load(new File(path))
                     .into(imageView);
         } else {
             if (path.contains("key=null") || path.endsWith("key=")) {
                 return;
             }
-            Glide.with(context)
+            GlideApp.with(context)
                     .load(path)
 //                    .override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
 //                    .signature(new ObjectKey(String.valueOf(System.currentTimeMillis())))

+ 6 - 0
demo/src/main/java/com/sybotan/android/demo/bean/result/ProblemsModel.java

@@ -1,5 +1,10 @@
 package com.sybotan.android.demo.bean.result;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import cn.sagacloud.android.cadengine.types.Photos;
+
 /**
  * Created by lihao.
  * Date: 2021/6/9
@@ -10,4 +15,5 @@ public class ProblemsModel {
     public String content;
     public String floorId;
     public String position;
+    public ArrayList<Photos> photos = new ArrayList<>();
 }

+ 1 - 1
demo/src/main/java/com/sybotan/android/demo/retrofit/API.java

@@ -8,10 +8,10 @@ import com.sybotan.android.demo.entitiies.*;
 import java.util.ArrayList;
 import java.util.List;
 
+import com.sybotan.android.demo.bean.result.ProblemsModel;
 import io.reactivex.Observable;
 import okhttp3.RequestBody;
 import retrofit2.http.Body;
-import retrofit2.http.GET;
 import retrofit2.http.POST;
 
 /**

+ 72 - 0
demo/src/main/java/com/sybotan/android/demo/tools/IdGenerator.java

@@ -0,0 +1,72 @@
+package com.sybotan.android.demo.tools;
+
+
+import android.text.TextUtils;
+
+import java.util.UUID;
+
+
+/**
+ * 实体对象id生成器
+ */
+public class IdGenerator {
+
+    public static final String PROJECT = "project"; //项目
+    public static final String BUILDING = "building"; //建筑
+    public static final String FLOOR = "floor"; //"楼层"),
+    public static final String SPACE = "space"; //空间
+    public static final String SYSTEM = "system"; //系统
+    public static final String EQUIPMENT = "equipment"; //设备
+    public static final String SHAFT = "shaft"; //竖井
+    public static final String COMPONENT = "component"; //部件
+    public static final String VIRTUAL = "virtual"; //虚拟对象
+    public static final String TOOL = "tool"; //工具
+    public static final String MATERIAL = "material"; //耗材
+
+    /**
+     * 生成对象id
+     *
+     * @param projectId 项目id
+     * @param objType   对象类型
+     * @return 两位prefix + 无前缀projectId + 无分隔符的32位uuid
+     */
+    public static String getId(String projectId, String objType) {
+        if (PROJECT.equals(objType))
+            return projectId;
+
+        String prefix = getPrefix(objType);
+        if (TextUtils.isEmpty(prefix))
+            return UUID.randomUUID().toString().replace("-", "");
+
+        return prefix + projectId.substring(2) + UUID.randomUUID().toString();
+    }
+
+    private static String getPrefix(String objType) {
+        switch (objType) {
+            case PROJECT:
+                return "Pj";
+            case BUILDING:
+                return "Bd";
+            case FLOOR:
+                return "Fl";
+            case SPACE:
+                return "Sp";
+            case SYSTEM:
+                return "Sy";
+            case EQUIPMENT:
+                return "Eq";
+            case SHAFT:
+                return "Sh";
+            case COMPONENT:
+                return "Ec";
+            case VIRTUAL:
+                return "Vo";
+            case TOOL:
+                return "To";
+            case MATERIAL:
+                return "Ma";
+        }
+        return null;
+    }
+
+}

+ 65 - 0
demo/src/main/java/com/sybotan/android/demo/tools/MyGlideModules.java

@@ -0,0 +1,65 @@
+package com.sybotan.android.demo.tools;
+
+import android.content.Context;
+import android.os.Environment;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.GlideBuilder;
+import com.bumptech.glide.Registry;
+import com.bumptech.glide.annotation.Excludes;
+import com.bumptech.glide.annotation.GlideModule;
+import com.bumptech.glide.integration.okhttp3.OkHttpLibraryGlideModule;
+import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
+import com.bumptech.glide.load.DecodeFormat;
+import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory;
+import com.bumptech.glide.load.engine.cache.LruResourceCache;
+import com.bumptech.glide.load.model.GlideUrl;
+import com.bumptech.glide.module.AppGlideModule;
+import com.bumptech.glide.request.RequestOptions;
+import com.sybotan.android.demo.retrofit.Constant;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.OkHttpClient;
+
+/**
+ * Created by mengxy on 2017/8/25.
+ */
+@Excludes(value = OkHttpLibraryGlideModule.class)
+@GlideModule
+public class MyGlideModules extends AppGlideModule{
+
+    @Override
+    public void applyOptions(Context context, GlideBuilder builder) {
+        //自定义缓存目录
+        builder.setDiskCache(new InternalCacheDiskCacheFactory(context,
+                getFilePath(),
+                Constant.GLIDE_CATCH_SIZE));
+        int maxMemory = (int) Runtime.getRuntime().maxMemory();//获取系统分配给应用的总内存大小
+        int memoryCacheSize = maxMemory / 8;//设置图片内存缓存占用八分之一
+        //设置内存缓存大小
+        builder.setMemoryCache(new LruResourceCache(memoryCacheSize));
+        builder.setDefaultRequestOptions(RequestOptions.formatOf(DecodeFormat.PREFER_RGB_565));
+    }
+
+    private String getFilePath(){
+        String saveDir = Environment.getExternalStorageDirectory() + Constant.GLIDE_CARCH_DIR;
+        // 新建目录
+        File dir = new File(saveDir);
+        if (! dir.exists()) dir.mkdirs();
+        return saveDir;
+    }
+
+    @Override
+    public void registerComponents(Context context, Glide glide, Registry registry) {
+        // 配置glide网络加载框架,用okhttp取代原先的httpconnection
+        OkHttpClient okHttpClient = new OkHttpClient.Builder()
+                .connectTimeout(30, TimeUnit.SECONDS)
+                .readTimeout(30,TimeUnit.SECONDS)
+                .writeTimeout(30,TimeUnit.SECONDS)
+                .build();
+        registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(okHttpClient));
+    }
+}

+ 9 - 0
demo/src/main/java/com/sybotan/android/demo/tools/MyProvider.java

@@ -0,0 +1,9 @@
+package com.sybotan.android.demo.tools;
+
+import androidx.core.content.FileProvider;
+
+/**
+ * Created by Administrator on 2018/6/11.
+ */
+public class MyProvider extends FileProvider {
+}

+ 28 - 9
demo/src/main/java/com/sybotan/android/demo/view/SelectListPopupWindow.java

@@ -4,7 +4,6 @@ package com.sybotan.android.demo.view;
  * Created by cunwen on 16/3/25.
  */
 
-import android.app.Activity;
 import android.content.Context;
 import android.graphics.drawable.ColorDrawable;
 import android.util.DisplayMetrics;
@@ -25,6 +24,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.sybotan.android.demo.R;
+import com.sybotan.android.demo.activities.BaseActivity;
 import com.sybotan.android.demo.adapter.SelectPopListAdapter;
 import com.sybotan.android.demo.tools.AnimateUtil;
 
@@ -48,15 +48,16 @@ public class SelectListPopupWindow extends PopupWindow {
     private Animation outAnim;
 
     SelectPopListAdapter adapter;
-    public ArrayList<String> list = new ArrayList<String>();
+    public ArrayList<Integer> list = new ArrayList<>();
     public int position = -1;
+    private Commit commit;
 
-    public SelectListPopupWindow(Activity context, OnClickListener itemsOnClick) {
+    public SelectListPopupWindow(Context context) {
         super(context);
         this.context = context;
 
         dm = new DisplayMetrics();
-        context.getWindowManager().getDefaultDisplay().getMetrics(dm);
+        ((BaseActivity)context).getWindowManager().getDefaultDisplay().getMetrics(dm);
         initAnimation();
 
         LayoutInflater inflater = (LayoutInflater) context
@@ -75,7 +76,16 @@ public class SelectListPopupWindow extends PopupWindow {
             }
         });
         //设置按钮监听
-        btn1.setOnClickListener(itemsOnClick);
+//        btn1.setOnClickListener(itemsOnClick);
+        btn1.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                if (commit != null) {
+                    commit.onCommit(list);
+                }
+                dismiss();
+            }
+        });
         btn1.setTag(0);
 
         recyclerview = (RecyclerView) mMenuView.findViewById(R.id.recyclerview);
@@ -87,11 +97,12 @@ public class SelectListPopupWindow extends PopupWindow {
         adapter = new SelectPopListAdapter();
         adapter.setOnItemClickListener(new SelectPopListAdapter.OnRecyclerViewItemClickListener() {
             @Override
-            public void onItemClick(View view, int position) {
-                if (mOnItemClickListener != null) {
-                    mOnItemClickListener.onItemClick(position);
+            public void onItemClick(View view, Integer position, boolean isChecked) {
+                if (isChecked) {
+                    list.add(position);
+                } else {
+                    list.remove(position);
                 }
-                dismiss();
             }
         });
         recyclerview.setAdapter(adapter);
@@ -241,4 +252,12 @@ public class SelectListPopupWindow extends PopupWindow {
         void onItemClick(int position);
     }
 
+    public interface Commit {
+        void onCommit(ArrayList<Integer> list);
+    }
+
+    public void setOnCommit(Commit commit) {
+        this.commit = commit;
+    }
+
 }

+ 11 - 6
demo/src/main/java/com/sybotan/android/demo/viewmodel/BaseViewModel.java

@@ -1,8 +1,10 @@
 package com.sybotan.android.demo.viewmodel;
 
 
+import android.app.Application;
 
-
+import androidx.annotation.NonNull;
+import androidx.lifecycle.AndroidViewModel;
 import androidx.lifecycle.LifecycleOwner;
 import androidx.lifecycle.MutableLiveData;
 import androidx.lifecycle.ViewModel;
@@ -32,7 +34,7 @@ import okhttp3.RequestBody;
 /**
  * Created by lihao on 2020/7/9.
  */
-public class BaseViewModel extends ViewModel implements IViewModelAction {
+public class BaseViewModel extends AndroidViewModel implements IViewModelAction {
     public BaseActivity mActivity;
     private MutableLiveData<BaseActionEvent> baseActionEventLiveData;
     protected LifecycleOwner lifecycleOwner;
@@ -41,12 +43,14 @@ public class BaseViewModel extends ViewModel implements IViewModelAction {
     private BaseViewModel baseViewModel;
     public ArrayList<UniversalCellClass> data_Array = new ArrayList<>();
 
-    public BaseViewModel() {
+    public BaseViewModel(Application app) {
+        super(app);
         baseActionEventLiveData = new MutableLiveData<>();
     }
 
 
-    public BaseViewModel(BaseViewModelInterface object, BaseActivity activity) {
+    public BaseViewModel(Application app,BaseViewModelInterface object, BaseActivity activity) {
+        this(app);
         this.mEmitter = object;
         this.mGSon = new Gson();
         baseActionEventLiveData = new MutableLiveData<>();
@@ -68,7 +72,7 @@ public class BaseViewModel extends ViewModel implements IViewModelAction {
         if (isNeedProgress) {
             showLoading("");
         }
-        observable.compose(compose(mActivity.<BaseModel<S>>bindToLifecycle(),bo)).subscribe(observer);
+        observable.compose(compose(mActivity.<BaseModel<S>>bindToLifecycle(), bo)).subscribe(observer);
     }
 
     private <T> ObservableTransformer<T, T> compose(final LifecycleTransformer<T> lifecycle) {
@@ -84,7 +88,8 @@ public class BaseViewModel extends ViewModel implements IViewModelAction {
                 .observeOn(AndroidSchedulers.mainThread())//改变调用它之后代码的线程  指定的就是订阅者接收事件的线程
                 .compose(lifecycle);
     }
-    private <T> ObservableTransformer<T, T> compose(final LifecycleTransformer<T> lifecycle ,boolean type) {
+
+    private <T> ObservableTransformer<T, T> compose(final LifecycleTransformer<T> lifecycle, boolean type) {
         return observable -> observable
                 .subscribeOn(Schedulers.io())
                 .doOnSubscribe(disposable -> {

+ 3 - 1
demo/src/main/java/com/sybotan/android/demo/viewmodel/BuildVM.kt

@@ -1,12 +1,14 @@
 package com.sybotan.android.demo.viewmodel
 
+import android.app.Application
 import com.sybotan.android.demo.activities.BaseActivity
 import com.sybotan.android.demo.entitiies.Build
 import com.sybotan.android.demo.retrofit.BaseObserver
 import com.sybotan.android.demo.retrofit.BaseViewModelInterface
 import com.sybotan.android.demo.retrofit.RetrofitFactory
 
-class BuildVM(b: BaseViewModelInterface, a: BaseActivity) : BaseViewModel(b, a) {
+class BuildVM(app: Application, b: BaseViewModelInterface, a: BaseActivity) :
+    BaseViewModel(app, b, a) {
     companion object {
         const val BUILD_TYPE = "BUILD_TYPE"
     }

+ 2 - 1
demo/src/main/java/com/sybotan/android/demo/viewmodel/DeviceVM.kt

@@ -1,5 +1,6 @@
 package com.sybotan.android.demo.viewmodel
 
+import android.app.Application
 import com.sybotan.android.demo.activities.BaseActivity
 import com.sybotan.android.demo.bean.request.ReqDeviceJob
 import com.sybotan.android.demo.bean.result.ResDeviceModel
@@ -8,7 +9,7 @@ import com.sybotan.android.demo.retrofit.BaseObserver
 import com.sybotan.android.demo.retrofit.BaseViewModelInterface
 import com.sybotan.android.demo.retrofit.RetrofitFactory
 
-class DeviceVM(b: BaseViewModelInterface, a: BaseActivity) : BaseViewModel(b, a) {
+class DeviceVM(app: Application, b: BaseViewModelInterface, a: BaseActivity) : BaseViewModel(app,b, a) {
     companion object {
         const val DEVICE_TYPE = "DEVICE_TYPE"
         const val DEVICE_ADD = "DEVICE_ADD"

+ 257 - 56
demo/src/main/java/com/sybotan/android/demo/viewmodel/GraphyVM.kt

@@ -1,17 +1,36 @@
 package com.sybotan.android.demo.viewmodel
 
+import android.app.Application
 import android.graphics.PointF
+import android.text.TextUtils
+import androidx.lifecycle.viewModelScope
 import cn.sagacloud.android.cadengine.items.PointItem
 import cn.sagacloud.android.cadengine.items.TunableSpaceItem
+import cn.sagacloud.android.cadengine.types.Photos
 import cn.sagacloud.android.cadengine.types.Point
+import cn.sagacloud.android.cadengine.types.PointZ
+import com.arashivision.arvbmg.shandowclone.TrackTarget
+import com.framework.mvvm.model.db.entity.*
+import com.framework.mvvm.model.repository.AdmRepository
+import com.sybotan.android.demo.bean.result.ProblemsModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
 import com.sybotan.android.demo.activities.BaseActivity
 import com.sybotan.android.demo.bean.request.*
 import com.sybotan.android.demo.bean.result.*
 import com.sybotan.android.demo.bean.result.Position
 import com.sybotan.android.demo.bean.result.Z
+import com.sybotan.android.demo.entitiies.Info
 import com.sybotan.android.demo.retrofit.BaseObserver
 import com.sybotan.android.demo.retrofit.BaseViewModelInterface
 import com.sybotan.android.demo.retrofit.RetrofitFactory
+import kotlinx.coroutines.launch
+import org.kodein.di.DI
+import org.kodein.di.DIAware
+import org.kodein.di.android.x.closestDI
+import org.kodein.di.instance
+import java.text.SimpleDateFormat
+import java.util.*
 import kotlin.collections.ArrayList
 
 /**
@@ -19,10 +38,16 @@ import kotlin.collections.ArrayList
  * Date: 2021/6/9
  */
 class GraphyVM(
+    app: Application,
     b: BaseViewModelInterface?, activity: BaseActivity?, //建筑id
     private val buildingId: String, //楼层id
-    private val floorId: String
-) : BaseViewModel(b, activity) {
+    private val floorId: String,
+    private val projectId: String
+) : BaseViewModel(app, b, activity), DIAware {
+    private val gson = Gson()
+
+    override val di: DI by closestDI()
+    val repo: AdmRepository by instance()
 
     /**
      * 查询空间和任务
@@ -53,20 +78,101 @@ class GraphyVM(
      * @param x          x坐标
      * @param y          y坐标
      */
-    fun addProblem(choseSpace: TunableSpaceItem, x: Float, y: Float) {
-        val bean = ReqAddProblem()
-        bean.spaceId = choseSpace.data.id
-        bean.floorId = floorId
-        val position = Position()
-        position.x = x.toString() + ""
-        position.y = y.toString() + ""
-        bean.position = position
-        val observable = RetrofitFactory.getInstance().addProblem(getRequestBody(bean))
-        sendRequest(observable, object : BaseObserver<AddProblemModel>(mActivity, this) {
-            override fun onSuccess(model: AddProblemModel) {
-                mEmitter.SendDircetive(ADD_PROBLEM, model)
+    fun addProblem(
+        point: PointItem?,
+        photos: ArrayList<Photos>,
+        content: String,
+        choseSpace: TunableSpaceItem,
+        x: Float,
+        y: Float
+    ) {
+        viewModelScope.launch {
+            //插入问题数据
+            val position = PointF()
+            position.x = x
+            position.y = y
+            var toJson = ""
+            if (point != null && point.data.mX != 0f) {
+                position.x = point.data.mX
+                position.y = point.data.mY
+                toJson = gson.toJson(position)
+            } else {
+                toJson = gson.toJson(position)
             }
-        }, true)
+            var time = SimpleDateFormat("yyyyMMddHHmmss").format(Date(System.currentTimeMillis()))
+            var toString = ""
+            if (point != null && !TextUtils.isEmpty(point.data.id)) {
+                toString = point.data.id!!
+            } else {
+                toString = UUID.randomUUID().toString().replace("-", "")
+            }
+
+            var problem = ProblemArchEntity(
+                toString,
+                floorId,
+                projectId,
+                buildingId,
+                "point", "",
+                "",
+                1,
+                content,
+                "",
+                time,
+                "android", time, "0", 1, toJson
+            )
+            repo.insProblem(problem)
+
+
+            //插入文件数据
+            var order = 0
+            for (photo in photos) {
+                if (order != 0) {
+                    var uuid = ""
+                    if (TextUtils.isEmpty(photo.id)) {
+                        uuid = UUID.randomUUID().toString().replace("-", "")
+                    } else {
+                        uuid = photo.id
+                    }
+
+                    val file = FileEntity(
+                        uuid,
+                        "problem_arch",
+                        photo.key,
+                        "photo",
+                        photo.path,
+                        toString,
+                        "",
+                        "",
+                        order,
+                        projectId,
+                        buildingId,
+                        floorId,
+                        "android",
+                        time,
+                        "",
+                        time,
+                        1,
+                        "0"
+                    )
+                    repo.insFile(file)
+                }
+                order++
+            }
+            mEmitter.SendDircetive(ADD_PROBLEM, null)
+        }
+//        val bean = ReqAddProblem()
+//        bean.spaceId = choseSpace.data.id
+//        bean.floorId = floorId
+//        val position = Position()
+//        position.x = x.toString() + ""
+//        position.y = y.toString() + ""
+//        bean.position = position
+//        val observable = RetrofitFactory.getInstance().addProblem(getRequestBody(bean))
+//        sendRequest(observable, object : BaseObserver<AddProblemModel>(mActivity, this) {
+//            override fun onSuccess(model: AddProblemModel) {
+//                mEmitter.SendDircetive(ADD_PROBLEM, model)
+//            }
+//        }, true)
     }
 
     /**
@@ -75,15 +181,41 @@ class GraphyVM(
      * @param choseSpace 选中的空间
      */
     fun getProblem(choseSpace: TunableSpaceItem?) {
-        val bean = ReqProblems()
-        bean.floorId = floorId
-//        bean.spaceId = choseSpace!!.data.id
-        val observable = RetrofitFactory.getInstance().problems(getRequestBody(bean))
-        sendRequest(observable, object : BaseObserver<List<ProblemsModel>>(mActivity, this) {
-            override fun onSuccess(models: List<ProblemsModel>) {
-                mEmitter.SendDircetive(GET_PROBLEM, models)
+        viewModelScope.launch {
+            val problems = repo.getProblem()
+            var models: ArrayList<ProblemsModel> = ArrayList()
+            for (problem in problems) {
+                if (problem.problemState == 1) {
+                    val promodel = ProblemsModel()
+                    promodel.content = problem.message
+                    promodel.floorId = floorId
+                    promodel.spaceId = choseSpace!!.data.id
+                    promodel.id = problem.id
+                    promodel.position = problem.geom
+                    val refFiles = repo.getRefFile(problem.id)
+                    for (file in refFiles) {
+                        var photo = Photos()
+                        photo.key = file.filePath
+                        photo.id = file.id
+                        photo.itemType = 0
+                        photo.path = file.clientPath
+                        promodel.photos.add(photo)
+                    }
+                    models.add(promodel)
+                }
             }
-        }, true)
+            mEmitter.SendDircetive(GET_PROBLEM, models)
+        }
+
+//        val bean = ReqProblems()
+//        bean.floorId = floorId
+////        bean.spaceId = choseSpace!!.data.id
+//        val observable = RetrofitFactory.getInstance().problems(getRequestBody(bean))
+//        sendRequest(observable, object : BaseObserver<List<ProblemsModel>>(mActivity, this) {
+//            override fun onSuccess(models: List<ProblemsModel>) {
+//                mEmitter.SendDircetive(GET_PROBLEM, models)
+//            }
+//        }, true)
     }
 
     /**
@@ -93,15 +225,21 @@ class GraphyVM(
      * @param choseSpace 选中的空间
      */
     fun closeProblem(point: PointItem, choseSpace: TunableSpaceItem?) {
-        val bean = ReqCloseProblem()
-        bean.problemId = point.data.id
-        bean.spaceId = choseSpace!!.data.id
-        val observable = RetrofitFactory.getInstance().closeProblem(getRequestBody(bean))
-        sendRequest(observable, object : BaseObserver<CloseProblemModel>(mActivity, this) {
-            override fun onSuccess(setProblemModel: CloseProblemModel) {
-                mEmitter.SendDircetive(CLOSE_PROBLEM, null)
-            }
-        }, true)
+        viewModelScope.launch {
+            val problem = repo.getProblemById(point.data.id!!)
+            problem.problemState = 2
+            repo.insProblem(problem)
+            mEmitter.SendDircetive(CLOSE_PROBLEM, null)
+        }
+//        val bean = ReqCloseProblem()
+//        bean.problemId = point.data.id
+//        bean.spaceId = choseSpace!!.data.id
+//        val observable = RetrofitFactory.getInstance().closeProblem(getRequestBody(bean))
+//        sendRequest(observable, object : BaseObserver<CloseProblemModel>(mActivity, this) {
+//            override fun onSuccess(setProblemModel: CloseProblemModel) {
+//                mEmitter.SendDircetive(CLOSE_PROBLEM, null)
+//            }
+//        }, true)
     }
 
     /**
@@ -113,23 +251,49 @@ class GraphyVM(
      * @param toString   z轴描述
      */
     fun bindQrcode(choseSpace: TunableSpaceItem?, result: String?, point: Point, toString: String) {
-        val bean = ReqBindQrcode()
-        bean.objId = choseSpace!!.data.id
-        bean.objType = "space"
-        bean.uuid = result
-        val position = Position()
-        position.x = java.lang.String.valueOf(point.mX)
-        position.y = java.lang.String.valueOf(point.mY)
-        position.z = Z()
-        position.z.offset = toString
-        position.z.region = "wall"
-        bean.position = position
-        val observable = RetrofitFactory.getInstance().bindQrcode(getRequestBody(bean))
-        sendRequest(observable, object : BaseObserver<BindQrcodeModel?>(mActivity, this) {
-            override fun onSuccess(bindQrcodeModel: BindQrcodeModel?) {
-                mEmitter.SendDircetive(BIND_QECODE, null)
-            }
-        }, true)
+        viewModelScope.launch {
+            var pointZ = PointZ()
+            pointZ.x = point.mX
+            pointZ.y = point.mY
+            pointZ.z = toString.toFloat()
+            val toJson = gson.toJson(pointZ)
+            var time = SimpleDateFormat("yyyyMMddHHmmss").format(Date(System.currentTimeMillis()))
+            val qrcode = QrCodeEntity(
+                id = UUID.randomUUID().toString(),
+                qrCode = result!!,
+                objId = choseSpace!!.data.id!!,
+                projectId = projectId,
+                buildingId = buildingId,
+                floorId = floorId,
+                location = toJson,
+                remark = "wall",
+                creator = "Anroid",
+                creationTime = time,
+                modifier = "Android",
+                modifiedTime = time,
+                valid = 1,
+                uploadFlag = "0"
+            )
+            repo.insQrcode(qrcode)
+            mEmitter.SendDircetive(BIND_QECODE, null)
+        }
+//        val bean = ReqBindQrcode()
+//        bean.objId = choseSpace!!.data.id
+//        bean.objType = "space"
+//        bean.uuid = result
+//        val position = Position()
+//        position.x = java.lang.String.valueOf(point.mX)
+//        position.y = java.lang.String.valueOf(point.mY)
+//        position.z = Z()
+//        position.z.offset = toString
+//        position.z.region = "wall"
+//        bean.position = position
+//        val observable = RetrofitFactory.getInstance().bindQrcode(getRequestBody(bean))
+//        sendRequest(observable, object : BaseObserver<BindQrcodeModel?>(mActivity, this) {
+//            override fun onSuccess(bindQrcodeModel: BindQrcodeModel?) {
+//                mEmitter.SendDircetive(BIND_QECODE, null)
+//            }
+//        }, true)
     }
 
     /**
@@ -138,14 +302,33 @@ class GraphyVM(
      * @param choseSpace 选中的空间
      */
     fun getQrcode(choseSpace: TunableSpaceItem?) {
-        val bean = ReqQrcode()
-        bean.objId = choseSpace!!.data.id
-        val observable = RetrofitFactory.getInstance().qrcode(getRequestBody(bean))
-        sendRequest(observable, object : BaseObserver<ArrayList<QrcodeModel>>(mActivity, this) {
-            override fun onSuccess(qrcodeModels: ArrayList<QrcodeModel>) {
-                mEmitter.SendDircetive(GET_QECODE, qrcodeModels)
+        viewModelScope.launch {
+            val qrcodes = repo.getQrcode(choseSpace!!.data.id!!)
+            val qrcodeModels = ArrayList<QrcodeModel>()
+            for (qrcode in qrcodes) {
+                var qrcodeModel = QrcodeModel()
+                qrcodeModel.obj_id = qrcode.objId
+                qrcodeModel.qr_code = qrcode.qrCode
+                var pointZ = gson.fromJson(qrcode.location, PointZ::class.java)
+                val position = Position()
+                position.x = pointZ.x.toString()
+                position.y = pointZ.y.toString()
+                position.z = Z()
+                position.z.offset = pointZ.z.toString()
+                position.z.region = "wall"
+                qrcodeModel.position = gson.toJson(position)
+                qrcodeModels.add(qrcodeModel)
             }
-        }, true)
+            mEmitter.SendDircetive(GET_QECODE, qrcodeModels)
+        }
+//        val bean = ReqQrcode()
+//        bean.objId = choseSpace!!.data.id
+//        val observable = RetrofitFactory.getInstance().qrcode(getRequestBody(bean))
+//        sendRequest(observable, object : BaseObserver<ArrayList<QrcodeModel>>(mActivity, this) {
+//            override fun onSuccess(qrcodeModels: ArrayList<QrcodeModel>) {
+//                mEmitter.SendDircetive(GET_QECODE, qrcodeModels)
+//            }
+//        }, true)
     }
 
     /**
@@ -160,6 +343,7 @@ class GraphyVM(
         bean.floorId = floorId
         bean.spaceId.add(choseSpace!!.data.id)
         bean.jobStatus = jobStatus
+        bean.spaceCode = "test"
         val observable = RetrofitFactory.getInstance().setJob(getRequestBody(bean))
         sendRequest(observable, object : BaseObserver<SetJobModel>(mActivity, this) {
             override fun onSuccess(model: SetJobModel) {
@@ -244,6 +428,20 @@ class GraphyVM(
         )
     }
 
+    fun getInfosConfig(spaceId: String) {
+        viewModelScope.launch {
+            val infosConfig = repo.getInfosConfigByObjType("space")
+            val strInfos = infosConfig.get(0).strInfos
+
+//            var infoList = gson.fromJson(strInfos, ArrayList<Infos>()::class.java)
+            var infoList = gson.fromJson<List<Infos>>(
+                strInfos,
+                object : TypeToken<List<Infos?>?>() {}.type
+            )
+            mEmitter.SendDircetive(SPACE_INFO, infoList)
+        }
+    }
+
     companion object {
         //查询空间和任务
         const val SPACE_JOB = "SPACE_JOB"
@@ -280,6 +478,9 @@ class GraphyVM(
 
         //查询空间下的管道
         const val SPACE_PIPE = "SPACE_PIPE"
+
+        //查询空间详情
+        const val SPACE_INFO = "SPACE_INFO"
     }
 
 }

+ 4 - 3
demo/src/main/java/com/sybotan/android/demo/viewmodel/RelationVM.kt

@@ -1,5 +1,6 @@
 package com.sybotan.android.demo.viewmodel
 
+import android.app.Application
 import com.sybotan.android.demo.activities.BaseActivity
 import com.sybotan.android.demo.bean.request.ReqEqToEqRel
 import com.sybotan.android.demo.bean.request.ReqEqToRel
@@ -11,7 +12,8 @@ import com.sybotan.android.demo.retrofit.BaseObserver
 import com.sybotan.android.demo.retrofit.BaseViewModelInterface
 import com.sybotan.android.demo.retrofit.RetrofitFactory
 
-class RelationVM(b: BaseViewModelInterface, a: BaseActivity) : BaseViewModel(b, a) {
+class RelationVM(app: Application, b: BaseViewModelInterface, a: BaseActivity) :
+    BaseViewModel(app, b, a) {
     companion object {
         // 设备服务于空间
         const val EQ_SP_SERVE = "eq_sp_serve"
@@ -43,7 +45,7 @@ class RelationVM(b: BaseViewModelInterface, a: BaseActivity) : BaseViewModel(b,
 
     }
 
-     fun getPipes(spaceId: String, code: String) {
+    fun getPipes(spaceId: String, code: String) {
         val req = ReqRelationEq(spaceId)
         val observable = RetrofitFactory.getInstance().getSpacePipe(getRequestBody(req))
         sendRequest(observable, object : BaseObserver<List<SpacePipe>>(mActivity, this) {
@@ -55,7 +57,6 @@ class RelationVM(b: BaseViewModelInterface, a: BaseActivity) : BaseViewModel(b,
     }
 
 
-
     fun addEqToSer(rel: ReqEqToRel) {
         val observable = RetrofitFactory.getInstance().addEqToSerRel(getRequestBody(rel))
         this.sendRequest(observable, object : BaseObserver<ResEqRel>(mActivity, this) {

+ 1 - 0
demo/src/main/res/layout/activity_equip_detail.xml

@@ -2,6 +2,7 @@
 <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
+    android:id="@+id/root"
     android:layout_height="match_parent"
     android:background="@color/white_ffffff"
     android:orientation="vertical">

+ 1 - 0
demo/src/main/res/layout/activity_graphy.xml

@@ -893,6 +893,7 @@
                 android:textSize="13sp" />
 
             <androidx.appcompat.widget.AppCompatEditText
+                android:id="@+id/problemDesc"
                 android:layout_width="match_parent"
                 android:layout_height="60dp"
                 android:layout_marginTop="8dp"

+ 1 - 0
demo/src/main/res/layout/activity_space_detail.xml

@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/root"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@color/white_ffffff">

+ 1 - 1
demo/src/main/res/layout/dialog_list_choice.xml

@@ -37,7 +37,7 @@
             android:layout_marginRight="16dp"
             android:background="@color/white_ffffff"
             android:gravity="center"
-            android:text="全部"
+            android:text="确定"
             android:textColor="@color/gray_272727"
             android:textSize="16sp" />
 

+ 10 - 2
demo/src/main/res/layout/personal_select_text_item.xml

@@ -13,14 +13,22 @@
         android:background="@drawable/common_line_ffffff_single_16"
         android:orientation="horizontal">
 
+        <CheckBox
+            android:id="@+id/radioButton"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_gravity="center"
+            android:layout_marginLeft="20dp"
+            android:gravity="center"
+            android:padding="10dp" />
+
         <TextView
             android:id="@+id/choice_name"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:layout_gravity="center"
             android:layout_marginLeft="16dp"
             android:layout_marginRight="16dp"
-            android:gravity="center"
+            android:gravity="center_vertical"
             android:singleLine="true"
             android:text="维修"
             android:textColor="@color/gray_272727"

+ 2 - 3
demo/src/main/res/layout/static_info.xml

@@ -15,9 +15,8 @@
         android:textStyle="bold" />
 
     <androidx.recyclerview.widget.RecyclerView
-        android:layout_marginLeft="16dp"
-        android:layout_marginRight="16dp"
         android:id="@+id/recycler"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
+        android:layout_height="wrap_content"
+        android:overScrollMode="never" />
 </androidx.appcompat.widget.LinearLayoutCompat>

+ 1 - 1
demo/src/main/res/layout/view_enum.xml

@@ -6,7 +6,7 @@
     android:orientation="horizontal">
 
     <com.sybotan.android.demo.view.ListItemView
-        android:id="@+id/view_double"
+        android:id="@+id/view_enum"
         android:layout_width="match_parent"
         android:layout_height="44dp"
         android:layout_marginTop="10dp"

+ 5 - 0
demo/src/main/res/xml/file_paths.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<paths>
+    <external-path path="Android/data/com.sybotan.android.demo/" name="files_root" />
+    <external-path path="." name="external_storage_root" />
+</paths>

+ 101 - 60
sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/SGraphyView.kt

@@ -44,15 +44,15 @@ import kotlin.math.min
  *
  * @author  庞利祥(sybotan@126.com)
  */
-open class SGraphyView(context: Context, attrs: AttributeSet? = null)
-    : SurfaceView(context, attrs), SurfaceHolder.Callback, View.OnTouchListener, GestureDetector.OnGestureListener {
+open class SGraphyView(context: Context, attrs: AttributeSet? = null) : SurfaceView(context, attrs),
+    SurfaceHolder.Callback, View.OnTouchListener, GestureDetector.OnGestureListener, Runnable {
 
     /**
      * 类对象
      */
     companion object {
         private val TAG = SGraphyView::class.java.name
-        private var fitrate =0.8f
+        private var fitrate = 0.8f
     } // companion object
 
     /** 指向加载到视图中的场景 */
@@ -66,10 +66,13 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
             // 保存场景
             field = value
         }
+
     /** 旋转 */
     var rotate = 0.0f
+
     /** 是否支持二指缩放操作 */
     var canZoom = true
+
     /** 缩放比例 */
     var scale = 1f
         get() = max(min(field, maxScale), minScale)
@@ -77,11 +80,13 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
             field = value
             moveRange()
         }
+
     /** 最小缩放比例 */
     var minScale = 0.0000001f
         set(value) {
             field = min(value, maxScale)
         }
+
     /** 最大缩放比例 */
     var maxScale = 1000000f
         set(value) {
@@ -90,6 +95,7 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
 
     /** 是否支持移动场景操作 */
     var canMove = true
+
     /** 场景原点位置在视图中的位置 */
     var pos = PointF(0f, 0f)
         get() {
@@ -97,8 +103,10 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
             field.y = min(max(field.y, minPos.y), maxPos.y)
             return field
         }
+
     /** 视图原点最小值 */
     var minPos = PointF(Float.MIN_VALUE, Float.MIN_VALUE)
+
     /** 视图原点最大值 */
     var maxPos = PointF(Float.MAX_VALUE, Float.MAX_VALUE)
 
@@ -108,6 +116,7 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
 
     /** 是否在绘制状态 */
     private var isDrawing = false
+
     /** 手势解析器 */
     private val gesture by lazy {
         GestureDetector(this)
@@ -115,8 +124,10 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
 
     /** 未缩放时二指间距离 */
     private var beforeLength = 0.0f
+
     /** 缩放后二指间距离 */
     private var afterLength = 0.0f
+
     /** 后台绘制线程 */
     private var paintThread: Thread? = null
     private var canvas: Canvas? = null
@@ -178,8 +189,8 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
 
     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec)
-        Log.e("w",widthMeasureSpec.toString())
-        Log.e("h",heightMeasureSpec.toString())
+        Log.e("w", widthMeasureSpec.toString())
+        Log.e("h", heightMeasureSpec.toString())
     }
 
     /**
@@ -201,8 +212,10 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
             val h = height.toFloat()
 
             val rect = scene!!.worldRect()
-            setCenterPoint( PointF(rect.centerX(), rect.centerY()),
-                    min(w / rect.width(), h / rect.height()) * fitrate)
+            setCenterPoint(
+                PointF(rect.centerX(), rect.centerY()),
+                min(w / rect.width(), h / rect.height()) * fitrate
+            )
 //            Log.e("w",w.toString())
 //            Log.e("h",h.toString())
 //            Log.e("rect1",rect.toJson())
@@ -216,33 +229,39 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
      *
      * @param scale 场景的缩放比例
      */
-    fun setCenterPoint(pos : PointF, scale : Float? = null) {
-        if (scale != null){
+    fun setCenterPoint(pos: PointF, scale: Float? = null) {
+        if (scale != null) {
             this.scale = scale
         }
-        this.pos = PointF(-pos.x  * this.scale + this.width.toFloat() / 2f,
-                -pos.y * this.scale + this.height.toFloat() / 2f)
+        this.pos = PointF(
+            -pos.x * this.scale + this.width.toFloat() / 2f,
+            -pos.y * this.scale + this.height.toFloat() / 2f
+        )
     } // Function setCenterPoint()
 
     /**
      * 限定移动范围
      */
-    fun moveRange(){
+    fun moveRange() {
         if (scene == null) {
             return
         }
-        val w= this.width.toFloat()
+        val w = this.width.toFloat()
         val h = this.height.toFloat()
         val rect = scene!!.worldRect()
-        this.minPos = PointF(-rect.centerX() * this.scale + w / 2f - rect.width() / 2f * this.scale,
-                -rect.centerY() * this.scale + h / 2f - rect.height() / 2f * this.scale)
+        this.minPos = PointF(
+            -rect.centerX() * this.scale + w / 2f - rect.width() / 2f * this.scale,
+            -rect.centerY() * this.scale + h / 2f - rect.height() / 2f * this.scale
+        )
         /**
          *   -(rect.left + rect.right) / 2f * graphyView.scale  + width / 2 图形的中心点,
          *   rect.width() / 2 * graphyView.scale / 0.8f 图形宽度的一半乘以缩放比例除以适配百分比
          *
          */
-        this.maxPos = PointF(-rect.centerX() * this.scale  + w / 2f + rect.width() / 2f * this.scale,
-                -rect.centerY() * this.scale +  h / 2f + rect.height() / 2f * this.scale)
+        this.maxPos = PointF(
+            -rect.centerX() * this.scale + w / 2f + rect.width() / 2f * this.scale,
+            -rect.centerY() * this.scale + h / 2f + rect.height() / 2f * this.scale
+        )
     } // Function moveRange()
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -257,9 +276,9 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
 
         isDrawing = true
         // 启动后台绘制线程
-//        paintThread = Thread(this)
-//        paintThread!!.start()
-        runableTask()
+        paintThread = Thread(this)
+        paintThread!!.start()
+//        runableTask()
         return
     } // Function surfaceCreated()
 
@@ -285,10 +304,10 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
     override fun surfaceDestroyed(holder: SurfaceHolder?) {
         Log.d(TAG, "surfaceDestroyed")
 
-//        paintThread!!.interrupt()
-//        paintThread = null
+        paintThread!!.interrupt()
+        paintThread = null
         isDrawing = false
-        shutDown()
+//        shutDown()
         return
     } // Function surfaceDestroyed()
 
@@ -410,7 +429,7 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
     override fun onSingleTapUp(e: MotionEvent): Boolean {
-        Log.e("手势view",e.toString())
+        Log.e("手势view", e.toString())
         scene?.onSingleTapUp(toSceneMotionEvent(e))
         return true
     } // Function onSingleTapUp()
@@ -434,13 +453,24 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
      * @param   distanceY   Y轴上的移动距离,单位:像素
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-    override fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
+    override fun onScroll(
+        e1: MotionEvent,
+        e2: MotionEvent,
+        distanceX: Float,
+        distanceY: Float
+    ): Boolean {
         if (scene == null) {
             return true
         }
 
         // 如果场景处理了该事件,则返回
-        if (scene!!.onScroll(toSceneMotionEvent(e1), toSceneMotionEvent(e2), distanceX / scale, distanceY / scale)) {
+        if (scene!!.onScroll(
+                toSceneMotionEvent(e1),
+                toSceneMotionEvent(e2),
+                distanceX / scale,
+                distanceY / scale
+            )
+        ) {
             return true
         }
 
@@ -448,8 +478,8 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
             // 移动场景
             pos.x = pos.x - distanceX
             pos.y = pos.y - distanceY
-            Log.e("x",pos.x.toString())
-            Log.e("y",pos.y.toString())
+            Log.e("x", pos.x.toString())
+            Log.e("y", pos.y.toString())
             EventBus.getDefault().post(SGraphyViewMoveEvent(this, pos.x, pos.y))
         }
 
@@ -465,8 +495,18 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
      * @param   velocityY   Y轴上的移动速度,像素/秒
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-    override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
-        scene?.onFling(toSceneMotionEvent(e1), toSceneMotionEvent(e2), velocityX / scale, velocityY / scale)
+    override fun onFling(
+        e1: MotionEvent,
+        e2: MotionEvent,
+        velocityX: Float,
+        velocityY: Float
+    ): Boolean {
+        scene?.onFling(
+            toSceneMotionEvent(e1),
+            toSceneMotionEvent(e2),
+            velocityX / scale,
+            velocityY / scale
+        )
         return true
     } // Function onFling()
 
@@ -475,30 +515,30 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
     /**
      * 重载线程run函数。
      */
-//    override fun run() {
-//        while(null != paintThread && !paintThread!!.isInterrupted) {      // 循环控制绘制
-//            var canvas: Canvas? = null
-//            try {
-//                Thread.sleep(100)
-//                canvas = holder.lockCanvas()
-//                if (null == canvas) {   // 如果canvas为空
-//                    continue
-//                }
-//                synchronized(holder) {
-//                    drawScene(canvas)
-//                }
-//            } catch (e: Exception) {
-//                e.printStackTrace()
-//
-//            } finally {
-//                if (null != canvas) {
-//                    holder.unlockCanvasAndPost(canvas)
-//                }
-//            }
-//        }
-//
-//        return
-//    } // Function run()
+    override fun run() {
+        while (null != paintThread && !paintThread!!.isInterrupted) {      // 循环控制绘制
+            var canvas: Canvas? = null
+            try {
+                Thread.sleep(100)
+                canvas = holder.lockCanvas()
+                if (null == canvas) {   // 如果canvas为空
+                    continue
+                }
+                synchronized(holder) {
+                    drawScene(canvas)
+                }
+            } catch (e: Exception) {
+                e.printStackTrace()
+
+            } finally {
+                if (null != canvas) {
+                    holder.unlockCanvasAndPost(canvas)
+                }
+            }
+        }
+
+        return
+    } // Function run()
 
     /**
      * 后台场景绘制线程
@@ -613,8 +653,10 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
      * @return  得到视图的x坐标中点
      */
     private fun getMiddlePoint(event: MotionEvent): PointF {
-        return PointF((event.getX(1) + event.getX(0)) / 2f,
-                (event.getY(1) + event.getY(0)) / 2f)
+        return PointF(
+            (event.getX(1) + event.getX(0)) / 2f,
+            (event.getY(1) + event.getY(0)) / 2f
+        )
     } // Function getMiddlePoint()
 
     /**
@@ -631,7 +673,7 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
 //        se.matrix.postScale(this.scale, this.scale);
 //        se.matrix.postRotate(this.rotate)
 
-        se.matrix.preTranslate(pos.x,pos.y)
+        se.matrix.preTranslate(pos.x, pos.y)
         se.matrix.preScale(this.scale, this.scale);
         se.matrix.preRotate(this.rotate)
 
@@ -640,9 +682,9 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
         se.matrix.invert(matrixMat)
 
         se.matrix.getValues(src1)
-        Log.e("src1= ",src1.toJson())
+        Log.e("src1= ", src1.toJson())
         matrixMat.getValues(src2)
-        Log.e("src2= ",src2.toJson())
+        Log.e("src2= ", src2.toJson())
 
         val mp = MatrixUtil.matrixTransform(matrixMat, e.x, e.y)
         se.x = mp.x
@@ -656,5 +698,4 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
     } // Function toSceneMotionEvent()
 
 
-
 } // Class SGraphyView