Browse Source

feat 设备关系可通过平面图选择

lihao1 3 năm trước cách đây
mục cha
commit
c5e5cbe596
21 tập tin đã thay đổi với 835 bổ sung64 xóa
  1. 4 3
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/EquipItem.kt
  2. 1 1
      cadengine/src/main/java/cn/sagacloud/android/cadengine/types/Point.kt
  3. BIN
      cadengine/src/main/res/drawable/equip6.png
  4. 3 0
      demo/src/main/AndroidManifest.xml
  5. 3 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/ObjectDao.kt
  6. 2 2
      demo/src/main/java/com/framework/mvvm/model/db/entity/task/RelationEntity.kt
  7. 4 0
      demo/src/main/java/com/framework/mvvm/model/repository/AdmRepository.kt
  8. 428 0
      demo/src/main/java/com/sybotan/android/demo/activities/ChooseEquipActivity.kt
  9. 2 2
      demo/src/main/java/com/sybotan/android/demo/activities/ChooseSpaceActivity.kt
  10. 77 21
      demo/src/main/java/com/sybotan/android/demo/activities/EquipDetailActivity.kt
  11. 6 6
      demo/src/main/java/com/sybotan/android/demo/activities/GraphyActivity.kt
  12. 1 1
      demo/src/main/java/com/sybotan/android/demo/activities/SpaceMapActivity.kt
  13. 1 1
      demo/src/main/java/com/sybotan/android/demo/bean/result/Children.java
  14. 66 20
      demo/src/main/java/com/sybotan/android/demo/tools/Lasso.kt
  15. 3 2
      demo/src/main/java/com/sybotan/android/demo/tools/ObjectNameUtils.kt
  16. 39 1
      demo/src/main/java/com/sybotan/android/demo/viewmodel/ChooseSpaceVM.kt
  17. 1 1
      demo/src/main/java/com/sybotan/android/demo/viewmodel/EquipDetailVM.kt
  18. 4 1
      demo/src/main/java/com/sybotan/android/demo/viewmodel/GraphyVM.kt
  19. 139 0
      demo/src/main/res/layout/activity_choose_equip.xml
  20. 49 0
      demo/src/main/res/layout/activity_equip_detail.xml
  21. 2 2
      gradle.properties

+ 4 - 3
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/EquipItem.kt

@@ -3,10 +3,7 @@ package cn.sagacloud.android.cadengine.items
 
 import android.content.Context
 import android.graphics.*
-import android.graphics.drawable.BitmapDrawable
 import android.util.Log
-import android.view.GestureDetector
-import android.view.MotionEvent
 import cn.sagacloud.android.cadengine.R
 import cn.sagacloud.android.cadengine.types.Point
 import com.sybotan.android.graphy.SGraphyItem
