Browse Source

feat:结构核查接口及交互逻辑

lihao1 3 years ago
parent
commit
3f789ea269
35 changed files with 1339 additions and 202 deletions
  1. 1 0
      cadengine/build.gradle
  2. 93 58
      cadengine/src/main/java/cn/sagacloud/android/cadengine/FloorScene.kt
  3. 2 2
      cadengine/src/main/java/cn/sagacloud/android/cadengine/Opt.kt
  4. 18 22
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/DoorItem.kt
  5. 94 0
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/QrcodeItem.kt
  6. 9 73
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/SpaceItem.kt
  7. 142 0
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/SpaceNameItem.kt
  8. 135 0
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/TunableSpaceItem.kt
  9. 4 0
      cadengine/src/main/java/cn/sagacloud/android/cadengine/types/Point.kt
  10. 30 0
      cadengine/src/main/java/cn/sagacloud/android/cadengine/types/PointZ.java
  11. 1 1
      cadengine/src/main/java/cn/sagacloud/android/cadengine/types/Space.kt
  12. 16 0
      cadengine/src/main/java/cn/sagacloud/android/cadengine/types/TunableSpace.kt
  13. 259 41
      demo/src/main/java/com/sybotan/android/demo/activities/GraphyActivity.kt
  14. 15 0
      demo/src/main/java/com/sybotan/android/demo/bean/request/ReqAddProblem.java
  15. 16 0
      demo/src/main/java/com/sybotan/android/demo/bean/request/ReqBindQrcode.java
  16. 10 0
      demo/src/main/java/com/sybotan/android/demo/bean/request/ReqCloseProblem.java
  17. 11 0
      demo/src/main/java/com/sybotan/android/demo/bean/request/ReqProblems.java
  18. 9 0
      demo/src/main/java/com/sybotan/android/demo/bean/request/ReqQrcode.java
  19. 17 0
      demo/src/main/java/com/sybotan/android/demo/bean/request/ReqSetJob.java
  20. 15 0
      demo/src/main/java/com/sybotan/android/demo/bean/request/ReqSetProblem.java
  21. 11 0
      demo/src/main/java/com/sybotan/android/demo/bean/result/AddProblemModel.java
  22. 8 0
      demo/src/main/java/com/sybotan/android/demo/bean/result/BindQrcodeModel.java
  23. 8 0
      demo/src/main/java/com/sybotan/android/demo/bean/result/CloseProblemModel.java
  24. 13 0
      demo/src/main/java/com/sybotan/android/demo/bean/result/Position.java
  25. 13 0
      demo/src/main/java/com/sybotan/android/demo/bean/result/ProblemsModel.java
  26. 12 0
      demo/src/main/java/com/sybotan/android/demo/bean/result/QrcodeModel.java
  27. 8 0
      demo/src/main/java/com/sybotan/android/demo/bean/result/SetJobModel.java
  28. 10 0
      demo/src/main/java/com/sybotan/android/demo/bean/result/SetProblemModel.java
  29. 6 1
      demo/src/main/java/com/sybotan/android/demo/bean/result/SpaceJobModel.java
  30. 12 0
      demo/src/main/java/com/sybotan/android/demo/bean/result/Z.java
  31. 50 0
      demo/src/main/java/com/sybotan/android/demo/retrofit/API.java
  32. 1 1
      demo/src/main/java/com/sybotan/android/demo/retrofit/RetrofitFactory.java
  33. 170 2
      demo/src/main/java/com/sybotan/android/demo/viewmodel/GraphyVM.java
  34. 10 0
      demo/src/main/res/drawable/bg_grey_e6e6e6.xml
  35. 110 1
      demo/src/main/res/layout/activity_graphy.xml

+ 1 - 0
cadengine/build.gradle