@@ -35,6 +32,7 @@ class EquipItem(
     var mBlueBitmap: Bitmap
     var mGreenBitmap: Bitmap
     var myellowBitmap: Bitmap
+    var mRedBitmap2: Bitmap
 
     init {
         if (defaultScale != null) {
@@ -48,6 +46,7 @@ class EquipItem(
         mGreenBitmap = BitmapFactory.decodeResource(context.resources, R.drawable.equip_green)
 
         mRedBitmap = BitmapFactory.decodeResource(context.resources, R.drawable.equip_red)
+        mRedBitmap2 = BitmapFactory.decodeResource(context.resources, R.drawable.equip6)
         mPurpleBitmap = BitmapFactory.decodeResource(context.resources, R.drawable.equip_notdone)
         myellowBitmap = BitmapFactory.decodeResource(context.resources, R.drawable.yellow_equip)
 
@@ -96,6 +95,8 @@ class EquipItem(
             canvas.drawBitmap(myellowBitmap, matrix, mPaint_center)
         }  else if (data.equipState == 5) {
             canvas.drawBitmap(mPurpleBitmap, matrix, mPaint_center)
+        }  else if (data.equipState == 6) {
+            canvas.drawBitmap(mRedBitmap2, matrix, mPaint_center)
         } else {
             canvas.drawBitmap(mBlueBitmap, matrix, mPaint_center)
         }

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

@@ -34,7 +34,7 @@ class Point {
     var digitalDeliveryID: String? = null
     var photos: ArrayList<Photos> = ArrayList()
 
-    //1-蓝 2-绿 3-红 4-huang
+    //1-蓝 2-绿 3-红 4-huang 6-关系已完成
     var equipState: Int? = 0
     var equipType: Int? = 0
 }

BIN
cadengine/src/main/res/drawable/equip6.png


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

@@ -63,6 +63,9 @@
             android:name=".activities.ChooseSpaceActivity"
             android:exported="true" />
         <activity
+            android:name=".activities.ChooseEquipActivity"
+            android:exported="true" />
+        <activity
             android:name=".activities.EquipContainerActivity"
             android:exported="true" /> <!-- <meta-data -->
         <!-- android:name="design_width_in_dp" -->

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

@@ -35,6 +35,9 @@ interface ObjectDao {
     @Query("select * from object where class_code = :code and building_id =:buildingId and valid = 1")
     suspend fun getObjectByCode(code: String, buildingId: String): List<ObjectEntity>
 
+    @Query("select * from object where class_code = :code and building_id =:buildingId and floor_id =:floorId and valid = 1")
+    suspend fun getObjectByCode(code: String, buildingId: String, floorId: String): List<ObjectEntity>
+
     @Query("select * from object where container_id = :objId and valid = 1")
     suspend fun getContainerObjs(objId: String): List<ObjectEntity>
 

+ 2 - 2
demo/src/main/java/com/framework/mvvm/model/db/entity/task/RelationEntity.kt

@@ -22,8 +22,8 @@ data class RelationEntity(
     @ColumnInfo(name = "graph_code") val graphCode: String? = null,         // 图编码
     @ColumnInfo(name = "rel_code") val relCode: String? = null,             // 关系编码
     @ColumnInfo(name = "rel_value") val relValue: String? = null,           // 关系值
-    @ColumnInfo(name = "obj_from") val objFrom: String? = null,             // 关系源对象
-    @ColumnInfo(name = "obj_to") val objTo: String? = null,                 // 关系目标对象
+    @ColumnInfo(name = "obj_from") var objFrom: String? = null,             // 关系源对象
+    @ColumnInfo(name = "obj_to") var objTo: String? = null,                 // 关系目标对象
     @ColumnInfo(name = "client_id") val clientId: String? = null,           // 客户端生成id
     @ColumnInfo(name = "client_device") val clientDevice: String? = null,   // 标识客户端设备
     @ColumnInfo(name = "delivery_state") val deliveryState: Int = -1,       // BDTP交付状态: 1 已交付, 0 待交付

+ 4 - 0
demo/src/main/java/com/framework/mvvm/model/repository/AdmRepository.kt

@@ -196,6 +196,10 @@ class AdmRepository(
         return db.objectDao().getObjectByCode(code, buildingId)
     }
 
+    suspend fun getObjectByCode(code: String, buildingId: String, floorId: String): List<ObjectEntity> {
+        return db.objectDao().getObjectByCode(code, buildingId, floorId)
+    }
+
     suspend fun getObjectByLocalId(localId: String): ObjectEntity? {
         return db.objectDao().getObjectByLocalId(localId)
     }

+ 428 - 0
demo/src/main/java/com/sybotan/android/demo/activities/ChooseEquipActivity.kt

@@ -0,0 +1,428 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *               iFHS7.
+ *              ;BBMBMBMc                  rZMBMBR              BMB
+ *              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
+ *     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
+ *     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
+ *      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
+ *     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
+ *     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
+ *     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
+ *         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
+ *     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
+ *      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
+ *         i0BM: SWKHKGO  MBDv
+ *           .UB  OOGDM. MK,                                          Copyright (c) 2015-2019.  斯伯坦机器人
+ *              ,  XMW  ..
+ *                  r                                                                     All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+package com.sybotan.android.demo.activities
+
+import android.annotation.SuppressLint
+import android.graphics.PointF
+import android.os.Bundle
+import android.text.TextUtils
+import android.view.Gravity
+import android.widget.*
+import cn.hutool.core.util.IdUtil
+import cn.sagacloud.android.cadengine.FloorScene
+import cn.sagacloud.android.cadengine.items.*
+import cn.sagacloud.android.cadengine.types.*
+import com.framework.mvvm.model.db.entity.task.InfosforEq
+import com.framework.mvvm.model.db.entity.task.ObjectEntity
+import com.framework.mvvm.model.db.entity.task.RelationEntity
+import com.google.gson.Gson
+import com.sybotan.android.demo.R
+import com.sybotan.android.demo.bean.RelConfigEntityPackClass
+import com.sybotan.android.demo.bean.RelationPackClass
+import com.sybotan.android.demo.bean.SpaceInfo
+import com.sybotan.android.demo.bean.SpaceNameModel
+import com.sybotan.android.demo.bean.result.*
+import com.sybotan.android.demo.entitiies.Floor
+import com.sybotan.android.demo.graphy.GraphyHelper
+import com.sybotan.android.demo.retrofit.Constant
+import com.sybotan.android.demo.tools.CommonUtils
+import com.sybotan.android.demo.tools.Lasso
+import com.sybotan.android.demo.tools.ObjectNameUtils
+import com.sybotan.android.demo.tools.ToastUtils
+import com.sybotan.android.demo.view.ObjectRelationDialog
+import com.sybotan.android.demo.view.SelectListSinglePopupWindow
+import com.sybotan.android.demo.viewmodel.ChooseSpaceVM
+import com.sybotan.android.graphy.SGraphyView
+import com.sybotan.base.utils.SJsonUtil
+import org.jetbrains.anko.doAsync
+import org.jetbrains.anko.uiThread
+import org.kodein.di.DI
+import org.kodein.di.DIAware
+import org.kodein.di.android.closestDI
+import java.lang.StringBuilder
+import kotlin.collections.ArrayList
+
+/**
+ * 平面图选择空间
+ */
+class ChooseEquipActivity : BaseActivity(), DIAware {
+
+    override val di: DI by closestDI()
+
+    /** viewModel */
+    lateinit var chooseSpaceVM: ChooseSpaceVM
+
+    /** 建筑Id */
+    private lateinit var buildingId: String
+
+    /** 楼层Id */
+    private lateinit var floorId: String
+    private lateinit var projectId: String
+    private lateinit var deviceId: String
+    private var scale: Float = 0f
+    private lateinit var area: ServeAreaItem
+    private lateinit var centerPoint: PointF
+    private lateinit var position: Position
+    var chooseSpaceList = ArrayList<TunableSpaceItem>()
+    var chooseRelList = ArrayList<RelationEntity>()
+    var chooseEquips = ArrayList<ObjectEntity>()
+    var spaceIdList = ArrayList<String>()
+
+    /** 楼层地图 */
+    private lateinit var floorMap: String
+
+    var scene = FloorScene()
+    private val gson = Gson()
+    private lateinit var floors: ArrayList<Floor>
+    private lateinit var groupRelConfigEntity: RelConfigEntityPackClass
+
+    private lateinit var graphyView: SGraphyView
+    private lateinit var close: TextView
+    private lateinit var save: TextView
+    private lateinit var floorTv: TextView
+    private lateinit var spaceName: TextView
+    private lateinit var direction: TextView
+    private lateinit var root: LinearLayout
+    private lateinit var spaces: ArrayList<ObjectEntity>
+    private lateinit var equips: ArrayList<ObjectEntity>
+
+    /** 实际距离 */
+    val distance = 3000f
+
+    /** 缩放后的同比例距离 */
+    var realDistance = 0f
+
+    /**
+     * 创建Activity时的回调函数
+     *
+     * @param   savedInstanceState
+     */
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_choose_equip)
+        initView()
+
+        /** 初始化数据 */
+        initData()
+        graphyView.scene = scene
+
+        /** 点击监听 */
+        initListener()
+        /** 图形点击-poc业务 */
+        initSingleTopUp()
+        /** 网络请求回调处理 */
+        initViewModel()
+
+        return
+    } // Function onCreate()
+
+
+    private fun initView() {
+        graphyView = findViewById(R.id.graphyView)
+        close = findViewById(R.id.close)
+        save = findViewById(R.id.save)
+        floorTv = findViewById(R.id.floorTv)
+        root = findViewById(R.id.root)
+        spaceName = findViewById(R.id.spaceName)
+        direction = findViewById(R.id.direction)
+    }
+
+    /**
+     * 初始化数据
+     */
+    private fun initData() {
+        val params = intent.getBundleExtra("params")!!
+        buildingId = params.getString("buildingId", "")!!
+        floorId = params.getString("floorId", "")!!
+        floorMap = params.getString("floorMap", "")!!
+        projectId = params.getString("projectId", "")!!
+        deviceId = params.getString("deviceId", "")!!
+        scale = params.getFloat("scale")!!
+        centerPoint = params.getParcelable("centerPoint")!!
+        groupRelConfigEntity = (params.getSerializable("groupRelConfigEntity") as RelConfigEntityPackClass?)!!
+        position = (params.getSerializable("position") as Position?)!!
+        val p = Point()
+        p.mX = position.x.toFloat()
+        p.mY = position.y.toFloat()
+        val equipItem = EquipItem(this, p)
+        equipItem.zOrder = 100000f
+        scene.addItem(equipItem)
+        if (groupRelConfigEntity.targetTypes[0].canFrom) {
+            direction.text = "<-"
+        } else {
+            direction.text = "->"
+        }
+        if (groupRelConfigEntity.targetTypes[0].canFrom && groupRelConfigEntity.targetTypes[0].canTo) {
+            direction.setOnClickListener {
+                if (direction.text.equals("->")) {
+                    direction.text = "<-"
+                } else {
+                    direction.text = "->"
+                }
+            }
+        }
+    }
+
+
+    /**
+     * 图形点击事件
+     * */
+    private fun initSingleTopUp() {
+        scene.setOnSingleTopUp(object : FloorScene.OnSingleTopUp {
+            @SuppressLint("SetJavaScriptEnabled")
+            override fun onSingUp(x: Float, y: Float) {
+                realDistance = distance * scene.defaultPointScale / graphyView.scale
+
+                var hasChooseEquip = false
+                var equipList = ArrayList<EquipItem>()
+
+                for (point in scene.equipList) {
+                    val sqrt = Math.sqrt(
+                        Math.pow(
+                            Math.abs(x - point.data.mX).toDouble(),
+                            2.0
+                        ) + Math.pow(Math.abs(y - point.data.mY).toDouble(), 2.0)
+                    ).toInt()
+                    if (sqrt < realDistance && !hasChooseEquip) {
+                        for (equip in equips) {
+                            if (equip.id == point.data.deviceId) {
+                                hasChooseEquip = true
+                                if (point.data.equipState == 4) {
+                                    point.data.equipState = 1
+                                    for (rel in chooseRelList) {
+                                        if (rel.objFrom.equals(point.data.deviceId) || rel.objTo.equals(point.data.deviceId)) {
+                                            chooseRelList.remove(rel)
+                                            initRelName()
+                                            break
+                                        }
+                                    }
+                                    break
+                                }
+                                equipList.add(point)
+                                val dialog = ObjectRelationDialog(
+                                    this@ChooseEquipActivity,
+                                    "该设备",
+                                    equip,
+                                    groupRelConfigEntity
+                                )
+                                dialog.show()
+                                dialog.setOnSubmit {
+                                    point.data.equipState = 4
+                                    val relEntity = RelationEntity(
+                                        id = IdUtil.simpleUUID(),
+                                        projectId = projectId,
+                                        buildingId = buildingId,
+                                        floorId = floorId,
+                                        graphCode = groupRelConfigEntity.entity.graphCode,
+                                        relCode = groupRelConfigEntity.entity.relCode,
+                                        objFrom = null,
+                                        objTo = null,
+                                        valid = 1,
+                                        state = 0
+                                    )
+                                    if (it) {
+                                        relEntity.objFrom = deviceId
+                                        relEntity.objTo = equip.id
+                                        relEntity.objFromLocalId = "该设备"
+                                        relEntity.objToLocalId = ObjectNameUtils.getEquipName(equip)
+                                    } else {
+                                        relEntity.objTo = deviceId
+                                        relEntity.objFrom = equip.id
+                                        relEntity.objFromLocalId = ObjectNameUtils.getEquipName(equip)
+                                        relEntity.objToLocalId = "该设备"
+                                    }
+                                    chooseRelList.add(relEntity)
+                                    initRelName()
+                                }
+                                break
+                            }
+                        }
+                    }
+                }
+
+                if (!hasChooseEquip) {
+
+                }
+            }
+
+        })
+    }
+
+
+    /**
+     * 页面全部监听事件
+     */
+    private fun initListener() {
+        floorTv.setOnClickListener {
+            val pop = SelectListSinglePopupWindow(this)
+            pop.setGenList(floors, Constant.TYPE5)
+            pop.setTitle(true, "选择对象")
+            pop.showAtLocation(root, Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL, 0, 0)
+            pop.setOnItemClickListener {
+                val floor = floors[it]
+                floorTv.text = floor.localName
+                floorId = floor.id
+                chooseSpaceVM.getFloorMap(floorId)
+            }
+        }
+        close.setOnClickListener { finish() }
+        save.setOnClickListener {
+            if (CommonUtils.IsNull(chooseRelList)) {
+                ToastUtils.showMyToast("请创建关系")
+                return@setOnClickListener
+            }
+            chooseSpaceVM.insRel(chooseRelList, groupRelConfigEntity, deviceId)
+        }
+    }
+
+    /**
+     * 初始化viewModel
+     */
+    private fun initViewModel() {
+        chooseSpaceVM = ChooseSpaceVM(this.application, { name, params ->
+            when (name) {
+                /** 加载地图 */
+                ChooseSpaceVM.MAP_LOAD -> {
+                    val floorOfflineData = gson.fromJson(params.toString(), FloorData::class.java)
+                    doAsync {
+                        scene.loadData(floorOfflineData)
+                        uiThread {
+                            graphyView.setCenterPoint(centerPoint, scale)
+                            chooseSpaceVM.getFloorList()
+                            chooseSpaceVM.getRel(deviceId, groupRelConfigEntity)
+                            initRelName()
+                        }
+                    }
+                }
+
+                /** 设备关系 */
+                ChooseSpaceVM.EQUIP_RELATION -> {
+                    val param = params as ArrayList<RelationPackClass>
+                    for (pa in param) {
+                        chooseRelList.add(pa.entity)
+                    }
+                    initRelName()
+                }
+                ChooseSpaceVM.FLOORS_LIST -> {
+                    floors = params as ArrayList<Floor>
+                    for (floor in floors) {
+                        if (floorId == floor.id) {
+                            floorTv.setText(floor.localName)
+                            chooseSpaceVM.getEquips(floorId, groupRelConfigEntity)
+                        }
+                    }
+                }
+                ChooseSpaceVM.FLOOR_MAP -> {
+                    val floorOfflineData = SJsonUtil.fromJson(params.toString(), FloorData::class.java)
+                    doAsync {
+                        scene = FloorScene()
+                        graphyView.scene = scene
+                        scene.loadData(floorOfflineData!!)
+                        uiThread {
+                            initSingleTopUp()
+                            for (space in chooseSpaceList) {
+                                if (space.data.floorId == floorId) {
+                                    scene.addItem(space)
+                                }
+                            }
+                            initRelName()
+                            chooseSpaceVM.getEquips(floorId, groupRelConfigEntity)
+                            graphyView.fitSceneToView()
+                        }
+                    }
+                }
+                ChooseSpaceVM.EQUIPS -> {
+                    if (params != null) {
+                        equips = params as ArrayList<ObjectEntity>
+                        for (equip in equips) {
+                            val info = gson.fromJson(equip.infos, InfosforEq::class.java)
+                            val point = Point()
+                            point.mX = info.location.x()
+                            point.mY = -info.location.y()
+                            point.equipState = 1
+                            point.equipType = 1
+                            point.deviceId = equip.id
+                            point.name = equip.localName
+                            val item = EquipItem(this, point)
+                            item.isVisible = true
+                            item.zOrder = 1000001f
+                            scene.equipList.add(item)
+                            scene.addItem(item)
+
+                        }
+                    }
+                    for (rel in chooseRelList) {
+                        for (point in scene.equipList) {
+                            if (point.data.deviceId.equals(rel.objFrom) || point.data.deviceId.equals(rel.objTo)) {
+                                point.data.equipState = 4
+                                break
+                            }
+                        }
+                    }
+                }
+
+            }
+        }, this, buildingId, floorId, projectId)
+        chooseSpaceVM.getMap()
+
+    }
+
+//    private fun initSpaceName() {
+//        val sb = StringBuilder()
+//        val others = ArrayList<SpaceNameModel>()
+//        sb.append(floorTv.text.toString()).append(":")
+//        for (space in chooseSpaceList) {
+//            if (space.data.floorName == floorTv.text.toString()) {
+//                sb.append(space.data.name).append("、")
+//            } else {
+//                var has = false
+//                for (other in others) {
+//                    if (other.name == space.data.floorName) {
+//                        other.size++
+//                        has = true
+//                    }
+//                }
+//                if (!has) {
+//                    others.add(SpaceNameModel(space.data.floorName, 1))
+//                }
+//            }
+//        }
+//        sb.append("\n\n其他层:\n")
+//        for (other in others) {
+//            sb.append("${other.name}(${other.size})、")
+//        }
+//        spaceName.text = sb.toString()
+//    }
+
+    private fun initRelName() {
+
+        val sb = StringBuilder()
+        for (rel in chooseRelList) {
+            sb.append(rel.objFromLocalId).append("->").append(rel.objToLocalId).append("、")
+        }
+        spaceName.text = sb.toString()
+    }
+
+
+} // Class GraphyActivity

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

@@ -178,7 +178,7 @@ class ChooseSpaceActivity : BaseActivity(), DIAware {
             override fun onSingUp(x: Float, y: Float) {
 
                 for (space in chooseSpaceList) {
-                    val isContain = Lasso.isPolygonContainsPoint(space.mPoints, android.graphics.Point(x.toInt(), -y.toInt()))
+                    val isContain = Lasso.isPolygonContainsPoint(space.data.outLine, android.graphics.Point(x.toInt(), -y.toInt()))
                     if (isContain && space.data.floorName == floorTv.text.toString()) {
                         scene.removeItem(space)
                         chooseSpaceList.remove(space)
@@ -189,7 +189,7 @@ class ChooseSpaceActivity : BaseActivity(), DIAware {
                 }
 
                 for (space in scene.tunableSpaceList) {
-                    val isContain = Lasso.isPolygonContainsPoint(space.mPoints, android.graphics.Point(x.toInt(), -y.toInt()))
+                    val isContain = Lasso.isPolygonContainsPoint(space.data.outLine, android.graphics.Point(x.toInt(), -y.toInt()))
                     if (isContain) {
                         val tunableSpace = TunableSpace()
                         tunableSpace.outLine = space.data.outLine

+ 77 - 21
demo/src/main/java/com/sybotan/android/demo/activities/EquipDetailActivity.kt

@@ -77,6 +77,7 @@ class EquipDetailActivity : BaseActivity(), View.OnTouchListener {
     private lateinit var serveArea: ListItemView
     private lateinit var compType: ListItemView
     private lateinit var doneSwitch: RMTristateSwitch
+    private lateinit var relSwitch: SwitchCompat
     private lateinit var height: ListItemView
     private lateinit var locationWhere: ListItemView
     private lateinit var equipClass: ListItemView
@@ -89,6 +90,10 @@ class EquipDetailActivity : BaseActivity(), View.OnTouchListener {
     private lateinit var pictureAdapter: PictureAdapter
     private lateinit var groupRelConfigEntity: RelConfigEntityPackClass
     private lateinit var groupPipeConfigEntity: PipeConfigEntityPackClass
+    private lateinit var infoTodo: RadioButton
+    private lateinit var infoNotDo: RadioButton
+    private lateinit var infoDone: RadioButton
+    private lateinit var relDone: RadioButton
     var list = ArrayList<Infos>()
     val beans: ArrayList<Photos> = ArrayList()
     private lateinit var staticInfoAdapter: StaticInfoAdapter
@@ -154,6 +159,10 @@ class EquipDetailActivity : BaseActivity(), View.OnTouchListener {
         location = findViewById(R.id.location)
         serveArea = findViewById(R.id.serveArea)
         doneSwitch = findViewById(R.id.doneSwitch)
+        infoTodo = findViewById(R.id.infoTodo)
+        infoNotDo = findViewById(R.id.infoNotDo)
+        infoDone = findViewById(R.id.infoDone)
+        relDone = findViewById(R.id.relDone)
         viewRecycler = findViewById(R.id.viewRecycler)
         mtextContent = findViewById(R.id.mtextContent)
         localName = findViewById(R.id.localName)
@@ -229,6 +238,19 @@ class EquipDetailActivity : BaseActivity(), View.OnTouchListener {
                 ToastUtils.showMyToast("请选择设备类")
                 return@setOnClickListener
             }
+            var state: Int = -1
+            if (infoTodo.isChecked) {
+                state = 0
+            }
+            if (infoNotDo.isChecked) {
+                state = 1
+            }
+            if (infoDone.isChecked) {
+                state = 2
+            }
+            if (relDone.isChecked) {
+                state = 3
+            }
             equipVM.insEquip(
                 uuid,
                 deviceId,
@@ -236,7 +258,7 @@ class EquipDetailActivity : BaseActivity(), View.OnTouchListener {
                 mtextContent.text.toString(),
                 beans,
                 equipEntity!!,
-                doneSwitch.state, position!!, containerId
+                state, position!!, containerId
             )
         }
         findViewById<ImageView>(R.id.back).setOnClickListener { finish() }
@@ -386,8 +408,23 @@ class EquipDetailActivity : BaseActivity(), View.OnTouchListener {
                         if (staticInfoAdapter.hashMap != null && staticInfoAdapter.hashMap.get("equipCheck") != null) {
                             val boo = staticInfoAdapter.hashMap.get("equipCheck")
                             if (boo is Double || boo is Int) {
-                                doneSwitch.state =
-                                    staticInfoAdapter.hashMap.get("equipCheck")!!.toInt()!!
+//                                doneSwitch.state =
+//                                    staticInfoAdapter.hashMap.get("equipCheck")!!.toInt()!!
+                                when (staticInfoAdapter.hashMap.get("equipCheck")!!.toInt()) {
+                                    0 -> {
+                                        infoTodo.isChecked = true
+                                    }
+                                    1 -> {
+                                        infoNotDo.isChecked = true
+                                    }
+                                    2 -> {
+                                        infoDone.isChecked = true
+                                    }
+                                    3 -> {
+                                        relDone.isChecked = true
+                                    }
+
+                                }
                             }
                         }
                         if (staticInfoAdapter.hashMap != null && staticInfoAdapter.hashMap.get("zRegion") != null) {
@@ -464,7 +501,7 @@ class EquipDetailActivity : BaseActivity(), View.OnTouchListener {
                     relAdapter.setOnAdd(object : RelationExpandAdapter.AddRel {
                         override fun onAdd(group: RelConfigEntityPackClass) {
                             this@EquipDetailActivity.groupRelConfigEntity = group
-                            equipVM.getRelObj(group, equipEntity!!.code!!)
+                            equipVM.getRelObj(group)
                         }
                     })
                     relAdapter.setOnDelete(object : RelationExpandAdapter.DeleteRel {
@@ -484,23 +521,42 @@ class EquipDetailActivity : BaseActivity(), View.OnTouchListener {
                     pop.setTitle(true, "选择对象")
                     if (groupRelConfigEntity.targetTypes[0].targetCode == "GeneralZone") {
                         pop.setChooseSpace()
-                    }
-                    pop.chooseSpace.setOnClickListener {
-                        val intent = Intent(this, ChooseSpaceActivity::class.java)
-                        val bundle = Bundle()
-                        bundle.putString("buildingId", buildingId)
-                        bundle.putString("floorId", floorId)
-                        bundle.putString("projectId", projectId)
-                        bundle.putFloat("scale", scale)
-                        bundle.putString("floorMap", floorMap)
-                        bundle.putParcelable("centerPoint", centerPoint)
-                        bundle.putSerializable("groupRelConfigEntity", groupRelConfigEntity)
-                        bundle.putSerializable("position", position)
-                        val id = if (TextUtils.isEmpty(deviceId)) uuid else deviceId
-                        bundle.putString("deviceId", id)
-                        intent.putExtra("params", bundle)
-                        startActivity(intent)
-                        pop.dismissImmediately()
+                        pop.chooseSpace.setOnClickListener {
+                            val intent = Intent(this, ChooseSpaceActivity::class.java)
+                            val bundle = Bundle()
+                            bundle.putString("buildingId", buildingId)
+                            bundle.putString("floorId", floorId)
+                            bundle.putString("projectId", projectId)
+                            bundle.putFloat("scale", scale)
+                            bundle.putString("floorMap", floorMap)
+                            bundle.putParcelable("centerPoint", centerPoint)
+                            bundle.putSerializable("groupRelConfigEntity", groupRelConfigEntity)
+                            bundle.putSerializable("position", position)
+                            val id = if (TextUtils.isEmpty(deviceId)) uuid else deviceId
+                            bundle.putString("deviceId", id)
+                            intent.putExtra("params", bundle)
+                            startActivity(intent)
+                            pop.dismissImmediately()
+                        }
+                    } else {
+                        pop.setChooseSpace()
+                        pop.chooseSpace.setOnClickListener {
+                            val intent = Intent(this, ChooseEquipActivity::class.java)
+                            val bundle = Bundle()
+                            bundle.putString("buildingId", buildingId)
+                            bundle.putString("floorId", floorId)
+                            bundle.putString("projectId", projectId)
+                            bundle.putFloat("scale", scale)
+                            bundle.putString("floorMap", floorMap)
+                            bundle.putParcelable("centerPoint", centerPoint)
+                            bundle.putSerializable("groupRelConfigEntity", groupRelConfigEntity)
+                            bundle.putSerializable("position", position)
+                            val id = if (TextUtils.isEmpty(deviceId)) uuid else deviceId
+                            bundle.putString("deviceId", id)
+                            intent.putExtra("params", bundle)
+                            startActivity(intent)
+                            pop.dismissImmediately()
+                        }
                     }
                     pop.showAtLocation(root, Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL, 0, 0)
                     pop.setOnItemClickListener {

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

@@ -159,7 +159,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
     lateinit var from: String
 
     /** 实际距离 */
-    val distance = 5000f
+    val distance = 3000f
 
     /** 缩放后的同比例距离 */
     var realDistance = 0f
@@ -675,7 +675,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
                     var hasChose = false
                     for (space in scene.tunableSpaceList) {
                         val polygonContainsPoint = Lasso.isPolygonContainsPoint(
-                            space.mPoints,
+                            space.data.outLine,
                             android.graphics.Point(x.toInt(), -y.toInt())
                         )
                         if (polygonContainsPoint) {
@@ -943,7 +943,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
             z.region = position.region
             positon.z = z
             for (space in scene.tunableSpaceList) {
-                val isContain = Lasso.isPolygonContainsPoint(space.mPoints, android.graphics.Point(positon.x.toFloat().toInt(), -positon.y.toFloat().toInt()))
+                val isContain = Lasso.isPolygonContainsPoint(space.data.outLine, android.graphics.Point(positon.x.toFloat().toInt(), -positon.y.toFloat().toInt()))
                 if (isContain) {
                     bundle.putString("spaceId", space.data.id)
                     break
@@ -1145,7 +1145,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
                 }
                 positon.z = z
                 for (space in scene.tunableSpaceList) {
-                    val isContain = Lasso.isPolygonContainsPoint(space.mPoints, android.graphics.Point(positon.x.toFloat().toInt(), -positon.y.toFloat().toInt()))
+                    val isContain = Lasso.isPolygonContainsPoint(space.data.outLine, android.graphics.Point(positon.x.toFloat().toInt(), -positon.y.toFloat().toInt()))
                     if (isContain) {
                         bundle.putString("spaceId", space.data.id)
                         break
@@ -1480,7 +1480,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
                     val child = childIterator.next()
                     if (child.position != null) {
                         var position = gson.fromJson(child.position, Position::class.java)
-                        val isContain = Lasso.isPolygonContainsPoint(scene.choseSpace!!.mPoints, android.graphics.Point(position.x.toFloat().toInt(), position.y.toFloat().toInt()))
+                        val isContain = Lasso.isPolygonContainsPoint(scene.choseSpace!!.data.outLine, android.graphics.Point(position.x.toFloat().toInt(), position.y.toFloat().toInt()))
                         if (!isContain) {
                             childIterator.remove()
                         }
@@ -1627,7 +1627,7 @@ class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCal
                         val point = Point()
                         point.mX = position.x.toFloat()
                         point.mY = -position.y.toFloat()
-                        val isContains = Lasso.isPolygonContainsPoint(scene.choseSpace!!.mPoints, android.graphics.Point(point.mX.toInt(), -point.mY.toInt()))
+                        val isContains = Lasso.isPolygonContainsPoint(scene.choseSpace!!.data.outLine, android.graphics.Point(point.mX.toInt(), -point.mY.toInt()))
                         point.remark = child.remark
                         point.type = model.type
                         point.equipState = child.type

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

@@ -429,7 +429,7 @@ class SpaceMapActivity : BaseActivity(), DIAware {
                     var hasChose = false
                     for (space in scene.tunableSpaceList) {
                         val polygonContainsPoint = Lasso.isPolygonContainsPoint(
-                            space.mPoints,
+                            space.data.outLine,
                             android.graphics.Point(x.toInt(), -y.toInt())
                         )
                         if (polygonContainsPoint) {

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

@@ -14,6 +14,6 @@ public class Children {
     public String name;
     public String position;
     public String remark;
-    //1-蓝 2-绿 3-红 4-黄 5-紫
+    //1-蓝 2-绿 3-红 4-黄 5-紫 6-红勾
     public int type;
 }

+ 66 - 20
demo/src/main/java/com/sybotan/android/demo/tools/Lasso.kt

@@ -86,29 +86,61 @@ class Lasso {
     companion object {
         fun isPolygonContainsPoint(mPoints: List<PointF>, point: Point): Boolean {
             val polygon = createPolygon(mPoints)
-
             val coord = Coordinate(point.x.toDouble(), point.y.toDouble())
             val geoPoint = geometryFactory.createPoint(coord)
-            return geoPoint.within(polygon)
-
-//            var nCross = 0
-//            for (i in mPoints.indices) {
-//                val p1 = mPoints[i]
-//                val p2 = mPoints[(i + 1) % mPoints.size]
-//                // 取多边形任意一个边,做点point的水平延长线,求解与当前边的交点个数
-//                // p1p2是水平线段,要么没有交点,要么有无限个交点
-//                if (p1.y == p2.y) continue
-//                // point 在p1p2 底部 --> 无交点
-//                if (point.y < Math.min(p1.y, p2.y)) continue
-//                // point 在p1p2 顶部 --> 无交点
-//                if (point.y >= Math.max(p1.y, p2.y)) continue
-//                // 求解 point点水平线与当前p1p2边的交点的 X 坐标
-//                val x = ((point.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x).toDouble()
-//                if (x > point.x) // 当x=point.x时,说明point在p1p2线段上
-//                    nCross++ // 只统计单边交点
-//            }
-//            // 单边交点为偶数,点在多边形之外 ---
+
+
+            var nCross = 0
+            for (i in mPoints.indices) {
+                val p1 = mPoints[i]
+                val p2 = mPoints[(i + 1) % mPoints.size]
+                // 取多边形任意一个边,做点point的水平延长线,求解与当前边的交点个数
+                // p1p2是水平线段,要么没有交点,要么有无限个交点
+                if (p1.y == p2.y) continue
+                // point 在p1p2 底部 --> 无交点
+                if (point.y < Math.min(p1.y, p2.y)) continue
+                // point 在p1p2 顶部 --> 无交点
+                if (point.y >= Math.max(p1.y, p2.y)) continue
+                // 求解 point点水平线与当前p1p2边的交点的 X 坐标
+                val x = ((point.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x).toDouble()
+                if (x > point.x) // 当x=point.x时,说明point在p1p2线段上
+                    nCross++ // 只统计单边交点
+            }
+            // 单边交点为偶数,点在多边形之外 ---
 //            return nCross % 2 == 1
+            return geoPoint.within(polygon) || nCross % 2 == 1
+        }
+
+        fun isPolygonContainsPoint(mPointsList: ArrayList<ArrayList<ArrayList<PointZ>>>, point: Point): Boolean {
+            for (mPoints in mPointsList) {
+                val polygon = createPolygonZ(mPoints[0])
+                val coord = Coordinate(point.x.toDouble(), point.y.toDouble())
+                val geoPoint = geometryFactory.createPoint(coord)
+
+
+                var nCross = 0
+                for (i in mPoints[0].indices) {
+                    val p1 = mPoints[0][i]
+                    val p2 = mPoints[0][(i + 1) % mPoints[0].size]
+                    // 取多边形任意一个边,做点point的水平延长线,求解与当前边的交点个数
+                    // p1p2是水平线段,要么没有交点,要么有无限个交点
+                    if (p1.y == p2.y) continue
+                    // point 在p1p2 底部 --> 无交点
+                    if (point.y < Math.min(p1.y, p2.y)) continue
+                    // point 在p1p2 顶部 --> 无交点
+                    if (point.y >= Math.max(p1.y, p2.y)) continue
+                    // 求解 point点水平线与当前p1p2边的交点的 X 坐标
+                    val x = ((point.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x).toDouble()
+                    if (x > point.x) // 当x=point.x时,说明point在p1p2线段上
+                        nCross++ // 只统计单边交点
+                }
+                // 单边交点为偶数,点在多边形之外 ---
+//            return nCross % 2 == 1
+                if (geoPoint.within(polygon) || nCross % 2 == 1) {
+                    return geoPoint.within(polygon) || nCross % 2 == 1
+                }
+            }
+            return false
         }
 
         private val geometryFactory = GeometryFactory()
@@ -127,6 +159,20 @@ class Lasso {
             return geometryFactory.createPolygon()
         }
 
+        fun createPolygonZ(xys: List<PointZ>): Polygon? {
+            try {
+                val coords: Array<Coordinate?> = arrayOfNulls<Coordinate>(xys.size + 1)
+                for (i in xys.indices) {
+                    coords[i] = Coordinate(xys[i].x.toDouble(), xys[i].y.toDouble())
+                }
+                coords[xys.size] = Coordinate(xys[0].x.toDouble(), xys[0].y.toDouble())
+                return geometryFactory.createPolygon(coords)
+            } catch (e: Exception) {
+                e.printStackTrace()
+            }
+            return geometryFactory.createPolygon()
+        }
+
         /**
          * point3到(point1与point2的连线)的最短距离
          */

+ 3 - 2
demo/src/main/java/com/sybotan/android/demo/tools/ObjectNameUtils.kt

@@ -18,8 +18,9 @@ class ObjectNameUtils {
             if (objectEntity?.classCode!!.contains("SELTCC") || (!TextUtils.isEmpty(objectEntity?.name) && objectEntity?.name!!.contains("照明回路"))) {
                 return if (TextUtils.isEmpty(objectEntity.localId)) "--" else objectEntity.localId.toString()
             }
-            val infos = objectEntity?.infos?.asJsonObject
-            return if (infos?.get("digitalDeliveryID") == null) "--" else infos.get("digitalDeliveryID").toString()
+//            val infos = objectEntity?.infos?.asJsonObject
+//            return if (infos?.get("digitalDeliveryID") == null) "--" else infos.get("digitalDeliveryID").toString()
+            return if (TextUtils.isEmpty(objectEntity.localName)) "--" else objectEntity.localName.toString()
         }
     }
 

+ 39 - 1
demo/src/main/java/com/sybotan/android/demo/viewmodel/ChooseSpaceVM.kt

@@ -251,6 +251,7 @@ class ChooseSpaceVM(
         viewModelScope.launch {
             val rels = getRelations(groupRelConfigEntity, deviceId)
             val spaces = ArrayList<TunableSpace>()
+            val equips = ArrayList<ObjectEntity>()
             for (rel in rels) {
                 val objEntity: ObjectEntity
                 if (rel.entity.objFrom == deviceId) {
@@ -260,6 +261,7 @@ class ChooseSpaceVM(
                 }
                 val obj = objEntity.infos!!.asJsonObject
                 val info = gson.fromJson(obj, SpaceInfo::class.java)
+                equips.add(objEntity)
 //                spaces.add(info.outline[0])
 
                 val tunableSpace = TunableSpace()
@@ -272,10 +274,11 @@ class ChooseSpaceVM(
                 spaces.add(tunableSpace)
             }
             mEmitter.SendDirective(SERVE_AREAS, spaces)
+            mEmitter.SendDirective(EQUIP_RELATION, rels)
         }
     }
 
-    private suspend fun ChooseSpaceVM.getRelations(
+    private suspend fun getRelations(
         groupRelConfigEntity: RelConfigEntityPackClass,
         deviceId: String
     ): ArrayList<RelationPackClass> {
@@ -347,6 +350,39 @@ class ChooseSpaceVM(
         }
     }
 
+    fun getEquips(floorId: String, group: RelConfigEntityPackClass) {
+        viewModelScope.launch {
+            val objects: ArrayList<ObjectEntity> = ArrayList()
+            for (type in group.targetTypes) {
+                val objs = repo.getObjectByCode(type.targetCode!!, buildingId, floorId)
+                if (!CommonUtils.IsNull(objs)) {
+                    objects.addAll(objs)
+                }
+            }
+            mEmitter.SendDirective(EQUIPS, objects)
+        }
+    }
+
+    fun insRel(
+        relationEntitys: ArrayList<RelationEntity>,
+        groupRelConfigEntity: RelConfigEntityPackClass,
+        deviceId: String
+    ) {
+        viewModelScope.launch {
+            val rels = getRelations(groupRelConfigEntity, deviceId)
+            for (rel in rels) {
+                rel.entity.valid = 0
+                repo.insRelation(rel.entity)
+            }
+
+
+            for (rel in relationEntitys) {
+                repo.insRelation(rel)
+            }
+            mActivity.finish()
+        }
+    }
+
 
     companion object {
         const val MAP_LOAD = "MAP_LOAD"
@@ -357,6 +393,8 @@ class ChooseSpaceVM(
         const val FLOORS_LIST = "FLOORS_LIST"
         const val FLOOR_MAP = "FLOOR_MAP"
         const val SPACES = "SPACES"
+        const val EQUIPS = "EQUIPS"
+        const val EQUIP_RELATION = "EQUIP_RELATION"
 
     }
 }

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

@@ -489,7 +489,7 @@ class EquipDetailVM(
         }
     }
 
-    fun getRelObj(group: RelConfigEntityPackClass, code: String) {
+    fun getRelObj(group: RelConfigEntityPackClass) {
         viewModelScope.launch {
             val objects: ArrayList<ObjectEntity> = ArrayList()
             for (type in group.targetTypes) {

+ 4 - 1
demo/src/main/java/com/sybotan/android/demo/viewmodel/GraphyVM.kt

@@ -118,7 +118,7 @@ class GraphyVM(
                                         gemo.y.toInt()
                                     )
                                 }
-                                if (Lasso.isPolygonContainsPoint(list, pointF)) {
+                                if (Lasso.isPolygonContainsPoint(spaceJobModel.outline, pointF)) {
                                     hasProblem = true
                                     break
                                 }
@@ -217,6 +217,9 @@ class GraphyVM(
                                         infos.equipCheck.toInt() == RMTristateSwitch.STATE_RIGHT -> {
                                             child.type = 2
                                         }
+                                        infos.equipCheck.toInt() == 3 -> {
+                                            child.type = 6
+                                        }
                                     }
                                 } else {
                                     child.type = 1

+ 139 - 0
demo/src/main/res/layout/activity_choose_equip.xml

@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ *********************************************************************************************************************
+  ~
+  ~               iFHS7.
+  ~              ;BBMBMBMc                  rZMBMBR              BMB
+  ~              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
+  ~     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
+  ~     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
+  ~      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
+  ~     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
+  ~     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
+  ~     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
+  ~         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
+  ~     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
+  ~      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
+  ~         i0BM: SWKHKGO  MBDv
+  ~           .UB  OOGDM. MK,                                          Copyright (c) 2015-2019.  斯伯坦机器人
+  ~              ,  XMW  ..
+  ~                  r                                                                     All rights reserved.
+  ~
+  ~ *********************************************************************************************************************
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/white"
+    android:orientation="vertical"
+    tools:context="com.sybotan.android.demo.activities.GraphyActivity">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1">
+
+        <com.sybotan.android.graphy.SGraphyView
+            android:id="@+id/graphyView"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginBottom="5dp" />
+
+        <TextView
+            android:id="@+id/floorTv"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="16dp"
+            android:layout_marginTop="16dp"
+            android:background="@color/grey_200"
+            android:drawableRight="@mipmap/icon_push_down"
+            android:gravity="center"
+            android:paddingLeft="10dp"
+            android:paddingTop="5dp"
+            android:paddingRight="10dp"
+            android:paddingBottom="5dp"
+            android:text=""
+            android:textColor="@color/black_272727"
+            android:textSize="16sp" />
+
+        <TextView
+            android:id="@+id/direction"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentBottom="true"
+            android:layout_marginRight="10dp"
+            android:layout_marginBottom="20dp"
+            android:background="@color/grey_200"
+            android:padding="8dp"
+            android:text="->"
+            android:textColor="@color/black_272727"
+            android:textSize="18sp"
+            android:visibility="gone" />
+
+    </RelativeLayout>
+
+    <androidx.appcompat.widget.LinearLayoutCompat
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@color/grey_50"
+        android:orientation="vertical"
+        android:paddingTop="20dp"
+        android:paddingBottom="20dp">
+
+        <androidx.core.widget.NestedScrollView
+            android:layout_width="match_parent"
+            android:layout_height="100dp">
+
+            <TextView
+                android:id="@+id/spaceName"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:paddingLeft="16dp"
+                android:paddingRight="16dp"
+                android:text=""
+                android:textColor="@color/black_272727"
+                android:textSize="13sp" />
+        </androidx.core.widget.NestedScrollView>
+
+
+        <androidx.appcompat.widget.LinearLayoutCompat
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="20dp"
+            android:layout_marginTop="20dp"
+            android:layout_marginRight="20dp"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/close"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:background="@drawable/bg_grey_e6e6e6"
+                android:gravity="center"
+                android:paddingTop="8dp"
+                android:paddingBottom="8dp"
+                android:text="关闭"
+                android:textColor="@color/black_272727"
+                android:textSize="16sp" />
+
+            <TextView
+                android:id="@+id/save"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="36dp"
+                android:layout_weight="1"
+                android:background="@drawable/bg_blue_3bacb2"
+                android:gravity="center"
+                android:paddingTop="8dp"
+                android:paddingBottom="8dp"
+                android:text="保存"
+                android:textColor="@color/white_ffffff"
+                android:textSize="16sp" />
+        </androidx.appcompat.widget.LinearLayoutCompat>
+    </androidx.appcompat.widget.LinearLayoutCompat>
+</LinearLayout>

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

@@ -116,6 +116,7 @@
                 android:textSize="15sp" />
 
             <com.rm.rmswitch.RMTristateSwitch
+                android:visibility="gone"
                 android:id="@+id/doneSwitch"
                 android:layout_width="60dp"
                 android:layout_height="30dp"
@@ -135,6 +136,54 @@
                 app:switchToggleRightImage="@drawable/ic_checked" />
         </LinearLayout>
 
+        <RadioGroup
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="6dp"
+            android:layout_marginRight="6dp"
+            android:orientation="horizontal">
+
+            <RadioButton
+                android:id="@+id/infoTodo"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="5dp"
+                android:layout_weight="1"
+                android:text="信息待完善"
+                android:textColor="@color/grey_900"
+                android:textSize="12sp" />
+
+            <RadioButton
+                android:id="@+id/infoNotDo"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="5dp"
+                android:layout_weight="1"
+                android:text="未做"
+                android:textColor="@color/grey_900"
+                android:textSize="12sp" />
+
+            <RadioButton
+                android:id="@+id/infoDone"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="5dp"
+                android:layout_weight="1"
+                android:text="信息已完善"
+                android:textColor="@color/grey_900"
+                android:textSize="12sp" />
+
+            <RadioButton
+                android:id="@+id/relDone"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="5dp"
+                android:layout_weight="1"
+                android:text="关系已交付"
+                android:textColor="@color/grey_900"
+                android:textSize="12sp" />
+        </RadioGroup>
+
         <include layout="@layout/static_info" />
 
         <include layout="@layout/geometry_info" />

+ 2 - 2
gradle.properties

@@ -17,14 +17,14 @@ SAGA_SERVICE_VERSION=1.4.140
 MAVEN_REPO_RELEASE_URL=http\://dev.dp.sagacloud.cn\:8082/repository/maven-releases/
 EVENTBUS_VERSION=3.1.1
 EASYPERMISSIONS_VERSION=1.2.0
-SAGA_ANDROID_VERSION=1.0.6
+SAGA_ANDROID_VERSION=1.0.7
 JUNIT_VERSION=5.3.1
 KOTLIN_VERSION=1.5.31
 SAGA_GROUP=cn.sagacloud
 SYBOTAN_KOTLIN_VERSION=1.2.42
 android.useAndroidX=true
 LICENSE_NAME=The Apache Software License, Version 2.0
-SAGA_CODE=18
+SAGA_CODE=19
 MAVEN_REPO_SNAPSHOT_URL=http\://dev.dp.sagacloud.cn\:8082/repository/maven-snapshots/
 NEXUS_USERNAME=saga
 DEVELOPER_ID=Andy.Sybotan