@@ -98,6 +98,7 @@ dependencies {
     implementation group: 'cn.sagacloud', name: 'sybotan-android-graphy', version: SYBOTAN_ANDROID_VERSION
     //noinspection GradleDependency
     implementation 'org.greenrobot:eventbus:3.0.0'
+    implementation 'com.google.code.gson:gson:2.8.1'
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

+ 93 - 58
cadengine/src/main/java/cn/sagacloud/android/cadengine/FloorScene.kt

@@ -23,9 +23,12 @@ import org.greenrobot.eventbus.ThreadMode
 open class FloorScene : SGraphyScene() {
     //点击事件回调到界面
     lateinit var topUp: OnSingleTopUp
-//    var item: PointItem? = null
+
+    //    var item: PointItem? = null
 //    val point = Point()
     var canEdit = true
+    val point = Point()
+    var item: QrcodeItem? = null
 
     /** 默认缩放比例,用于指定最小缩放比例*/
     var defaultPointScale = 0.01785718f
@@ -34,8 +37,16 @@ open class FloorScene : SGraphyScene() {
      * normol 普通可以查看,可以点击问题点的模式
      * dot 绘制问题点
      * pipe 绘制管道模式
+     * qrcode 绘制二维码
      */
     var type: String? = "normal"
+
+    /**
+     * nothing 不显示任何操作界面
+     * space 选中某一空间
+     */
+    var mapType: String? = "nothing"
+    var choseSpace: TunableSpaceItem? = null
     var pipeLineList: ArrayList<PointF> = ArrayList()
 
     /** item 数据  */
@@ -117,7 +128,7 @@ open class FloorScene : SGraphyScene() {
     var spaceList = ArrayList<SpaceItem>()
 
     /** 空间名称 list   */
-    val spaceNameList = ArrayList<SpatialCenterItem>()
+    val spaceNameList = ArrayList<SpaceNameItem>()
 
     /** 门 list   */
     var doorList = ArrayList<DoorItem>()
@@ -128,9 +139,15 @@ open class FloorScene : SGraphyScene() {
     /** 点 */
     val pointItemList = java.util.ArrayList<PointItem>()
 
+    /** 二维码 */
+    val qrcodeItemList = java.util.ArrayList<QrcodeItem>()
+
     /** 管道 */
     val pipeItemList = ArrayList<PipeLineItem>()
 
+    /** 有任务的空间 list   */
+    var tunableSpaceList = ArrayList<TunableSpaceItem>()
+
     /**
      *  获取底图压缩文件
      *
@@ -207,11 +224,11 @@ open class FloorScene : SGraphyScene() {
         }
 
         // 添加空间名称
-        if (elements.spaces != null) {
-            for (space in elements.spaces!!) {
-                addSpaceName(space)
-            }
-        }
+//        if (elements.spaces != null) {
+//            for (space in elements.spaces!!) {
+//                addSpaceName(space)
+//            }
+//        }
 
         // 添加门
         if (elements.doors != null) {
@@ -240,6 +257,22 @@ open class FloorScene : SGraphyScene() {
             item.zOrder = 100000f
             addItem(item)
         }
+
+        // 添加空间
+        for (tunableSpace in tunableSpaceList) {
+            tunableSpace.isVisible = isShowSpace
+            tunableSpace.zOrder = 99996f
+            addItem(tunableSpace)
+
+            val space = Space()
+            space.outLine = tunableSpace.data.outLine
+            space.name = tunableSpace.data.name
+            val item = SpaceNameItem(space)
+            item.zOrder = 99999f
+            item.isVisible = isShowSpace
+            spaceNameList.add(item)
+            addItem(item)
+        }
     } // Function addBaseMapItem()
 
     /**
@@ -296,17 +329,17 @@ open class FloorScene : SGraphyScene() {
      *
      *  @param  space       空间
      */
-    open fun addSpaceName(space: Space) {
-        if (space.outLine != null) {
-            val scitem = SpatialCenterItem(space.name!!)
-            scitem.moveTo(PointF(space.location!!.points!![0].x, -space.location!!.points!![0].y))
-            scitem.zOrder = 100f
-            scitem.isVisible = true
-            spaceNameList.add(scitem)
-            this.addItem(scitem)
-
-        }
-    } // Function addSpace()
+//    open fun addSpaceName(space: Space) {
+//        if (space.outLine != null) {
+//            val scitem = SpatialCenterItem(space.name!!)
+//            scitem.moveTo(PointF(space.location!!.points!![0].x, -space.location!!.points!![0].y))
+//            scitem.zOrder = 100f
+//            scitem.isVisible = true
+//            spaceNameList.add(scitem)
+//            this.addItem(scitem)
+//
+//        }
+//    } // Function addSpace()
 
     /**
      *  添加门到 scene 中
@@ -369,45 +402,51 @@ open class FloorScene : SGraphyScene() {
     }
 
     override fun onSingleTapUp(e: SMotionEvent): Boolean {
+        //如果只是查看模式,可以选中空间,进行空间内业务操作
+        if ("normal".equals(type)) {
+            var hasChose = false
+            for (space in tunableSpaceList) {
+                val polygonContainsPoint = Lasso.isPolygonContainsPoint(
+                    space.mPoints,
+                    android.graphics.Point(e.x.toInt(), -e.y.toInt())
+                )
+                if (polygonContainsPoint) {
+                    mapType = "space"
+                    choseSpace = space
+                    hasChose = true
+                    break
+                }
+            }
+            if (!hasChose) {
+                mapType = "nothing"
+                choseSpace = null
+            }
+        }
+
+
         var outSide = false
         //计算控制点的边界
         //是否已经拥有该点
         //打点业务
-
         if ("dot".equals(type)) {
-            //便利该点所在的空间
             for (space in spaceList) {
                 val polygonContainsPoint = Lasso.isPolygonContainsPoint(
                     space.mPoints,
                     android.graphics.Point(e.x.toInt(), -e.y.toInt())
                 )
-//                if (polygonContainsPoint) {
                 outSide = true
                 space.paint.color = Opt.spaceChoseColor
                 space.outPaint.color = Color.rgb(0xbd, 0xe8, 0xfe)
-//                val point =Point()
-//                point.mX = e.x
-//                point.mY = e.y
-//                if (item != null) {
-//                    removeItem(item!!)
-//                }
-//                var item = PointItem(point, null, defaultPointScale)
-//                item!!.isVisible = true
-//                item!!.zOrder = 100000f
-//                addItem(item!!)
-//                } else {
-//                    space!!.paint.color = Opt.spaceColor
-//                    space.outPaint.color = Color.rgb(0xff, 0xff, 0xff)
-//                }
             }
-            val point =Point()
-            point.mX = e.x
-            point.mY = e.y
-            var item = PointItem(point, null, defaultPointScale)
-            item!!.isVisible = true
-            item!!.zOrder = 100000f
-            pointItemList.add(item!!)
-            //添加问题点
+//            val point = Point()
+//            point.mX = e.x
+//            point.mY = e.y
+//            var item = PointItem(point, null, defaultPointScale)
+//            item!!.isVisible = true
+//            item!!.zOrder = 100000f
+//            pointItemList.add(item!!)
+
+            //添加问题点业务
             for (item in pointItemList) {
                 item.isVisible = isShowSpace
                 item.zOrder = 100000f
@@ -417,21 +456,6 @@ open class FloorScene : SGraphyScene() {
                 return true
             }
         }
-//        else {
-//            for (space in spaceList) {
-//                val polygonContainsPoint = Lasso.isPolygonContainsPoint(
-//                    space.mPoints,
-//                    android.graphics.Point(e.x.toInt(), -e.y.toInt())
-//                )
-//                if (polygonContainsPoint) {
-//                    outSide = true
-//                    break
-//                }
-//            }
-//            if (!outSide) {
-//                return true
-//            }
-//        }
 
         //绘制管道业务
         else if ("pipe".equals(type)) {
@@ -450,6 +474,17 @@ open class FloorScene : SGraphyScene() {
                 item.zOrder = 100000f
                 addItem(item)
             }
+        } else if ("qrcode".equals(type)) {
+            point.mX = e.x
+            point.mY = e.y
+
+            if (item != null) {
+                removeItem(item!!)
+            }
+            item = QrcodeItem(point, null, defaultPointScale)
+            item!!.isVisible = true
+            item!!.zOrder = 100000f
+            addItem(item!!)
         }
 
         if (topUp != null) {

+ 2 - 2
cadengine/src/main/java/cn/sagacloud/android/cadengine/Opt.kt

@@ -12,7 +12,7 @@ class Opt {
         /** 墙颜色 */
         val wallColor = Color.rgb(0xff, 0xff, 0xff)
         /** 柱子颜色 */
-        val columnColor = Color.rgb(0xe2, 0xe5, 0xec)
+        val columnColor = Color.rgb(0x5b, 0x5b, 0x5b)
         /** 虚拟墙颜色 */
         val virtualWallColor = Color.rgb(0xC3,0xC7,0xCb)
         /** 默认空间颜色 */
@@ -26,7 +26,7 @@ class Opt {
         /** 被选中的空间颜色 */
         val spaceChoseColor = Color.rgb(0xe6, 0xfa, 0xff)
         /** 门颜色 */
-        val doorColor = Color.rgb(0x0c, 0x90, 0xeb)
+        val doorColor = Color.rgb(0x97, 0x63, 0x17)
         /** 窗户颜色 */
         val windowColor = Color.rgb(0xba, 0xe0, 0xfd)
         /** 文字颜色 */

+ 18 - 22
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/DoorItem.kt

@@ -9,11 +9,6 @@ import kotlin.math.sqrt
 import kotlin.math.abs
 
 
-/**
- * 门item
- *
- * @author 付国宝
- */
 class DoorItem(private val data: Door, parent: SGraphyItem? = null) : SGraphyItem(parent) {
     /** 画笔 */
     private val paint1 = Paint()
@@ -52,16 +47,17 @@ class DoorItem(private val data: Door, parent: SGraphyItem? = null) : SGraphyIte
                 // 角度为
                 val fo = atan2(-data.faceDirection!!.y, data.faceDirection!!.x)
                 // 门朝向角度
-                angle = if(data.faceDirection!!.x > 0) {
-                    fo
-                } else {
-                    fo + Math.PI.toFloat()
-                }
+                angle =
+                    if (data.faceDirection!!.x > 0) {
+                        fo
+                    } else {
+                        fo + Math.PI.toFloat()
+                    }
 
-//                val dir = data.faceDirection!!.x * (data.handDirection!!.y - data.faceDirection!!.y) - data.faceDirection!!.y * (data.handDirection!!.x - data.faceDirection!!.x)
-//                if (dir < 0) {
-//                    startAng = -90f
-//                }
+////                val dir = data.faceDirection!!.x * (data.handDirection!!.y - data.faceDirection!!.y) - data.faceDirection!!.y * (data.handDirection!!.x - data.faceDirection!!.x)
+////                if (dir < 0) {
+////                    startAng = -90f
+////                }
 
                 // 计算旋转点
                 if (abs(data.handDirection!!.x) > abs(data.handDirection!!.y)) {
@@ -105,13 +101,13 @@ class DoorItem(private val data: Door, parent: SGraphyItem? = null) : SGraphyIte
      * @param   canvas          画布
      * @param   rect            绘制区域
      */
-    override fun onDraw(canvas : Canvas) {
-        canvas.translate(p.x, p.y);
-        canvas.rotate(angle * 180f / Math.PI.toFloat())
-
-        canvas.drawLine(0f, 0f, d, 0f, paint1)
+    override fun onDraw(canvas: Canvas) {
+//        canvas.translate(p.x, p.y);
+//        canvas.rotate(angle * 180f / Math.PI.toFloat())
 //
-//        canvas.drawArc(-d, -d, d, d, startAng, 90f ,false, paint2)
-
+//        canvas.drawLine(0f, 0f, d, 0f, paint1)
+        canvas.drawLine(data.outLine!![0][0].x, -data.outLine!![0][0].y, data.outLine!![0][1].x, -data.outLine!![0][1].y, paint1)
+//        canvas.drawArc(-d, -d, d, d, startAng, 90f, false, paint2)
+        super.onDraw(canvas)
     } // Function onDraw()
-} // Class DoorItem
+} // Class DoorItem

+ 94 - 0
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/QrcodeItem.kt

@@ -0,0 +1,94 @@
+package cn.sagacloud.android.cadengine.items
+
+
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import cn.sagacloud.android.cadengine.types.Point
+import com.sybotan.android.graphy.SGraphyItem
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/4
+ */
+class QrcodeItem(val data: Point, parent: SGraphyItem? = null, defaultScale: Float) :
+    SGraphyItem(parent) {
+    /** 新建 画笔 */
+    val mPaint_inner = Paint()
+    val mPaint_center = Paint()
+    val mPaint_outer = Paint()
+
+    /** 按时 画笔 */
+    val not_overTime_inner = Paint()
+    val not_overTime_outer = Paint()
+
+    /** 逾期 画笔 */
+    val overTime_inner = Paint()
+    val overTime_outer = Paint()
+
+    /** 承接查验复核中 */
+    val checkReviewing_inner = Paint()
+    val checkReviewing_outer = Paint()
+    var mDefaultScale = 0f
+    //var defaultScale = 1.0f
+    //var mScale = 1f
+
+    init {
+        mDefaultScale = defaultScale;
+        /** 按时 */
+        not_overTime_inner.color = Color.parseColor("#ffffff")
+        not_overTime_inner.isAntiAlias = true
+        not_overTime_inner.style = Paint.Style.FILL
+
+        not_overTime_outer.color = Color.parseColor("#04df97")//绿色
+        not_overTime_outer.isAntiAlias = true
+        not_overTime_outer.style = Paint.Style.FILL
+
+        /** 逾期 */
+        overTime_inner.color = Color.parseColor("#ffffff")
+        overTime_inner.isAntiAlias = true
+        overTime_inner.style = Paint.Style.FILL
+
+        overTime_outer.color = Color.parseColor("#ff3b33")//红色
+        overTime_outer.isAntiAlias = true
+        overTime_outer.style = Paint.Style.FILL
+
+        /** 承接查验复核中 */
+        checkReviewing_inner.color = Color.parseColor("#ffffff")
+        checkReviewing_inner.isAntiAlias = true
+        checkReviewing_inner.style = Paint.Style.FILL
+
+        checkReviewing_outer.color = Color.parseColor("#F7B500")//黄色
+        checkReviewing_outer.isAntiAlias = true
+        checkReviewing_outer.style = Paint.Style.FILL
+
+        /** 新建 */
+        //内圈
+        mPaint_inner.color = Color.parseColor("#5E59E1")
+        mPaint_inner.isAntiAlias = true
+        mPaint_inner.style = Paint.Style.FILL
+        //中圈
+        mPaint_center.color = Color.parseColor("#ffffff")
+        mPaint_center.isAntiAlias = true
+        mPaint_center.style = Paint.Style.FILL
+        //外圈
+        mPaint_outer.color = Color.parseColor("#260c90eb")
+        mPaint_outer.isAntiAlias = true
+        mPaint_outer.style = Paint.Style.FILL
+    }
+
+    /**
+     * Item绘制操作
+     *
+     * @param   canvas          画布
+     * @param   rect            绘制区域
+     */
+    override fun onDraw(canvas: Canvas) {
+        data.scalePoint = mDefaultScale / scene!!.view!!.scale
+//        canvas.drawCircle(data.mX, data.mY, 2400f * data.scalePoint, mPaint_outer)
+//        canvas.drawCircle(data.mX, data.mY, 1200f * data.scalePoint, mPaint_center)
+        canvas.drawCircle(data.mX, data.mY, 2000f * data.scalePoint, mPaint_inner)
+        super.onDraw(canvas)
+    } // Function onDraw()
+
+}

+ 9 - 73
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/SpaceItem.kt

@@ -13,16 +13,22 @@ import com.sybotan.android.graphy.SGraphyItem
 class SpaceItem(private val data: Space, parent: SGraphyItem? = null) : SGraphyItem(parent) {
     /** 画笔 */
     val paint = Paint()
+
     /** 墙轮廓 */
     private var spacePath: Path? = null
+
     /** 空间轮廓线坐标list  */
     private val pointArr = ArrayList<ArrayList<PointF>>()
+
     /** X坐标最小值  */
     private var minX = 0f
+
     /** X坐标最大值  */
     private var maxX = 0f
+
     /** Y坐标最小值  */
     private var minY = 0f
+
     /** Y坐标最大值  */
     private var maxY = 0f
     val outPaint = Paint()
@@ -71,35 +77,6 @@ class SpaceItem(private val data: Space, parent: SGraphyItem? = null) : SGraphyI
             e.printStackTrace()
         }
 
-        //if (data.outLine!!.size > 0) {
-//            val tempArr = this.data.OutLine
-//            this.minX = tempArr[0][0].x
-//            this.maxX = this.minX
-//            this.minY = -(tempArr[0][0].y)
-//            this.maxY = this.minY
-            // 处理轮廓点数组,同时计算最大最小值
-//            this.pointArr = tempArr.map(t => {
-//                var tempArr = t.map(it => {
-//                    var x = it.X,
-//                    y = -it.Y
-//                    if (x < this.minX) {
-//                        this.minX = x
-//                    }
-//                    if (y < this.minY) {
-//                        this.minY = y
-//                    }
-//                    if (x > this.maxX) {
-//                        this.maxX = x
-//                    }
-//                    if (y > this.maxY) {
-//                        this.maxY = y
-//                    }
-//                    return SPoint(x, y)
-//                })
-//                return tempArr
-//            })
-        //}
-
         outPaint.style = Paint.Style.STROKE
         outPaint.color = Color.rgb(0xff, 0xff, 0xff)
         outPaint.strokeWidth = 20f
@@ -110,61 +87,20 @@ class SpaceItem(private val data: Space, parent: SGraphyItem? = null) : SGraphyI
      *
      * @return SRect
      */
-    override fun boundingRect() : RectF {
+    override fun boundingRect(): RectF {
         return RectF(minX, minY, maxX, maxY)
     } // Function boundingRect()
 
     /**
-     * 判断点是否在区域内
-     *
-     * @param x
-     * @param y
-     */
-    override fun contains(x: Float, y: Float): Boolean {
-//        if (this.data?.OutLine!!.size > 0) {
-//            var nCross: Double = 0.0
-//            var point = ArrayList<String>()
-//            point.add("x")
-//            point.add("y")
-//            var APoints = this.data?.OutLine!!.get(0)
-//            var length = APoints.size
-//            var p1: ArrayList<Point>? = null
-//            var p2: ArrayList<Point>? = null
-//            var i: Int? = null
-//            var xinters: Double? = null
-//            p1 = APoints.get(0)
-//            i == 1
-//            while (i!! <= length){
-//                p2 = APoints.get((i % length))
-//                if (point[0] > Math.min(p1.X, p2.X) && point[0] <= Math.max(p1.X, p2.X)) {
-//                    if (point[1] <= Math.max(p1.Y, p2.Y)) {
-//                        if (p1.X != p2.X) {
-//                            //计算位置信息
-//                            xinters = ((point[0] - p1.X) * (p2.Y - p1.Y)) / (p2.X - p1.X) + p1.Y
-//                            if (p1.Y == p2.Y || point[1] <= xinters) {
-//                                nCross++
-//                            }
-//                        }
-//                    }
-//                }
-//                p1 = p2
-//                i++
-//            }
-//            return nCross % 2 === 1
-//        }
-        return false
-    } // Function contains()
-
-    /**
      * Item绘制操作
      *
      * @param   canvas          画布
      * @param   rect            绘制区域
      */
-    override fun onDraw(canvas : Canvas) {
+    override fun onDraw(canvas: Canvas) {
         if (null != spacePath) {
             paint.style = Paint.Style.FILL
-            paint.color = Opt.spaceColor;
+            paint.color = Opt.spaceColor
             canvas.drawPath(spacePath!!, paint)
 
 

+ 142 - 0
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/SpaceNameItem.kt

@@ -0,0 +1,142 @@
+package cn.sagacloud.android.cadengine.items
+
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.graphics.RectF
+import android.graphics.Typeface
+import android.text.Layout
+import android.text.StaticLayout
+import android.text.TextPaint
+import cn.sagacloud.android.cadengine.Opt
+import cn.sagacloud.android.cadengine.types.Space
+import com.sybotan.android.graphy.SGraphyItem
+
+
+/**
+ * 空间名称item
+ *
+ * @author 付国宝re
+ */
+class SpaceNameItem(val data: Space, parent: SGraphyItem? = null) : SGraphyItem(parent) {
+    /** 画笔 */
+    private val paintText = TextPaint()
+
+    /** X坐标最小值  */
+    private var minX = 0f
+
+    /** X坐标最大值  */
+    private var maxX = 0f
+
+    /** Y坐标最小值  */
+    private var minY = 0f
+
+    /** Y坐标最大值  */
+    private var maxY = 0f
+    private var textX = 0f
+    private var textY = 0f
+
+
+    init {
+        try {
+            zOrder = 1f
+            if (data.outLine != null && data.outLine!!.size > 0 && data.outLine!![0].size > 0) {
+                minX = 9999999f
+                maxX = -9999999f
+                minY = 9999999f
+                maxY = -9999999f
+
+                for (line in data.outLine!!) {
+                    if (line.size < 1) {
+                        continue
+                    }
+                    for (p in line) {
+                        if (p.x < minX) {
+                            minX = p.x
+                        }
+                        if (p.x > maxX) {
+                            maxX = p.x
+                        }
+                        if (-p.y < minY) {
+                            minY = -p.y
+                        }
+                        if (-p.y > maxY) {
+                            maxY = -p.y
+                        }
+                    }
+                }
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+        paintText.style = Paint.Style.FILL
+        paintText.flags = Paint.ANTI_ALIAS_FLAG
+        paintText.color = Opt.textColor
+        paintText.textSize = 700f
+        val font: Typeface = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)
+        paintText.setTypeface(font)
+//        paintText.textSkewX - 0.5f
+
+//        textX = (minX + ((maxX - minX) / 2)) /*- 250*/
+//        textY = (minY + ((maxY - minY) / 2)) - paintText.measureText(data.name!!) / 2
+//
+//        if (data.name!!.contains("走廊2")) {
+//            textX -= 400f
+//        } else if (data.name!!.contains("走廊1")) {
+//            textY -= 5000f
+//        } else if (data.name!!.contains("财务室旁开间办公区")) {
+//            textY -= 2000f
+//        }
+        textX = (minX + ((maxX - minX) / 2)) - paintText.measureText(data.name!!) / 2 /*- 250*/
+        textY = (minY + ((maxY - minY) / 2)) + 125f
+    } // Constructor
+
+
+    /**
+     * Item对象边界区域
+     *
+     * @return SRect
+     */
+    override fun boundingRect(): RectF {
+        return RectF(minX, minY, maxX, maxY)
+    } // Function boundingRect()
+
+    /**
+     * 判断点是否在区域内
+     *
+     * @param x
+     * @param y
+     */
+    override fun contains(x: Float, y: Float): Boolean {
+        return false
+    } // Function contains()
+
+    /**
+     * Item绘制操作
+     *
+     * @param   canvas          画布
+     * @param   rect            绘制区域
+     */
+    override fun onDraw(canvas: Canvas) {
+        canvas.save()
+        canvas.rotate(-30f, textX, textY)
+//        if (data.name!!.equals("张联庆旁办公室")) {
+//            val layout = StaticLayout(data.name!!, paintText, 3500, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, true)
+//            canvas.translate(textY + 1000, -textX - 1000)
+//            layout.draw(canvas)
+//        } else if (data.name!!.equals("会议室11") || data.name!!.equals("会议室12")) {
+//            val layout = StaticLayout(data.name!!, paintText, 2300, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, true)
+//            canvas.translate(textY + 500, -textX - 1000)
+//            layout.draw(canvas)
+//        } else {
+//            canvas.drawText(data.name!!, textY, -textX, paintText)
+//        }
+//        canvas.rotate(-90f)
+//        canvas.restore()
+        var x = textX
+        var y = textY * 0.95
+
+        canvas.rotate(30f)
+        canvas.restore()
+        super.onDraw(canvas)
+    } // Function onDraw()
+} // Class SpaceItem

+ 135 - 0
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/TunableSpaceItem.kt

@@ -0,0 +1,135 @@
+package cn.sagacloud.android.cadengine.items
+
+import android.graphics.*
+import android.text.TextPaint
+import cn.sagacloud.android.cadengine.Opt
+import cn.sagacloud.android.cadengine.types.Space
+import cn.sagacloud.android.cadengine.types.TunableSpace
+import com.sybotan.android.graphy.SGraphyItem
+
+
+/**
+ * 可调节item
+ *
+ */
+class TunableSpaceItem(val data: TunableSpace, parent: SGraphyItem? = null) : SGraphyItem(parent) {
+    /** 画笔 */
+    val paint = Paint()
+    val centerPaint = Paint()
+    val outPaint = Paint()
+    private val paintText = TextPaint()
+
+    /** 墙轮廓 */
+    private var spacePath: Path? = null
+    /** 空间轮廓线坐标list  */
+    //private val pointArr = ArrayList<ArrayList<PointF>>()
+    /** X坐标最小值  */
+    private var minX = 0f
+
+    /** X坐标最大值  */
+    private var maxX = 0f
+
+    /** Y坐标最小值  */
+    private var minY = 0f
+
+    /** Y坐标最大值  */
+    private var maxY = 0f
+
+    var mPoints = ArrayList<PointF>()
+
+    init {
+        try {
+            zOrder = 1f
+            if (data.outLine != null && data.outLine!!.size > 0 && data.outLine!![0].size > 0) {
+                minX = 9999999f
+                maxX = -9999999f
+                minY = 9999999f
+                maxY = -9999999f
+
+                for (line in data.outLine!!) {
+                    if (line.size < 1) {
+                        mPoints.add(PointF(data.outLine!![0][0].x, data.outLine!![0][0].y))
+                        continue
+                    }
+                    var path = Path()
+                    path.moveTo(line[0].x, -line[0].y)
+                    for (p in line) {
+                        if (p.x < minX) {
+                            minX = p.x
+                        }
+                        if (p.x > maxX) {
+                            maxX = p.x
+                        }
+                        if (-p.y < minY) {
+                            minY = -p.y
+                        }
+                        if (-p.y > maxY) {
+                            maxY = -p.y
+                        }
+                        mPoints.add(PointF(p.x, p.y))
+                        path.lineTo(p.x, -p.y)
+                    }
+                    path.close()
+                    if (spacePath == null) {
+                        spacePath = path
+                    } else {
+                        // spacePath.b
+                    }
+                }
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+
+        paintText.style = Paint.Style.FILL
+        paintText.flags = Paint.ANTI_ALIAS_FLAG
+        paintText.color = Opt.textColor
+        paintText.textSize = 800f
+
+        paint.style = Paint.Style.FILL
+        paint.flags = Paint.ANTI_ALIAS_FLAG
+        paint.isAntiAlias = true
+        paint.color = Color.parseColor("#007CDB")
+        //paint.color = Opt.spaceColor
+
+        outPaint.style = Paint.Style.STROKE
+        outPaint.color = Color.parseColor("#7E96FF")
+        outPaint.setAntiAlias(true)
+        outPaint.strokeWidth = 100f
+
+        centerPaint.style = Paint.Style.STROKE
+        centerPaint.color = Color.parseColor("#7E96FF")
+        centerPaint.setAntiAlias(true)
+        centerPaint.strokeWidth = 200f
+
+    } // Constructor
+
+
+    /**
+     * Item对象边界区域
+     *
+     * @return SRect
+     */
+    override fun boundingRect(): RectF {
+        return RectF(minX, minY, maxX, maxY)
+    } // Function boundingRect()
+
+
+    /**
+     * Item绘制操作
+     *
+     * @param   canvas          画布
+     * @param   rect            绘制区域
+     */
+    override fun onDraw(canvas: Canvas) {
+        if (null != spacePath) {
+            if (data.jobStatus.equals("01")) {
+                paint.color = Color.parseColor("#EEF496")
+            } else {
+                paint.color = Color.parseColor("#33F76B65")
+            }
+            canvas.drawPath(spacePath!!, paint)
+        }
+        super.onDraw(canvas)
+    } // Function onDraw()
+} // Class SpaceItem

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

@@ -5,8 +5,12 @@ package cn.sagacloud.android.cadengine.types
  * Date: 2021/6/4
  */
 class Point {
+    //问题id
+    var id: String? = null
+
     /** X坐标  */
     var mX = 0f
+
     /** Y坐标  */
     var mY = 0f
 

+ 30 - 0
cadengine/src/main/java/cn/sagacloud/android/cadengine/types/PointZ.java

@@ -0,0 +1,30 @@
+package cn.sagacloud.android.cadengine.types;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/10
+ */
+public class PointZ {
+    @SerializedName("X")
+    public float x;
+    @SerializedName("Y")
+    public float y;
+    @SerializedName("Z")
+    public float z;
+
+    public PointZ() {
+    }
+
+    public PointZ(float x, float y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public PointZ(float x, float y, float z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+}

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

@@ -17,7 +17,7 @@ class Space {
     /** 名称  */
     var name: String? = null
     /** 轮廓线  */
-    var outLine: ArrayList<ArrayList<PointF>>? = null
+    var outLine: ArrayList<ArrayList<PointZ>>? = null
     /** 对应Revit模型id */
     var sourceId: String? = null
     /** 补充信息    */

+ 16 - 0
cadengine/src/main/java/cn/sagacloud/android/cadengine/types/TunableSpace.kt

@@ -0,0 +1,16 @@
+package cn.sagacloud.android.cadengine.types
+
+import android.graphics.PointF
+
+/**
+ * 可调节空间空间 item 类
+ *
+ */
+class TunableSpace {
+    /** 轮廓线  */
+    var outLine: ArrayList<ArrayList<PointZ>>? = null
+    var name: String? = null
+    var jobStatus: String? = null
+    var id: String? = null
+    var localName: String? = null
+}

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

@@ -23,35 +23,32 @@
 
 package com.sybotan.android.demo.activities
 
-import android.app.Activity
-import android.graphics.BitmapFactory
-import android.graphics.PointF
-import android.support.v7.app.AppCompatActivity
 import android.os.Bundle
 import android.util.Log
-import android.util.SizeF
 import android.widget.Toast
 import cn.sagacloud.android.cadengine.FloorScene
 import cn.sagacloud.cadengine.HttpDownloadMap
-import com.fasterxml.jackson.databind.PropertyNamingStrategy
 import com.sybotan.android.demo.R
-import com.sybotan.android.demo.R.id.graphyView
-import com.sybotan.android.demo.entitiies.Revit
-import com.sybotan.android.demo.graphy.GraphyWallItem
-import com.sybotan.android.graphy.SGraphyScene
 import com.sybotan.android.graphy.events.SGraphyViewMoveEvent
-import com.sybotan.android.graphy.items.SGraphyClockItem
-import com.sybotan.base.utils.SJsonUtil
 import kotlinx.android.synthetic.main.activity_graphy.*
 import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.Subscribe
 import org.jetbrains.anko.doAsync
 import org.jetbrains.anko.uiThread
-import android.support.v4.app.ActivityCompat.startActivityForResult
 
 import android.content.Intent
 import android.view.View
 import cn.sagacloud.android.cadengine.items.PointItem
+import cn.sagacloud.android.cadengine.items.QrcodeItem
+import cn.sagacloud.android.cadengine.items.SpaceNameItem
+import cn.sagacloud.android.cadengine.items.TunableSpaceItem
+import cn.sagacloud.android.cadengine.types.Point
+import cn.sagacloud.android.cadengine.types.Space
+import cn.sagacloud.android.cadengine.types.TunableSpace
+import com.google.gson.Gson
+import com.sybotan.android.demo.bean.result.Position
+import com.sybotan.android.demo.bean.result.ProblemsModel
+import com.sybotan.android.demo.bean.result.QrcodeModel
 import com.sybotan.android.demo.bean.result.SpaceJobModel
 import com.sybotan.android.demo.viewmodel.GraphyVM
 import com.zbar.lib.CaptureActivity
@@ -63,6 +60,8 @@ class GraphyActivity : BaseActivity() {
         private val REQUEST_CODE_SCAN = 0x0000 // 扫描二维码
     }
 
+    lateinit var graphyVM: GraphyVM
+
     //实际距离
     val distance = 1800f
 
@@ -70,6 +69,7 @@ class GraphyActivity : BaseActivity() {
     var realDistance = 0f
 
     val scene = FloorScene()
+    val gson = Gson()
 
     //    val path = "base/cbde057b91e711eb9901557a780001bf.jsonz"
 //    val path = "base/ebd53bb00d3511eb9a1db95f725712e8.jsonz"
@@ -98,10 +98,7 @@ class GraphyActivity : BaseActivity() {
 
         /** 开启异步 */
         doAsync {
-//            scene.loadUrl("http://adm.sagacloud.cn/image-service/common/file_get?systemId=revit&key=base/61a99fc1a66b11eb8f633d7605ae9def.jsonz")
-//            scene.loadUrl("http://api.sagacloud.cn/dp-auxiliary/image-service/common/file_get?systemId=revit&key=Fl42010500018b580334dcf111e8a553db1eadfac99320190803114958bim.jsonz",false)
-            val downloadGZIPMap =
-                HttpDownloadMap.downloadGZIPMap(path)
+            val downloadGZIPMap = HttpDownloadMap.downloadGZIPMap(path)
             if (downloadGZIPMap != null) {
                 scene.loadData(downloadGZIPMap!!)
             }
@@ -119,35 +116,52 @@ class GraphyActivity : BaseActivity() {
                 Log.e("viewH", graphyView.measuredHeight.toString())
             }
         }
-        nfc.setOnClickListener { Toast.makeText(this, "正在开发中,敬请期待", Toast.LENGTH_SHORT).show() }
-        modelCheckBox.setOnCheckedChangeListener { buttonView, isChecked ->
-            if (isChecked) {
-                modelSubmit.isEnabled = true
-                modelSubmit.alpha = 1f
-            } else {
-                modelSubmit.isEnabled = false
-                modelSubmit.alpha = 0.3f
-            }
-        }
+        /** 点击监听 */
+        initListener()
+        /** 图形点击-poc业务 */
+        initSingleTopUp()
+        /** 网络请求回调处理 */
+        initViewModel()
 
-        addDot.setOnClickListener {
-            scene.type = "dot"
-            addDot.alpha = 0.3f
-        }
 
-        qrcode.setOnClickListener {
-            val intent = Intent(this@GraphyActivity, CaptureActivity::class.java)
-            startActivityForResult(intent, REQUEST_CODE_SCAN)
-        }
+        return
+    } // Function onCreate()
 
+    /**
+     * 图形点击事件
+     * */
+    private fun initSingleTopUp() {
         scene.setOnSingleTopUp(object : FloorScene.OnSingleTopUp {
             override fun onSingUp(x: Float, y: Float) {
+                //选中空间完毕界面逻辑
+                if (scene.mapType.equals("space")) {
+                    spaceStructure.visibility = View.VISIBLE
+                    spaceName.text = scene.choseSpace!!.data.localName
+                    graphyVM.getProblem(scene.choseSpace)
+                    graphyVM.getQrcode(scene.choseSpace)
+                    //未选中空间
+                } else if (scene.mapType.equals("nothing")) {
+                    spaceStructure.visibility = View.GONE
+                    qrcodeLl.visibility = View.GONE
+                    for (item in scene.pointItemList) {
+                        scene.removeItem(item)
+                    }
+                    scene.pointItemList.clear()
+                    for (item in scene.qrcodeItemList) {
+                        scene.removeItem(item)
+                    }
+                    scene.qrcodeItemList.clear()
+                }
+
+                //打点业务
                 if ("dot".equals(scene.type)) {
                     scene.type = "normal"
                     addDot.alpha = 1f
+                    graphyVM.addProblem(scene.choseSpace, x, y)
                     return
                 }
 
+                //查看模式下,判断问题点选中逻辑
                 if ("normal".equals(scene.type)) {
                     realDistance = distance * scene.defaultPointScale / graphyView.scale
                     for (point in scene.pointItemList) {
@@ -158,33 +172,220 @@ class GraphyActivity : BaseActivity() {
                             ) + Math.pow(Math.abs(y - point.data.mY).toDouble(), 2.0)
                         ).toInt()
                         if (sqrt < realDistance) {
-                            Toast.makeText(this@GraphyActivity, "x=" + x, Toast.LENGTH_LONG).show()
                             showDotDetail(point)
                             break
                         }
                     }
                     return
                 }
+
+                //绑定二位码业务
+                if ("qrcode".equals(scene.type)) {
+                    qrcodeLl.visibility = View.VISIBLE
+                    qrcodeLocation.setText("(${scene.point.mX},${scene.point.mY})")
+                    spaceStructure.visibility = View.GONE
+
+                }
             }
         })
-        initViewModel()
+    }
 
+    /**
+     * 页面全部监听事件
+     */
+    private fun initListener() {
+        //nfc点击监听
+        nfc.setOnClickListener { Toast.makeText(this, "正在开发中,敬请期待", Toast.LENGTH_SHORT).show() }
 
-        return
-    } // Function onCreate()
+        //checkBox
+        modelCheckBox.setOnCheckedChangeListener { buttonView, isChecked ->
+            if (isChecked) {
+                modelSubmit.isEnabled = true
+                modelSubmit.alpha = 1f
+            } else {
+                modelSubmit.isEnabled = false
+                modelSubmit.alpha = 0.3f
+            }
+        }
+
+        //设置空间的任务状态完成
+        modelSubmit.setOnClickListener {
+            graphyVM.setJob(scene.choseSpace, codeEdit.text.toString())
+        }
+
+        //打点按钮
+        addDot.setOnClickListener {
+            scene.type = "dot"
+            addDot.alpha = 0.3f
+        }
+
+        //绑定二维码按钮
+        qrcode.setOnClickListener {
+            scene.type = "qrcode"
+            qrcodeLl.visibility = View.VISIBLE
+            spaceStructure.visibility = View.GONE
+        }
+
+        //取消绑定二维码
+        qrcodeCancel.setOnClickListener {
+            qrcodeLl.visibility = View.GONE
+            spaceStructure.visibility = View.VISIBLE
+            scene.type = "normal"
+            scene.item?.let { it1 -> scene.removeItem(it1) }
+        }
+
+        //下一步
+        qrcodeNext.setOnClickListener {
+            val intent = Intent(this@GraphyActivity, CaptureActivity::class.java)
+            startActivityForResult(intent, REQUEST_CODE_SCAN)
+        }
+    }
 
+    /**
+     * 初始化viewModel
+     */
     private fun initViewModel() {
-        var graphyVM = GraphyVM({ name, params ->
+        graphyVM = GraphyVM({ name, params ->
             when (name) {
+
+                /** 查询空间和任务 */
                 GraphyVM.SPACE_JOB -> {
+                    for (item in scene.tunableSpaceList) {
+                        scene.removeItem(item)
+                    }
+                    scene.tunableSpaceList.clear()
+
                     val list = params as (List<SpaceJobModel>)
+                    for (model in list) {
+                        if (!model.outline.isEmpty()) {
+                            val space = Space()
+                            space.outLine = model.outline.get(0)
+                            space.name = model.name
+                            val nameItem = SpaceNameItem(space)
+                            nameItem.zOrder = 99999f
+                            nameItem.isVisible = scene.isShowSpace
+                            scene.spaceNameList.add(nameItem)
+                            scene.addItem(nameItem)
+
+                            val tunableSpace = TunableSpace()
+                            tunableSpace.outLine = model.outline.get(0)
+                            tunableSpace.name = model.name
+                            tunableSpace.jobStatus = model.job
+                            tunableSpace.id = model.id
+                            tunableSpace.localName = model.localName
+                            val item = TunableSpaceItem(tunableSpace, null)
+                            item.isVisible = true
+                            item.zOrder = 99996f
+                            scene.tunableSpaceList.add(item)
+                            scene.addItem(item)
+                        }
+                    }
+                }
+                /** 添加空间核查问题 */
+                GraphyVM.ADD_PROBLEM -> {
+                    Toast.makeText(this, "记录成功", Toast.LENGTH_SHORT).show()
+                    graphyVM.getProblem(scene.choseSpace)
+                    graphyVM.getSpaceJob()
+                }
+
+                /** 查询空间核查问题 */
+                GraphyVM.GET_PROBLEM -> {
+                    for (item in scene.pointItemList) {
+                        scene.removeItem(item)
+                    }
+                    scene.pointItemList.clear()
+                    var list = params as ArrayList<ProblemsModel>
+                    for (model in list) {
+                        val point = Point()
+                        var position = gson.fromJson(model.position, Position::class.java)
+                        point.mX = position.x.toFloat()
+                        point.mY = position.y.toFloat()
+                        point.id = model.id
+                        var item = PointItem(point, null, scene.defaultPointScale)
+                        item.isVisible = true
+                        item.zOrder = 100000f
+                        scene.pointItemList.add(item)
+                        scene.addItem(item)
+                    }
+                }
+
+                /** 关闭空间核查问题 */
+                GraphyVM.CLOSE_PROBLEM -> {
+                    graphyVM.getProblem(scene.choseSpace)
+                }
+
+                /** 绑定二维码 */
+                GraphyVM.BIND_QECODE -> {
+                    Toast.makeText(this, "绑定成功", Toast.LENGTH_SHORT).show()
+                    scene.type = "normal"
+                    qrcodeLl.visibility = View.GONE
+                    spaceStructure.visibility = View.VISIBLE
+                    scene.removeItem(scene.item!!)
+                    scene.qrcodeItemList.clear()
+                    graphyVM.getQrcode(scene.choseSpace)
+                }
+
+                /** 查询对象绑定的二维码 */
+                GraphyVM.GET_QECODE -> {
+                    val models = params as ArrayList<QrcodeModel>
+                    for (model in models) {
+                        val point = Point()
+                        var position = gson.fromJson(model.position, Position::class.java)
+                        point.mX = position.x.toFloat()
+                        point.mY = position.y.toFloat()
+
+                        var item = QrcodeItem(point, null, scene.defaultPointScale)
+                        item.isVisible = true
+                        item.zOrder = 100000f
+                        scene.qrcodeItemList.add(item)
+                        scene.addItem(item)
+                    }
+                }
+
+                /** 设置空间的任务状态(新建和修改) */
+                GraphyVM.SET_JOB -> {
+                    Toast.makeText(this, "核查成功", Toast.LENGTH_SHORT).show()
+                    refreshAll()
+                    graphyVM.getSpaceJob()
+                }
 
+                /** 设置空间核查问题的信息和状态 */
+                GraphyVM.SET_PROBLEM -> {
+                    graphyVM.getSpaceJob()
                 }
             }
         }, this)
         graphyVM.getSpaceJob()
     }
 
+    /**
+     * 重置空间界面
+     */
+    private fun refreshAll() {
+        for (item in scene.pointItemList) {
+            scene.removeItem(item)
+        }
+        scene.pointItemList.clear()
+
+        for (item in scene.tunableSpaceList) {
+            scene.removeItem(item)
+        }
+        scene.tunableSpaceList.clear()
+
+        for (item in scene.qrcodeItemList) {
+            scene.removeItem(item)
+        }
+        scene.qrcodeItemList.clear()
+
+        spaceStructure.visibility = View.GONE
+        scene.type = "normal"
+        modelCheckBox.isChecked = false
+        codeEdit.setText("")
+    }
+
+    /**
+     * 显示点位信息框
+     */
     private fun showDotDetail(point: PointItem) {
         spaceStructure.visibility = View.GONE
         quesDetail.visibility = View.VISIBLE
@@ -194,14 +395,25 @@ class GraphyActivity : BaseActivity() {
                     "\ny轴:${point.data.mY}" +
                     "\n点击下方“问题已解决”按钮后可关闭该问题点。"
         )
+        //问题已解决按钮
         quesSubmit.setOnClickListener {
+            graphyVM.closeProblem(point, scene.choseSpace)
             spaceStructure.visibility = View.VISIBLE
             quesDetail.visibility = View.GONE
-            scene.removeItem(point)
             scene.pointItemList.remove(point)
+            scene.removeItem(point)
+            if (scene.pointItemList.isEmpty()) {
+                for (item in scene.tunableSpaceList) {
+                    scene.removeItem(item)
+                }
+            }
+            graphyVM.getSpaceJob()
         }
     }
 
+    /**
+     * 扫码返回uuid
+     */
     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
         super.onActivityResult(requestCode, resultCode, data)
         when (requestCode) {
@@ -212,6 +424,12 @@ class GraphyActivity : BaseActivity() {
                         val bundle = data.extras
                         val result = bundle.getString(CaptureActivity.EXTRA_STRING)
                         Log.e("tag", "扫描结果:$result")
+                        graphyVM.bindQrcode(
+                            scene.choseSpace,
+                            result,
+                            scene.point,
+                            qrcodeEdit.text.toString()
+                        )
                     }
                 }
             else -> {

+ 15 - 0
demo/src/main/java/com/sybotan/android/demo/bean/request/ReqAddProblem.java

@@ -0,0 +1,15 @@
+package com.sybotan.android.demo.bean.request;
+
+
+import com.sybotan.android.demo.bean.result.Position;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/9
+ */
+public class ReqAddProblem {
+    public String spaceId;
+    public String floorId;
+    public Position position;
+    public String target = "action";
+}

+ 16 - 0
demo/src/main/java/com/sybotan/android/demo/bean/request/ReqBindQrcode.java

@@ -0,0 +1,16 @@
+package com.sybotan.android.demo.bean.request;
+
+import com.sybotan.android.demo.bean.result.Position;
+
+/**
+ * 绑定二维码
+ * Created by lihao.
+ * Date: 2021/6/10
+ */
+public class ReqBindQrcode {
+    public String objId;
+    public String objType;
+    public String uuid;
+    public Position position;
+    public String target = "action";
+}

+ 10 - 0
demo/src/main/java/com/sybotan/android/demo/bean/request/ReqCloseProblem.java

@@ -0,0 +1,10 @@
+package com.sybotan.android.demo.bean.request;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/10
+ */
+public class ReqCloseProblem {
+    public String problemId;
+    public String spaceId;
+}

+ 11 - 0
demo/src/main/java/com/sybotan/android/demo/bean/request/ReqProblems.java

@@ -0,0 +1,11 @@
+package com.sybotan.android.demo.bean.request;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/9
+ */
+public class ReqProblems {
+    public String floorId;
+    public String spaceId;
+    public String target = "rtn";
+}

+ 9 - 0
demo/src/main/java/com/sybotan/android/demo/bean/request/ReqQrcode.java

@@ -0,0 +1,9 @@
+package com.sybotan.android.demo.bean.request;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/10
+ */
+public class ReqQrcode {
+    public String objId;
+}

+ 17 - 0
demo/src/main/java/com/sybotan/android/demo/bean/request/ReqSetJob.java

@@ -0,0 +1,17 @@
+package com.sybotan.android.demo.bean.request;
+
+import java.util.ArrayList;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/10
+ */
+public class ReqSetJob {
+    public ArrayList<String> spaceId = new ArrayList<>();
+    public String buildingId;
+    public String floorId;
+    public String jobStatus;
+    public String spaceCode;
+    public String target = "action";
+
+}

+ 15 - 0
demo/src/main/java/com/sybotan/android/demo/bean/request/ReqSetProblem.java

@@ -0,0 +1,15 @@
+package com.sybotan.android.demo.bean.request;
+
+import com.sybotan.android.demo.bean.result.Position;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/9
+ */
+public class ReqSetProblem {
+    public String problemId;
+    public Position position;
+    public boolean state;
+    public String target = "action";
+
+}

+ 11 - 0
demo/src/main/java/com/sybotan/android/demo/bean/result/AddProblemModel.java

@@ -0,0 +1,11 @@
+package com.sybotan.android.demo.bean.result;
+
+import java.io.Serializable;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/9
+ */
+public class AddProblemModel implements Serializable {
+
+}

+ 8 - 0
demo/src/main/java/com/sybotan/android/demo/bean/result/BindQrcodeModel.java

@@ -0,0 +1,8 @@
+package com.sybotan.android.demo.bean.result;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/10
+ */
+public class BindQrcodeModel {
+}

+ 8 - 0
demo/src/main/java/com/sybotan/android/demo/bean/result/CloseProblemModel.java

@@ -0,0 +1,8 @@
+package com.sybotan.android.demo.bean.result;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/10
+ */
+public class CloseProblemModel {
+}

+ 13 - 0
demo/src/main/java/com/sybotan/android/demo/bean/result/Position.java

@@ -0,0 +1,13 @@
+package com.sybotan.android.demo.bean.result;
+
+import java.io.Serializable;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/9
+ */
+public class Position implements Serializable {
+    public String x;
+    public String y;
+    public Z z;
+}

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

@@ -0,0 +1,13 @@
+package com.sybotan.android.demo.bean.result;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/9
+ */
+public class ProblemsModel {
+    public String id;
+    public String spaceId;
+    public String content;
+    public String floorId;
+    public String position;
+}

+ 12 - 0
demo/src/main/java/com/sybotan/android/demo/bean/result/QrcodeModel.java

@@ -0,0 +1,12 @@
+package com.sybotan.android.demo.bean.result;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/10
+ */
+public class QrcodeModel {
+    public String obj_id;
+    public String obj_type;
+    public String qr_code;
+    public String position;
+}

+ 8 - 0
demo/src/main/java/com/sybotan/android/demo/bean/result/SetJobModel.java

@@ -0,0 +1,8 @@
+package com.sybotan.android.demo.bean.result;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/10
+ */
+public class SetJobModel {
+}

+ 10 - 0
demo/src/main/java/com/sybotan/android/demo/bean/result/SetProblemModel.java

@@ -0,0 +1,10 @@
+package com.sybotan.android.demo.bean.result;
+
+import java.io.Serializable;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/9
+ */
+public class SetProblemModel implements Serializable {
+}

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

@@ -2,6 +2,10 @@ package com.sybotan.android.demo.bean.result;
 
 import com.sybotan.android.demo.bean.BaseModel;
 
+import java.util.ArrayList;
+
+import cn.sagacloud.android.cadengine.types.PointZ;
+
 /**
  * Created by lihao.
  * Date: 2021/6/9
@@ -18,6 +22,7 @@ public class SpaceJobModel extends BaseModel {
     public String name;
     public String projectId;
     public String state;
-//    public String statistics;
+    //    public String statistics;
     public String job;
+    public ArrayList<ArrayList<ArrayList<PointZ>>> outline = new ArrayList<>();
 }

+ 12 - 0
demo/src/main/java/com/sybotan/android/demo/bean/result/Z.java

@@ -0,0 +1,12 @@
+package com.sybotan.android.demo.bean.result;
+
+import java.io.Serializable;
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/9
+ */
+public class Z implements Serializable {
+    public String region;
+    public String offset;
+}

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

@@ -2,9 +2,17 @@ package com.sybotan.android.demo.retrofit;
 
 
 import com.sybotan.android.demo.bean.BaseModel;
+import com.sybotan.android.demo.bean.result.AddProblemModel;
+import com.sybotan.android.demo.bean.result.BindQrcodeModel;
+import com.sybotan.android.demo.bean.result.CloseProblemModel;
+import com.sybotan.android.demo.bean.result.ProblemsModel;
+import com.sybotan.android.demo.bean.result.QrcodeModel;
+import com.sybotan.android.demo.bean.result.SetJobModel;
+import com.sybotan.android.demo.bean.result.SetProblemModel;
 import com.sybotan.android.demo.entitiies.DeviceType;
 import com.sybotan.android.demo.bean.result.SpaceJobModel;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import io.reactivex.Observable;
@@ -91,6 +99,48 @@ public interface API {
     Observable<BaseModel<List<SpaceJobModel>>> getSpaceJob(@Body RequestBody body);
 
     /**
+     * 查询空间核查问题
+     */
+    @POST("clmt/query/problems")
+    Observable<BaseModel<List<ProblemsModel>>> problems(@Body RequestBody body);
+
+    /**
+     * 添加空间核查问题
+     */
+    @POST("clmt/job/add_problem")
+    Observable<BaseModel<AddProblemModel>> addProblem(@Body RequestBody body);
+
+    /**
+     * 设置空间核查问题的信息和状态
+     */
+    @POST("clmt/job/set_problem")
+    Observable<BaseModel<SetProblemModel>> setProblem(@Body RequestBody body);
+
+    /**
+     * 关闭空间核查问题
+     */
+    @POST("clmt/job/close_problem")
+    Observable<BaseModel<CloseProblemModel>> closeProblem(@Body RequestBody body);
+
+    /**
+     * 绑定二维码
+     */
+    @POST("clmt/job/bind_qrcode")
+    Observable<BaseModel<BindQrcodeModel>> bindQrcode(@Body RequestBody body);
+
+    /**
+     * 查询对象绑定的二维码
+     */
+    @POST("clmt/query/qrcode")
+    Observable<BaseModel<ArrayList<QrcodeModel>>> qrcode(@Body RequestBody body);
+
+    /**
+     * 设置空间的任务状态(新建和修改)
+     */
+    @POST("clmt/job/set_job")
+    Observable<BaseModel<SetJobModel>> setJob(@Body RequestBody body);
+
+    /**
      * 查询设备类型
      */
     @POST("clmt/dict/sys_eq_list")

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

@@ -20,7 +20,7 @@ public class RetrofitFactory {
     private static final long TIMEOUT = 30;
     private static final long TIMEOUT2 = 10;
     public static OkHttpClient httpClient = new OkHttpClient.Builder()
-//            .addInterceptor(new RetrofitLogInterceptor())
+            .addInterceptor(new RetrofitLogInterceptor())
             .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
             .writeTimeout(TIMEOUT, TimeUnit.SECONDS)
             .readTimeout(TIMEOUT, TimeUnit.SECONDS)

+ 170 - 2
demo/src/main/java/com/sybotan/android/demo/viewmodel/GraphyVM.java

@@ -1,17 +1,38 @@
 package com.sybotan.android.demo.viewmodel;
 
-import android.util.Log;
-
 import com.sybotan.android.demo.activities.BaseActivity;
 import com.sybotan.android.demo.bean.BaseModel;
+import com.sybotan.android.demo.bean.request.ReqAddProblem;
+import com.sybotan.android.demo.bean.request.ReqBindQrcode;
+import com.sybotan.android.demo.bean.request.ReqCloseProblem;
+import com.sybotan.android.demo.bean.request.ReqProblems;
+import com.sybotan.android.demo.bean.request.ReqQrcode;
+import com.sybotan.android.demo.bean.request.ReqSetJob;
+import com.sybotan.android.demo.bean.request.ReqSetProblem;
 import com.sybotan.android.demo.bean.request.ReqSpaceJob;
+import com.sybotan.android.demo.bean.result.AddProblemModel;
+import com.sybotan.android.demo.bean.result.BindQrcodeModel;
+import com.sybotan.android.demo.bean.result.CloseProblemModel;
+import com.sybotan.android.demo.bean.result.Position;
+import com.sybotan.android.demo.bean.result.ProblemsModel;
+import com.sybotan.android.demo.bean.result.QrcodeModel;
+import com.sybotan.android.demo.bean.result.SetJobModel;
+import com.sybotan.android.demo.bean.result.SetProblemModel;
 import com.sybotan.android.demo.bean.result.SpaceJobModel;
+import com.sybotan.android.demo.bean.result.Z;
 import com.sybotan.android.demo.retrofit.BaseObserver;
 import com.sybotan.android.demo.retrofit.BaseViewModelInterface;
 import com.sybotan.android.demo.retrofit.RetrofitFactory;
 
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
 import java.util.List;
 
+import cn.sagacloud.android.cadengine.items.PointItem;
+import cn.sagacloud.android.cadengine.items.TunableSpaceItem;
+import cn.sagacloud.android.cadengine.types.Point;
 import io.reactivex.Observable;
 
 /**
@@ -19,12 +40,30 @@ import io.reactivex.Observable;
  * Date: 2021/6/9
  */
 public class GraphyVM extends BaseViewModel {
+    //查询空间和任务
     public static final String SPACE_JOB = "SPACE_JOB";
+    //添加空间核查问题
+    public static final String ADD_PROBLEM = "ADD_PROBLEM";
+    //查询空间核查问题
+    public static final String GET_PROBLEM = "GET_PROBLEM";
+    //设置空间核查问题的信息和状态
+    public static final String SET_PROBLEM = "SET_PROBLEM";
+    //关闭空间核查问题
+    public static final String CLOSE_PROBLEM = "CLOSE_PROBLEM";
+    //绑定二维码
+    public static final String BIND_QECODE = "BIND_QECODE";
+    //查询对象绑定的二维码
+    public static final String GET_QECODE = "GET_QECODE";
+    //设置空间的任务状态(新建和修改)
+    public static final String SET_JOB = "SET_JOB";
 
     public GraphyVM(BaseViewModelInterface object, BaseActivity activity) {
         super(object, activity);
     }
 
+    /**
+     * 查询空间和任务
+     */
     public void getSpaceJob() {
         ReqSpaceJob bean = new ReqSpaceJob();
         bean.buildingId = "Bd00022200113a69205aebc34aba87b31a2a03a572ab";
@@ -39,4 +78,133 @@ public class GraphyVM extends BaseViewModel {
             }
         }, true);
     }
+
+    /**
+     * 添加空间核查问题
+     *
+     * @param choseSpace 选中的空间
+     * @param x          x坐标
+     * @param y          y坐标
+     */
+    public void addProblem(TunableSpaceItem choseSpace, float x, float y) {
+        ReqAddProblem bean = new ReqAddProblem();
+        bean.spaceId = choseSpace.getData().getId();
+        bean.floorId = "Fl00022200115d43d88abaab46cda43f1596b5e3930b";
+        Position position = new Position();
+        position.x = x + "";
+        position.y = y + "";
+        bean.position = position;
+        Observable<BaseModel<AddProblemModel>> observable = RetrofitFactory.getInstance().addProblem(getRequestBody(bean));
+        sendRequest(observable, new BaseObserver<AddProblemModel>(mActivity, this) {
+            @Override
+            protected void onSuccess(AddProblemModel model) {
+                mEmitter.SendDircetive(ADD_PROBLEM, model);
+            }
+        }, true);
+    }
+
+    /**
+     * 查询空间核查问题
+     *
+     * @param choseSpace 选中的空间
+     */
+    public void getProblem(@Nullable TunableSpaceItem choseSpace) {
+        ReqProblems bean = new ReqProblems();
+        bean.floorId = "Fl00022200115d43d88abaab46cda43f1596b5e3930b";
+        bean.spaceId = choseSpace.getData().getId();
+        Observable<BaseModel<List<ProblemsModel>>> observable = RetrofitFactory.getInstance().problems(getRequestBody(bean));
+        sendRequest(observable, new BaseObserver<List<ProblemsModel>>(mActivity, this) {
+            @Override
+            protected void onSuccess(List<ProblemsModel> models) {
+                mEmitter.SendDircetive(GET_PROBLEM, models);
+            }
+        }, true);
+    }
+
+    /**
+     * 关闭空间核查问题
+     *
+     * @param point      点位
+     * @param choseSpace 选中的空间
+     */
+    public void closeProblem(@NotNull PointItem point, @Nullable TunableSpaceItem choseSpace) {
+        ReqCloseProblem bean = new ReqCloseProblem();
+        bean.problemId = point.getData().getId();
+        bean.spaceId = choseSpace.getData().getId();
+        Observable<BaseModel<CloseProblemModel>> observable = RetrofitFactory.getInstance().closeProblem(getRequestBody(bean));
+        sendRequest(observable, new BaseObserver<CloseProblemModel>(mActivity, this) {
+            @Override
+            protected void onSuccess(CloseProblemModel setProblemModel) {
+                mEmitter.SendDircetive(CLOSE_PROBLEM, null);
+            }
+        }, true);
+    }
+
+
+    /**
+     * 绑定二维码
+     *
+     * @param choseSpace 选中的空间
+     * @param result     二维码uuid
+     * @param point      点位信息
+     * @param toString   z轴描述
+     */
+    public void bindQrcode(@Nullable TunableSpaceItem choseSpace, @Nullable String result, @NotNull Point point, @NotNull String toString) {
+        ReqBindQrcode bean = new ReqBindQrcode();
+        bean.objId = choseSpace.getData().getId();
+        bean.objType = "space";
+        bean.uuid = result;
+        Position position = new Position();
+        position.x = String.valueOf(point.getMX());
+        position.y = String.valueOf(point.getMY());
+        position.z = new Z();
+        position.z.offset = toString;
+        position.z.region = "wall";
+        bean.position = position;
+        Observable<BaseModel<BindQrcodeModel>> observable = RetrofitFactory.getInstance().bindQrcode(getRequestBody(bean));
+        sendRequest(observable, new BaseObserver<BindQrcodeModel>(mActivity, this) {
+            @Override
+            protected void onSuccess(BindQrcodeModel bindQrcodeModel) {
+                mEmitter.SendDircetive(BIND_QECODE, null);
+            }
+        }, true);
+    }
+
+    /**
+     * 查询对象绑定的二维码
+     *
+     * @param choseSpace 选中的空间
+     */
+    public void getQrcode(@Nullable TunableSpaceItem choseSpace) {
+        ReqQrcode bean = new ReqQrcode();
+        bean.objId = choseSpace.getData().getId();
+        Observable<BaseModel<ArrayList<QrcodeModel>>> observable = RetrofitFactory.getInstance().qrcode(getRequestBody(bean));
+        sendRequest(observable, new BaseObserver<ArrayList<QrcodeModel>>(mActivity, this) {
+            @Override
+            protected void onSuccess(ArrayList<QrcodeModel> qrcodeModels) {
+                mEmitter.SendDircetive(GET_QECODE, qrcodeModels);
+            }
+        }, true);
+    }
+
+    /**
+     * 设置空间的任务状态(新建和修改)
+     * @param choseSpace 选中的空间
+     * @param toString 数字化交付编码
+     */
+    public void setJob(@Nullable TunableSpaceItem choseSpace, @NotNull String toString) {
+        ReqSetJob bean = new ReqSetJob();
+        bean.buildingId = "Bd00022200113a69205aebc34aba87b31a2a03a572ab";
+        bean.floorId = "Fl00022200115d43d88abaab46cda43f1596b5e3930b";
+        bean.spaceId.add(choseSpace.getData().getId());
+        bean.jobStatus = "03";
+        bean.spaceCode = toString;
+        Observable<BaseModel<SetJobModel>> observable = RetrofitFactory.getInstance().setJob(getRequestBody(bean));
+        sendRequest(observable, new BaseObserver<SetJobModel>(mActivity, this) {
+            @Override
+            protected void onSuccess(SetJobModel model) {
+                mEmitter.SendDircetive(SET_JOB, null);
+            }
+        }, true);
+    }
 }

+ 10 - 0
demo/src/main/res/drawable/bg_grey_e6e6e6.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners
+        android:radius="50dp"/>
+    <solid
+        android:color="#e6e6e6"/>
+
+</shape>

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

@@ -45,7 +45,20 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="5dp"
             android:layout_marginBottom="20dp"
-            android:orientation="vertical">
+            android:orientation="vertical"
+            android:visibility="gone">
+
+            <TextView
+                android:id="@+id/spaceName"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:layout_marginBottom="5dp"
+                android:paddingLeft="90dp"
+                android:paddingTop="5dp"
+                android:paddingRight="90dp"
+                android:textColor="@color/grey_900"
+                android:textSize="12sp" />
 
             <TextView
                 android:id="@+id/addDot"
@@ -106,6 +119,19 @@
                 android:layout_marginTop="22dp"
                 android:text="此空间核查完毕,模型和现场无区别" />
 
+            <EditText
+                android:id="@+id/codeEdit"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:layout_marginLeft="65dp"
+                android:layout_marginTop="12dp"
+                android:layout_marginRight="65dp"
+                android:hint="输入数字化交付编码"
+                android:inputType="numberDecimal"
+                android:textColorHint="@color/grey_500"
+                android:textSize="16sp" />
+
             <TextView
                 android:id="@+id/modelSubmit"
                 android:layout_width="wrap_content"
@@ -171,5 +197,88 @@
                 android:textColor="@color/white"
                 android:textSize="15sp" />
         </RelativeLayout>
+
+        <LinearLayout
+            android:id="@+id/qrcodeLl"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="@color/white"
+            android:orientation="vertical"
+            android:paddingTop="20dp"
+            android:paddingBottom="20dp"
+            android:visibility="gone">
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:text="请在平面图上放置二维码或NFC标签位置"
+                android:textColor="@color/grey_900"
+                android:textSize="16sp" />
+
+            <TextView
+                android:id="@+id/qrcodeLocation"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:layout_marginTop="12dp"
+                android:text="(0,0)"
+                android:textColor="@color/grey_900"
+                android:textSize="16sp" />
+
+            <EditText
+                android:id="@+id/qrcodeEdit"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:layout_marginLeft="50dp"
+                android:layout_marginTop="12dp"
+                android:layout_marginRight="50dp"
+                android:hint="距离地面高度,米"
+                android:inputType="numberDecimal"
+                android:textColorHint="@color/grey_500"
+                android:textSize="16sp" />
+
+            <TextView
+                android:id="@+id/qrcodeNext"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@+id/quesTv"
+                android:layout_centerHorizontal="true"
+                android:layout_gravity="center_horizontal"
+                android:layout_marginLeft="50dp"
+                android:layout_marginTop="12dp"
+                android:layout_marginRight="50dp"
+                android:background="@drawable/bg_blue_3bacb2"
+                android:gravity="center"
+                android:paddingLeft="15dp"
+                android:paddingTop="10dp"
+                android:paddingRight="15dp"
+                android:paddingBottom="10dp"
+                android:text="下一步"
+                android:textColor="@color/white"
+                android:textSize="15sp" />
+
+            <TextView
+                android:id="@+id/qrcodeCancel"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@+id/quesTv"
+                android:layout_centerHorizontal="true"
+                android:layout_gravity="center_horizontal"
+                android:layout_marginLeft="50dp"
+                android:layout_marginTop="12dp"
+                android:layout_marginRight="50dp"
+                android:background="@drawable/bg_grey_e6e6e6"
+                android:gravity="center"
+                android:paddingLeft="15dp"
+                android:paddingTop="10dp"
+                android:paddingRight="15dp"
+                android:paddingBottom="10dp"
+                android:text="取消"
+                android:textColor="@color/grey_900"
+                android:textSize="15sp" />
+
+        </LinearLayout>
     </RelativeLayout>
 </LinearLayout>