Browse Source

@fun 3D土建精装

lihao1 2 years ago
parent
commit
8d49aa7c71
92 changed files with 6535 additions and 153 deletions
  1. 18 0
      app/build.gradle.kts
  2. 43 7
      app/src/main/AndroidManifest.xml
  3. BIN
      app/src/main/assets/dist/Images/AddPointIcon.png
  4. BIN
      app/src/main/assets/dist/Images/Type_0.png
  5. BIN
      app/src/main/assets/dist/Images/Type_1.png
  6. BIN
      app/src/main/assets/dist/Images/Type_2.png
  7. 748 0
      app/src/main/assets/dist/JsonConfig/PorjectConfig copy.json
  8. 749 0
      app/src/main/assets/dist/JsonConfig/PorjectConfig.json
  9. 1 0
      app/src/main/assets/dist/css/app.9e7e8a89.css
  10. 1 0
      app/src/main/assets/dist/css/chunk-vendors.a16c4353.css
  11. BIN
      app/src/main/assets/dist/favicon.ico
  12. BIN
      app/src/main/assets/dist/fonts/element-icons.535877f5.woff
  13. BIN
      app/src/main/assets/dist/fonts/element-icons.732389de.ttf
  14. 18 0
      app/src/main/assets/dist/index.html
  15. 2 0
      app/src/main/assets/dist/js/app.90127e5f.js
  16. 1 0
      app/src/main/assets/dist/js/app.90127e5f.js.map
  17. 74 0
      app/src/main/assets/dist/js/chunk-vendors.47a002f1.js
  18. 1 0
      app/src/main/assets/dist/js/chunk-vendors.47a002f1.js.map
  19. 4 0
      app/src/main/java/com/ys/bdtp/adm/di/Di.kt
  20. 6 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/db/dao/config/ProblemInfoConfigDao.kt
  21. 6 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/db/dao/config/ProblemTypeConfigDao.kt
  22. 4 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/db/dao/task/BuildingDao.kt
  23. 3 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/db/dao/task/FloorDao.kt
  24. 6 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/db/dao/task/ProblemDao.kt
  25. 2 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/InfosforFloor.kt
  26. 15 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/LineArray.java
  27. 7 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/LineObject.java
  28. 1 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/MeshObjectModel.kt
  29. 3 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/Options.kt
  30. 22 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/Photos.java
  31. 5 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/PointModel.java
  32. 9 15
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/PointZ.java
  33. 12 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/PositionInfo.java
  34. 1 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/SetFloorPathModel.kt
  35. 12 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/StyleObject.java
  36. 20 1
      app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/TipArray.java
  37. 348 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/BaseRecyclerViewAdapter.java
  38. 16 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/BaseViewHolder.java
  39. 17 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/BaseViewModelInterface.java
  40. 83 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/BuildingFloorExpandAdapter.kt
  41. 112 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/ImageListRVAdapter.java
  42. 284 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/InfoAdapter.java
  43. 96 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/LocalDataOperation.java
  44. 151 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/LookBigPicActivity.java
  45. 94 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/MyDialogViewSingle.java
  46. 63 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/MyGlideModules.java
  47. 9 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/MyProvider.java
  48. 72 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/OfflineSendRequest.java
  49. 119 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/PersonalSelectSingleAdapter.java
  50. 156 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/PictureAdapter.java
  51. 115 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/PictureUtils.java
  52. 292 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/Repair_ImgSelActivity.java
  53. 460 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/Repair_ImgSelFragment.java
  54. 393 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/SDCardHelper.java
  55. 226 0
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/SelectListSinglePopupWindow.java
  56. 380 109
      app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/Space3DActivity.kt
  57. 52 1
      app/src/main/java/com/ys/bdtp/adm/mvvm/vm/examine/Space3DRepository.kt
  58. 214 1
      app/src/main/java/com/ys/bdtp/adm/mvvm/vm/examine/Space3DViewModel.kt
  59. BIN
      app/src/main/res/drawable-xxhdpi/add_pic.png
  60. BIN
      app/src/main/res/drawable-xxhdpi/choseicon_gray.png
  61. BIN
      app/src/main/res/drawable-xxhdpi/icon_lock.png
  62. BIN
      app/src/main/res/drawable-xxhdpi/icon_lock_blue.png
  63. BIN
      app/src/main/res/drawable-xxhdpi/icon_takephoto.png
  64. BIN
      app/src/main/res/drawable-xxhdpi/image_error_icon.png
  65. BIN
      app/src/main/res/drawable-xxhdpi/image_loading_icon.png
  66. 8 0
      app/src/main/res/drawable/bg_edt_gray_eff0f1.xml
  67. 6 0
      app/src/main/res/drawable/bg_gray_f2f3f6.xml
  68. BIN
      app/src/main/res/drawable/checkbox_selected.png
  69. 7 0
      app/src/main/res/drawable/checkbox_style.xml
  70. BIN
      app/src/main/res/drawable/checkbox_unselected.png
  71. 16 0
      app/src/main/res/drawable/corners_line_black.xml
  72. 12 0
      app/src/main/res/drawable/shape_rectangle_green_3.xml
  73. 19 0
      app/src/main/res/layout/activity_look_big_pic.xml
  74. 74 0
      app/src/main/res/layout/activity_newcreate_dialog.xml
  75. 111 19
      app/src/main/res/layout/activity_space3d_activity.xml
  76. 34 0
      app/src/main/res/layout/child_expand_space.xml
  77. 68 0
      app/src/main/res/layout/common_fragment_img_sel.xml
  78. 28 0
      app/src/main/res/layout/common_item_img_sel.xml
  79. 83 0
      app/src/main/res/layout/dialog_list_choice.xml
  80. 6 0
      app/src/main/res/layout/empty.xml
  81. 20 0
      app/src/main/res/layout/group_expand_space.xml
  82. 23 0
      app/src/main/res/layout/item_img_sel_take_photo.xml
  83. 33 0
      app/src/main/res/layout/item_node_nine_pic.xml
  84. 31 0
      app/src/main/res/layout/personal_select_text_single_item.xml
  85. 52 0
      app/src/main/res/layout/view_enum.xml
  86. 24 0
      app/src/main/res/layout/view_photo.xml
  87. 225 0
      app/src/main/res/layout/view_position.xml
  88. 77 0
      app/src/main/res/layout/view_text.xml
  89. 2 0
      app/src/main/res/values/colors.xml
  90. 5 0
      app/src/main/res/xml/file_paths.xml
  91. 21 0
      buildSrc/src/main/kotlin/Build.kt
  92. 4 0
      settings.gradle.kts

+ 18 - 0
app/build.gradle.kts

@@ -136,4 +136,22 @@ dependencies {
     androidTestImplementation(Deps.AndroidXTest.Ktx)
     androidTestImplementation(Deps.AndroidXTest.Ext)
     debugImplementation(Deps.Compose.Debug.Tooling)
+
+    //glide
+    implementation(Deps.Glide.Glide)
+    implementation(Deps.Glide.Rxjava)
+    implementation(Deps.Glide.Rxandroid)
+    implementation(Deps.Glide.Components)
+//    implementation(Deps.Glide.Compiler)
+//    implementation(Deps.Glide.annotations)
+//    implementation(Deps.Glide.Okhttp3)
+//    implementation(Deps.Glide.Logging)
+
+    //db
+    implementation(Deps.Tools.DebugDB)
+    implementation(Deps.Tools.hutool)
+//    implementation(Deps.Tools.Autosize)
+
+    //Imgsel
+    implementation(Deps.Imgsel.Imgsel)
 }

+ 43 - 7
app/src/main/AndroidManifest.xml

@@ -1,9 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:tools="http://schemas.android.com/tools"
           package="com.ys.bdtp.adm">
 
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.CAMERA"/>
+    <uses-permission
+            android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
+            tools:ignore="ProtectedPermissions"/> <!-- 向SDCard写入数据权限 -->
+
     <application
             android:allowBackup="true"
             android:icon="@mipmap/ic_launcher"
@@ -13,29 +21,57 @@
             android:usesCleartextTraffic="true"
             android:supportsRtl="true"
             android:largeHeap="true"
-            android:hardwareAccelerated="false"
             android:theme="@style/Theme.Adm">
+        <meta-data
+                android:name="design_width_in_dp"
+                android:value="2580"/>
+        <meta-data
+                android:name="design_height_in_dp"
+                android:value="1600"/>
+
+        <provider
+                android:name=".mvvm.ui.examine.MyProvider"
+                android:authorities="com.ys.bdtp.adm.fileProvider"
+                android:exported="false"
+                android:grantUriPermissions="true">
+            <meta-data
+                    android:name="android.support.FILE_PROVIDER_PATHS"
+                    android:resource="@xml/file_paths"/>
+        </provider>
+
         <activity
                 android:name=".MainActivity"
                 android:exported="true"
                 android:label="@string/app_name"
                 android:networkSecurityConfig="@xml/network_security_config"
                 android:theme="@style/Theme.Adm.NoActionBar">
-                        <intent-filter>
-                            <action android:name="android.intent.action.MAIN"/>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
 
-                            <category android:name="android.intent.category.LAUNCHER"/>
-                        </intent-filter>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
         </activity>
 
-<!--        <activity android:name=".mvvm.ui.examine.ModelExamineActivity" android:exported="true"/>-->
-        <activity android:name=".mvvm.ui.examine.Space3DActivity" android:exported="true">
+        <!--        <activity android:name=".mvvm.ui.examine.ModelExamineActivity" android:exported="true"/>-->
+        <activity
+                android:name=".mvvm.ui.examine.Space3DActivity"
+                android:exported="true"
+                android:windowSoftInputMode="adjustPan"
+                android:theme="@style/Theme.Adm.NoActionBar">
             <!--<intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
 
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>-->
         </activity>
+        <activity
+                android:name=".mvvm.ui.examine.Repair_ImgSelActivity"
+                android:exported="true"
+                android:theme="@style/Theme.Adm.NoActionBar"/>
+        <activity
+                android:name=".mvvm.ui.examine.LookBigPicActivity"
+                android:exported="true"
+                android:theme="@style/Theme.Adm.NoActionBar"/>
     </application>
 
 </manifest>

BIN
app/src/main/assets/dist/Images/AddPointIcon.png


BIN
app/src/main/assets/dist/Images/Type_0.png


BIN
app/src/main/assets/dist/Images/Type_1.png


BIN
app/src/main/assets/dist/Images/Type_2.png


+ 748 - 0
app/src/main/assets/dist/JsonConfig/PorjectConfig copy.json

@@ -0,0 +1,748 @@
+{
+  "Url": {
+    "burl": "http://60.205.177.43:8000/",
+    "rurl": "api/WebMeshProvider/"
+  },
+  "Other": {
+    "WebView": {
+      "MaxViewNumber": 30
+    },
+    "CameraMove": {
+      "Angle": 45,
+      "Scale": 20
+    }
+  },
+  "Scene": {
+    "background": "#ffffff"
+  },
+  "SceneShowConfig": {
+    "IsShowHellp": false,
+    "IsSaveBgFileContent": true
+  },
+  "Camera": {
+    "set_position": [201.69111390728676, 64.05603286250314, 354.8486370303567],
+    "set_rotation": [0,0,3.1415926],
+    "set_up": [0, 0, 1],
+    "far": 2000000
+  },
+  "Controls": {
+    "set_target": [201.56757796623262, 49.06930207992287, -3.673672653795472e-15],
+    "minDistance": 0,
+    "maxDistance": 1000000,    
+    "enableDamping": false,
+    "dampingFactor": 0.05
+  },
+  "Light": {
+    "DirectionalLight": {
+      "set_position": [0, 41.497, 47.424],
+      "color": "#EEFOF6",
+      "intensity":0.8
+    },
+    "AmbientLight": {
+      "color": "#000003"
+    }
+  },
+  "Material": {
+    "DefaultMaterial": {
+      "matType": "MeshPhongMaterial",
+      "color": "#92CBEE",
+      "transparent": true
+    },
+    "System": {
+      "OST_Doors": {
+        "color": "#1F2429"
+      },
+      "OST_Columns":{
+        "color": "#646C73"
+      },
+      "OST_Windows ": {
+        "color": "#ffffff"
+      },"OST_Floors": {
+        "color": "#ffffff"
+      },"OST_Stairs": {
+        "color": "#646C73"
+      },
+      "OST_Stairsrailing": {
+        "color": "#ffffff"
+      },
+      "OST_StructuralColumns": {
+        "color": "#ffffff"
+      },
+      "OST_Walls": {
+        "color": "#C3C7CB"
+      },
+      "OST_PipeFitting": {
+        "color": "#6d67e0"
+      },
+      "OST_PipeAccessory": {
+        "color": "#6d67e0"
+      },
+      "OST_PipeCurves": {
+        "color": "#6d67e0"
+      },
+      "OST_DuctFitting": {
+        "color": "#6d67e0"
+      },
+      "OST_DuctCurves": {
+        "color": "#6d67e0"
+      }
+    },
+    "CustomGroup": {
+
+    }
+  },
+  "Matrix": {
+    "CustomGroup": {
+      "BaoJingWebPanel": {
+        "contentMessage": "所有报警设备面板默认位置以及缩放系数",
+        "translate": {
+          "y": 10
+        },
+        "scale": {
+          "x": 1,
+          "y": 1,
+          "z": 1
+        }
+      }
+    }
+  },
+  "Clip_OST":[
+    {
+      "name": "OST_MechanicalEquipment",
+      "CName": "机械设备"
+    },
+    {
+      "name": "OST_PipeFitting",
+      "CName": "管件"
+    },
+    {
+      "name": "OST_PipeAccessory",
+      "CName": "管道附件"
+    },
+    {
+      "name": "OST_PipeCurves",
+      "CName": "管道"
+    },
+    {
+      "name": "OST_CableTray",
+      "CName": "电缆桥架"
+    },
+    {
+      "name": "OST_CableTrayFitting",
+      "CName": "电缆桥架配件"
+    },
+    {
+      "name": "OST_DuctFitting",
+      "CName": "风管管件"
+    },
+    {
+      "name": "OST_DuctCurves",
+      "CName": "风管"
+    },
+    {
+      "name": "OST_DuctAccessory",
+      "CName": "风管附件"
+    },
+    {
+      "name": "OST_DuctTerminal",
+      "CName": "风道末端"
+    },
+    {
+      "name": "OST_ElectricalEquipment",
+      "CName": "电气设备"
+    },
+    {
+      "name": "OST_ElectricalFixtures",
+      "CName": "电气装置"
+    },
+    {
+      "name": "OST_FireAlarmDevices",
+      "CName": "火警设备"
+    },
+    {
+      "name": "OST_LightingFixtures",
+      "CName": "照明设备"
+    },
+    {
+      "name": "OST_SecurityDevices",
+      "CName": "安全设备"
+    },
+    {
+      "name": "OST_SpecialityEquipment",
+      "CName": "专用设备"
+    },
+    {
+      "name": "OST_FlexPipeCurves",
+      "CName": "软管"
+    },
+    {
+      "name": "OST_FlexDuctCurves",
+      "CName": "软风管"
+    },
+    {
+      "name": "OST_FabricationParts",
+      "CName": "预制零件"
+    },
+    {
+      "name": "OST_GenericModel",
+      "CName": "常规模型"
+    },
+    {
+      "name": "OST_Walls",
+      "CName": "墙"
+    },
+    {
+      "name": "OST_Ceilings",
+      "CName": "天花板"
+    },
+    {
+      "name": "OST_Floors",
+      "CName": "楼板"
+    },
+    {
+      "name": "OST_Roofs",
+      "CName": "屋顶"
+    },
+    {
+      "name": "OST_Doors",
+      "CName": "门"
+    },
+    {
+      "name": "OST_Windows",
+      "CName": "窗"
+    },
+    {
+      "name": "OST_Columns",
+      "CName": "柱"
+    },
+    {
+      "name": "OST_StructuralStiffener",
+      "CName": "结构加强板"
+    },
+    {
+      "name": "OST_AreaRein",
+      "CName": "结构区域钢筋"
+    },
+    {
+      "name": "OST_StructuralFoundation",
+      "CName": "结构基础"
+    },
+    {
+      "name": "OST_StructuralColumns",
+      "CName": "结构柱"
+    },
+    {
+      "name": "OST_StructuralTruss",
+      "CName": "结构桁架"
+    },
+    {
+      "name": "OST_StructuralFraming",
+      "CName": "结构框架"
+    },
+    {
+      "name": "OST_Stairs",
+      "CName": "楼梯"
+    },
+    {
+      "name": "OST_CurtainWallPanels",
+      "CName": "幕墙嵌板"
+    },
+    {
+      "name": "OST_CurtainWallMullions",
+      "CName": "幕墙竖梃"
+    },
+    {
+      "name": "OST_CurtaSystem",
+      "CName": "幕墙系统"
+    },
+    {
+      "name": "OST_Topography",
+      "CName": "地形"
+    },
+    {
+      "name": "OST_Site",
+      "CName": "场地"
+    },
+    {
+      "name": "OST_Ramps",
+      "CName": "坡道"
+    },
+    {
+      "name": "OST_HVAC_Zones",
+      "CName": "HVAC 区"
+    },
+    {
+      "name": "OST_Mass",
+      "CName": "体量"
+    },
+    {
+      "name": "OST_Parking",
+      "CName": "停车场"
+    },
+    {
+      "name": "OST_RasterImages",
+      "CName": "光栅图像"
+    },
+    {
+      "name": "OST_PlumbingFixtures",
+      "CName": "卫浴装置"
+    },
+    {
+      "name": "OST_Sprinklers",
+      "CName": "喷头"
+    },
+    {
+      "name": "OST_Furniture",
+      "CName": "家具"
+    },
+    {
+      "name": "OST_FurnitureSystems",
+      "CName": "家具系统"
+    },
+    {
+      "name": "OST_Wire",
+      "CName": "导线"
+    },
+    {
+      "name": "OST_Rooms",
+      "CName": "房间"
+    },
+    {
+      "name": "OST_NurseCallDevices",
+      "CName": "护理呼叫设备"
+    },
+    {
+      "name": "OST_DataDevices",
+      "CName": "数据设备"
+    },
+    {
+      "name": "OST_StairsRailing",
+      "CName": "栏杆扶手"
+    },
+    {
+      "name": "OST_Planting",
+      "CName": "植物"
+    },
+    {
+      "name": "OST_Casework",
+      "CName": "橱柜"
+    },
+    {
+      "name": "OST_LightingDevices",
+      "CName": "灯具"
+    },
+    {
+      "name": "OST_TelephoneDevices",
+      "CName": "电话设备"
+    },
+    {
+      "name": "OST_MEPSpaces",
+      "CName": "空间"
+    },
+    {
+      "name": "OST_PipeInsulations",
+      "CName": "管道隔热层"
+    },
+    {
+      "name": "OST_Entourage",
+      "CName": "环境"
+    },
+    {
+      "name": "OST_DetailComponents",
+      "CName": "详图项目"
+    },
+    {
+      "name": "OST_CommunicationDevices",
+      "CName": "通讯设备"
+    },
+    {
+      "name": "OST_Roads",
+      "CName": "道路"
+    },
+    {
+      "name": "OST_Areas",
+      "CName": "面积"
+    },
+    {
+      "name": "OST_DuctLinings",
+      "CName": "风管内衬"
+    },
+    {
+      "name": "OST_PlaceHolderDucts",
+      "CName": "风管占位符"
+    },
+    {
+      "name": "OST_DuctInsulations",
+      "CName": "风管隔热层"
+    },
+    {
+      "name": "OST_PlaceHolderPipes",
+      "CName": "管道占位符"
+    },
+    {
+      "name": "OST_Lines",
+      "CName": "线"
+    },
+    {
+      "name": "OST_Conduit",
+      "CName": "线管"
+    },
+    {
+      "name": "OST_ConduitFitting",
+      "CName": "线管配件"
+    },
+    {
+      "name": "OST_Parts",
+      "CName": "组成部分"
+    },
+    {
+      "name": "OST_StructuralFramingSystem",
+      "CName": "结构梁系统"
+    },
+    {
+      "name": "OST_PathRein",
+      "CName": "结构路径钢筋"
+    },
+    {
+      "name": "OST_StructConnections",
+      "CName": "结构连接"
+    },
+    {
+      "name": "OST_Rebar",
+      "CName": "结构钢筋"
+    },
+    {
+      "name": "OST_FabricReinforcement",
+      "CName": "结构钢筋网"
+    },
+    {
+      "name": "OST_FabricAreas",
+      "CName": "结构钢筋网区域"
+    },
+    {
+      "name": "OST_ShaftOpening",
+      "CName": "竖井洞口"
+    }
+  ],
+  "Load_OST": [{
+      "name": "OST_MechanicalEquipment",
+      "CName": "机械设备"
+    },
+    {
+      "name": "OST_PipeFitting",
+      "CName": "管件"
+    },
+    {
+      "name": "OST_PipeAccessory",
+      "CName": "管道附件"
+    },
+    {
+      "name": "OST_PipeCurves",
+      "CName": "管道"
+    },
+    {
+      "name": "OST_CableTray",
+      "CName": "电缆桥架"
+    },
+    {
+      "name": "OST_CableTrayFitting",
+      "CName": "电缆桥架配件"
+    },
+    {
+      "name": "OST_DuctFitting",
+      "CName": "风管管件"
+    },
+    {
+      "name": "OST_DuctCurves",
+      "CName": "风管"
+    },
+    {
+      "name": "OST_DuctAccessory",
+      "CName": "风管附件"
+    },
+    {
+      "name": "OST_DuctTerminal",
+      "CName": "风道末端"
+    },
+    {
+      "name": "OST_ElectricalEquipment",
+      "CName": "电气设备"
+    },
+    {
+      "name": "OST_ElectricalFixtures",
+      "CName": "电气装置"
+    },
+    {
+      "name": "OST_FireAlarmDevices",
+      "CName": "火警设备"
+    },
+    {
+      "name": "OST_LightingFixtures",
+      "CName": "照明设备"
+    },
+    {
+      "name": "OST_SecurityDevices",
+      "CName": "安全设备"
+    },
+    {
+      "name": "OST_SpecialityEquipment",
+      "CName": "专用设备"
+    },
+    {
+      "name": "OST_FlexPipeCurves",
+      "CName": "软管"
+    },
+    {
+      "name": "OST_FlexDuctCurves",
+      "CName": "软风管"
+    },
+    {
+      "name": "OST_FabricationParts",
+      "CName": "预制零件"
+    },
+    {
+      "name": "OST_GenericModel",
+      "CName": "常规模型"
+    },
+    {
+      "name": "OST_Walls",
+      "CName": "墙"
+    },
+    {
+      "name": "OST_Ceilings",
+      "CName": "天花板"
+    },
+    {
+      "name": "OST_Floors",
+      "CName": "楼板"
+    },
+    {
+      "name": "OST_Roofs",
+      "CName": "屋顶"
+    },
+    {
+      "name": "OST_Doors",
+      "CName": "门"
+    },
+    {
+      "name": "OST_Windows",
+      "CName": "窗"
+    },
+    {
+      "name": "OST_Columns",
+      "CName": "柱"
+    },
+    {
+      "name": "OST_StructuralStiffener",
+      "CName": "结构加强板"
+    },
+    {
+      "name": "OST_AreaRein",
+      "CName": "结构区域钢筋"
+    },
+    {
+      "name": "OST_StructuralFoundation",
+      "CName": "结构基础"
+    },
+    {
+      "name": "OST_StructuralColumns",
+      "CName": "结构柱"
+    },
+    {
+      "name": "OST_StructuralTruss",
+      "CName": "结构桁架"
+    },
+    {
+      "name": "OST_StructuralFraming",
+      "CName": "结构框架"
+    },
+    {
+      "name": "OST_Stairs",
+      "CName": "楼梯"
+    },
+    {
+      "name": "OST_CurtainWallPanels",
+      "CName": "幕墙嵌板"
+    },
+    {
+      "name": "OST_CurtainWallMullions",
+      "CName": "幕墙竖梃"
+    },
+    {
+      "name": "OST_CurtaSystem",
+      "CName": "幕墙系统"
+    },
+    {
+      "name": "OST_Topography",
+      "CName": "地形"
+    },
+    {
+      "name": "OST_Site",
+      "CName": "场地"
+    },
+    {
+      "name": "OST_Ramps",
+      "CName": "坡道"
+    },
+    {
+      "name": "OST_HVAC_Zones",
+      "CName": "HVAC 区"
+    },
+    {
+      "name": "OST_Mass",
+      "CName": "体量"
+    },
+    {
+      "name": "OST_Parking",
+      "CName": "停车场"
+    },
+    {
+      "name": "OST_RasterImages",
+      "CName": "光栅图像"
+    },
+    {
+      "name": "OST_PlumbingFixtures",
+      "CName": "卫浴装置"
+    },
+    {
+      "name": "OST_Sprinklers",
+      "CName": "喷头"
+    },
+    {
+      "name": "OST_Furniture",
+      "CName": "家具"
+    },
+    {
+      "name": "OST_FurnitureSystems",
+      "CName": "家具系统"
+    },
+    {
+      "name": "OST_Wire",
+      "CName": "导线"
+    },
+    {
+      "name": "OST_Rooms",
+      "CName": "房间"
+    },
+    {
+      "name": "OST_NurseCallDevices",
+      "CName": "护理呼叫设备"
+    },
+    {
+      "name": "OST_DataDevices",
+      "CName": "数据设备"
+    },
+    {
+      "name": "OST_StairsRailing",
+      "CName": "栏杆扶手"
+    },
+    {
+      "name": "OST_Planting",
+      "CName": "植物"
+    },
+    {
+      "name": "OST_Casework",
+      "CName": "橱柜"
+    },
+    {
+      "name": "OST_LightingDevices",
+      "CName": "灯具"
+    },
+    {
+      "name": "OST_TelephoneDevices",
+      "CName": "电话设备"
+    },
+    {
+      "name": "OST_MEPSpaces",
+      "CName": "空间"
+    },
+    {
+      "name": "OST_PipeInsulations",
+      "CName": "管道隔热层"
+    },
+    {
+      "name": "OST_Entourage",
+      "CName": "环境"
+    },
+    {
+      "name": "OST_DetailComponents",
+      "CName": "详图项目"
+    },
+    {
+      "name": "OST_CommunicationDevices",
+      "CName": "通讯设备"
+    },
+    {
+      "name": "OST_Roads",
+      "CName": "道路"
+    },
+    {
+      "name": "OST_Areas",
+      "CName": "面积"
+    },
+    {
+      "name": "OST_DuctLinings",
+      "CName": "风管内衬"
+    },
+    {
+      "name": "OST_PlaceHolderDucts",
+      "CName": "风管占位符"
+    },
+    {
+      "name": "OST_DuctInsulations",
+      "CName": "风管隔热层"
+    },
+    {
+      "name": "OST_PlaceHolderPipes",
+      "CName": "管道占位符"
+    },
+    {
+      "name": "OST_Lines",
+      "CName": "线"
+    },
+    {
+      "name": "OST_Conduit",
+      "CName": "线管"
+    },
+    {
+      "name": "OST_ConduitFitting",
+      "CName": "线管配件"
+    },
+    {
+      "name": "OST_Parts",
+      "CName": "组成部分"
+    },
+    {
+      "name": "OST_StructuralFramingSystem",
+      "CName": "结构梁系统"
+    },
+    {
+      "name": "OST_PathRein",
+      "CName": "结构路径钢筋"
+    },
+    {
+      "name": "OST_StructConnections",
+      "CName": "结构连接"
+    },
+    {
+      "name": "OST_Rebar",
+      "CName": "结构钢筋"
+    },
+    {
+      "name": "OST_FabricReinforcement",
+      "CName": "结构钢筋网"
+    },
+    {
+      "name": "OST_FabricAreas",
+      "CName": "结构钢筋网区域"
+    },
+    {
+      "name": "OST_ShaftOpening",
+      "CName": "竖井洞口"
+    }
+  ],
+  "CodeString":{
+    "SpaceCatName":"OST_Space",
+    "OutLineUnit":0.00328083989501
+  }
+}

+ 749 - 0
app/src/main/assets/dist/JsonConfig/PorjectConfig.json

@@ -0,0 +1,749 @@
+{
+  "Url": {
+    "burl": "http://60.205.177.43:8000/",
+    "rurl": "api/WebMeshProvider/"
+  },
+  "Other": {
+    "WebView": {
+      "MaxViewNumber": 30
+    },
+    "CameraMove": {
+      "Angle": 45,
+      "Scale": 20
+    }
+  },
+  "Scene": {
+    "background": "#ffffff"
+  },
+  "SceneShowConfig": {
+    "IsShowHellp": false,
+    "IsSaveBgFileContent": true
+  },
+  "Camera": {
+    "set_position": [201.56757796623262, 49.06930207992287, 1000],
+    "set_rotation": [0,0,0],
+    "set_up": [0, 0, 1],
+    "far": 2000000
+  },
+  "Controls": {
+    "set_target": [201.56757796623262, 49.06930207992287, 0],
+    "minDistance": 0,
+    "maxDistance": 1000000,    
+    "maxPolarAngle":90,
+    "enableDamping": false,
+    "dampingFactor": 0.05
+  },
+  "Light": {
+    "DirectionalLight": {
+      "set_position": [0, 41.497, 47.424],
+      "color": "#EEFOF6",
+      "intensity":0.8
+    },
+    "AmbientLight": {
+      "color": "#000003"
+    }
+  },
+  "Material": {
+    "DefaultMaterial": {
+      "matType": "MeshPhongMaterial",
+      "color": "#92CBEE",
+      "transparent": true
+    },
+    "System": {
+      "OST_Doors": {
+        "color": "#1F2429"
+      },
+      "OST_Columns":{
+        "color": "#646C73"
+      },
+      "OST_Windows ": {
+        "color": "#ffffff"
+      },"OST_Floors": {
+        "color": "#ffffff"
+      },"OST_Stairs": {
+        "color": "#646C73"
+      },
+      "OST_Stairsrailing": {
+        "color": "#ffffff"
+      },
+      "OST_StructuralColumns": {
+        "color": "#ffffff"
+      },
+      "OST_Walls": {
+        "color": "#C3C7CB"
+      },
+      "OST_PipeFitting": {
+        "color": "#6d67e0"
+      },
+      "OST_PipeAccessory": {
+        "color": "#6d67e0"
+      },
+      "OST_PipeCurves": {
+        "color": "#6d67e0"
+      },
+      "OST_DuctFitting": {
+        "color": "#6d67e0"
+      },
+      "OST_DuctCurves": {
+        "color": "#6d67e0"
+      }
+    },
+    "CustomGroup": {
+
+    }
+  },
+  "Matrix": {
+    "CustomGroup": {
+      "BaoJingWebPanel": {
+        "contentMessage": "所有报警设备面板默认位置以及缩放系数",
+        "translate": {
+          "y": 10
+        },
+        "scale": {
+          "x": 1,
+          "y": 1,
+          "z": 1
+        }
+      }
+    }
+  },
+  "Clip_OST":[
+    {
+      "name": "OST_MechanicalEquipment",
+      "CName": "机械设备"
+    },
+    {
+      "name": "OST_PipeFitting",
+      "CName": "管件"
+    },
+    {
+      "name": "OST_PipeAccessory",
+      "CName": "管道附件"
+    },
+    {
+      "name": "OST_PipeCurves",
+      "CName": "管道"
+    },
+    {
+      "name": "OST_CableTray",
+      "CName": "电缆桥架"
+    },
+    {
+      "name": "OST_CableTrayFitting",
+      "CName": "电缆桥架配件"
+    },
+    {
+      "name": "OST_DuctFitting",
+      "CName": "风管管件"
+    },
+    {
+      "name": "OST_DuctCurves",
+      "CName": "风管"
+    },
+    {
+      "name": "OST_DuctAccessory",
+      "CName": "风管附件"
+    },
+    {
+      "name": "OST_DuctTerminal",
+      "CName": "风道末端"
+    },
+    {
+      "name": "OST_ElectricalEquipment",
+      "CName": "电气设备"
+    },
+    {
+      "name": "OST_ElectricalFixtures",
+      "CName": "电气装置"
+    },
+    {
+      "name": "OST_FireAlarmDevices",
+      "CName": "火警设备"
+    },
+    {
+      "name": "OST_LightingFixtures",
+      "CName": "照明设备"
+    },
+    {
+      "name": "OST_SecurityDevices",
+      "CName": "安全设备"
+    },
+    {
+      "name": "OST_SpecialityEquipment",
+      "CName": "专用设备"
+    },
+    {
+      "name": "OST_FlexPipeCurves",
+      "CName": "软管"
+    },
+    {
+      "name": "OST_FlexDuctCurves",
+      "CName": "软风管"
+    },
+    {
+      "name": "OST_FabricationParts",
+      "CName": "预制零件"
+    },
+    {
+      "name": "OST_GenericModel",
+      "CName": "常规模型"
+    },
+    {
+      "name": "OST_Walls",
+      "CName": "墙"
+    },
+    {
+      "name": "OST_Ceilings",
+      "CName": "天花板"
+    },
+    {
+      "name": "OST_Floors",
+      "CName": "楼板"
+    },
+    {
+      "name": "OST_Roofs",
+      "CName": "屋顶"
+    },
+    {
+      "name": "OST_Doors",
+      "CName": "门"
+    },
+    {
+      "name": "OST_Windows",
+      "CName": "窗"
+    },
+    {
+      "name": "OST_Columns",
+      "CName": "柱"
+    },
+    {
+      "name": "OST_StructuralStiffener",
+      "CName": "结构加强板"
+    },
+    {
+      "name": "OST_AreaRein",
+      "CName": "结构区域钢筋"
+    },
+    {
+      "name": "OST_StructuralFoundation",
+      "CName": "结构基础"
+    },
+    {
+      "name": "OST_StructuralColumns",
+      "CName": "结构柱"
+    },
+    {
+      "name": "OST_StructuralTruss",
+      "CName": "结构桁架"
+    },
+    {
+      "name": "OST_StructuralFraming",
+      "CName": "结构框架"
+    },
+    {
+      "name": "OST_Stairs",
+      "CName": "楼梯"
+    },
+    {
+      "name": "OST_CurtainWallPanels",
+      "CName": "幕墙嵌板"
+    },
+    {
+      "name": "OST_CurtainWallMullions",
+      "CName": "幕墙竖梃"
+    },
+    {
+      "name": "OST_CurtaSystem",
+      "CName": "幕墙系统"
+    },
+    {
+      "name": "OST_Topography",
+      "CName": "地形"
+    },
+    {
+      "name": "OST_Site",
+      "CName": "场地"
+    },
+    {
+      "name": "OST_Ramps",
+      "CName": "坡道"
+    },
+    {
+      "name": "OST_HVAC_Zones",
+      "CName": "HVAC 区"
+    },
+    {
+      "name": "OST_Mass",
+      "CName": "体量"
+    },
+    {
+      "name": "OST_Parking",
+      "CName": "停车场"
+    },
+    {
+      "name": "OST_RasterImages",
+      "CName": "光栅图像"
+    },
+    {
+      "name": "OST_PlumbingFixtures",
+      "CName": "卫浴装置"
+    },
+    {
+      "name": "OST_Sprinklers",
+      "CName": "喷头"
+    },
+    {
+      "name": "OST_Furniture",
+      "CName": "家具"
+    },
+    {
+      "name": "OST_FurnitureSystems",
+      "CName": "家具系统"
+    },
+    {
+      "name": "OST_Wire",
+      "CName": "导线"
+    },
+    {
+      "name": "OST_Rooms",
+      "CName": "房间"
+    },
+    {
+      "name": "OST_NurseCallDevices",
+      "CName": "护理呼叫设备"
+    },
+    {
+      "name": "OST_DataDevices",
+      "CName": "数据设备"
+    },
+    {
+      "name": "OST_StairsRailing",
+      "CName": "栏杆扶手"
+    },
+    {
+      "name": "OST_Planting",
+      "CName": "植物"
+    },
+    {
+      "name": "OST_Casework",
+      "CName": "橱柜"
+    },
+    {
+      "name": "OST_LightingDevices",
+      "CName": "灯具"
+    },
+    {
+      "name": "OST_TelephoneDevices",
+      "CName": "电话设备"
+    },
+    {
+      "name": "OST_MEPSpaces",
+      "CName": "空间"
+    },
+    {
+      "name": "OST_PipeInsulations",
+      "CName": "管道隔热层"
+    },
+    {
+      "name": "OST_Entourage",
+      "CName": "环境"
+    },
+    {
+      "name": "OST_DetailComponents",
+      "CName": "详图项目"
+    },
+    {
+      "name": "OST_CommunicationDevices",
+      "CName": "通讯设备"
+    },
+    {
+      "name": "OST_Roads",
+      "CName": "道路"
+    },
+    {
+      "name": "OST_Areas",
+      "CName": "面积"
+    },
+    {
+      "name": "OST_DuctLinings",
+      "CName": "风管内衬"
+    },
+    {
+      "name": "OST_PlaceHolderDucts",
+      "CName": "风管占位符"
+    },
+    {
+      "name": "OST_DuctInsulations",
+      "CName": "风管隔热层"
+    },
+    {
+      "name": "OST_PlaceHolderPipes",
+      "CName": "管道占位符"
+    },
+    {
+      "name": "OST_Lines",
+      "CName": "线"
+    },
+    {
+      "name": "OST_Conduit",
+      "CName": "线管"
+    },
+    {
+      "name": "OST_ConduitFitting",
+      "CName": "线管配件"
+    },
+    {
+      "name": "OST_Parts",
+      "CName": "组成部分"
+    },
+    {
+      "name": "OST_StructuralFramingSystem",
+      "CName": "结构梁系统"
+    },
+    {
+      "name": "OST_PathRein",
+      "CName": "结构路径钢筋"
+    },
+    {
+      "name": "OST_StructConnections",
+      "CName": "结构连接"
+    },
+    {
+      "name": "OST_Rebar",
+      "CName": "结构钢筋"
+    },
+    {
+      "name": "OST_FabricReinforcement",
+      "CName": "结构钢筋网"
+    },
+    {
+      "name": "OST_FabricAreas",
+      "CName": "结构钢筋网区域"
+    },
+    {
+      "name": "OST_ShaftOpening",
+      "CName": "竖井洞口"
+    }
+  ],
+  "Load_OST": [{
+      "name": "OST_MechanicalEquipment",
+      "CName": "机械设备"
+    },
+    {
+      "name": "OST_PipeFitting",
+      "CName": "管件"
+    },
+    {
+      "name": "OST_PipeAccessory",
+      "CName": "管道附件"
+    },
+    {
+      "name": "OST_PipeCurves",
+      "CName": "管道"
+    },
+    {
+      "name": "OST_CableTray",
+      "CName": "电缆桥架"
+    },
+    {
+      "name": "OST_CableTrayFitting",
+      "CName": "电缆桥架配件"
+    },
+    {
+      "name": "OST_DuctFitting",
+      "CName": "风管管件"
+    },
+    {
+      "name": "OST_DuctCurves",
+      "CName": "风管"
+    },
+    {
+      "name": "OST_DuctAccessory",
+      "CName": "风管附件"
+    },
+    {
+      "name": "OST_DuctTerminal",
+      "CName": "风道末端"
+    },
+    {
+      "name": "OST_ElectricalEquipment",
+      "CName": "电气设备"
+    },
+    {
+      "name": "OST_ElectricalFixtures",
+      "CName": "电气装置"
+    },
+    {
+      "name": "OST_FireAlarmDevices",
+      "CName": "火警设备"
+    },
+    {
+      "name": "OST_LightingFixtures",
+      "CName": "照明设备"
+    },
+    {
+      "name": "OST_SecurityDevices",
+      "CName": "安全设备"
+    },
+    {
+      "name": "OST_SpecialityEquipment",
+      "CName": "专用设备"
+    },
+    {
+      "name": "OST_FlexPipeCurves",
+      "CName": "软管"
+    },
+    {
+      "name": "OST_FlexDuctCurves",
+      "CName": "软风管"
+    },
+    {
+      "name": "OST_FabricationParts",
+      "CName": "预制零件"
+    },
+    {
+      "name": "OST_GenericModel",
+      "CName": "常规模型"
+    },
+    {
+      "name": "OST_Walls",
+      "CName": "墙"
+    },
+    {
+      "name": "OST_Ceilings",
+      "CName": "天花板"
+    },
+    {
+      "name": "OST_Floors",
+      "CName": "楼板"
+    },
+    {
+      "name": "OST_Roofs",
+      "CName": "屋顶"
+    },
+    {
+      "name": "OST_Doors",
+      "CName": "门"
+    },
+    {
+      "name": "OST_Windows",
+      "CName": "窗"
+    },
+    {
+      "name": "OST_Columns",
+      "CName": "柱"
+    },
+    {
+      "name": "OST_StructuralStiffener",
+      "CName": "结构加强板"
+    },
+    {
+      "name": "OST_AreaRein",
+      "CName": "结构区域钢筋"
+    },
+    {
+      "name": "OST_StructuralFoundation",
+      "CName": "结构基础"
+    },
+    {
+      "name": "OST_StructuralColumns",
+      "CName": "结构柱"
+    },
+    {
+      "name": "OST_StructuralTruss",
+      "CName": "结构桁架"
+    },
+    {
+      "name": "OST_StructuralFraming",
+      "CName": "结构框架"
+    },
+    {
+      "name": "OST_Stairs",
+      "CName": "楼梯"
+    },
+    {
+      "name": "OST_CurtainWallPanels",
+      "CName": "幕墙嵌板"
+    },
+    {
+      "name": "OST_CurtainWallMullions",
+      "CName": "幕墙竖梃"
+    },
+    {
+      "name": "OST_CurtaSystem",
+      "CName": "幕墙系统"
+    },
+    {
+      "name": "OST_Topography",
+      "CName": "地形"
+    },
+    {
+      "name": "OST_Site",
+      "CName": "场地"
+    },
+    {
+      "name": "OST_Ramps",
+      "CName": "坡道"
+    },
+    {
+      "name": "OST_HVAC_Zones",
+      "CName": "HVAC 区"
+    },
+    {
+      "name": "OST_Mass",
+      "CName": "体量"
+    },
+    {
+      "name": "OST_Parking",
+      "CName": "停车场"
+    },
+    {
+      "name": "OST_RasterImages",
+      "CName": "光栅图像"
+    },
+    {
+      "name": "OST_PlumbingFixtures",
+      "CName": "卫浴装置"
+    },
+    {
+      "name": "OST_Sprinklers",
+      "CName": "喷头"
+    },
+    {
+      "name": "OST_Furniture",
+      "CName": "家具"
+    },
+    {
+      "name": "OST_FurnitureSystems",
+      "CName": "家具系统"
+    },
+    {
+      "name": "OST_Wire",
+      "CName": "导线"
+    },
+    {
+      "name": "OST_Rooms",
+      "CName": "房间"
+    },
+    {
+      "name": "OST_NurseCallDevices",
+      "CName": "护理呼叫设备"
+    },
+    {
+      "name": "OST_DataDevices",
+      "CName": "数据设备"
+    },
+    {
+      "name": "OST_StairsRailing",
+      "CName": "栏杆扶手"
+    },
+    {
+      "name": "OST_Planting",
+      "CName": "植物"
+    },
+    {
+      "name": "OST_Casework",
+      "CName": "橱柜"
+    },
+    {
+      "name": "OST_LightingDevices",
+      "CName": "灯具"
+    },
+    {
+      "name": "OST_TelephoneDevices",
+      "CName": "电话设备"
+    },
+    {
+      "name": "OST_MEPSpaces",
+      "CName": "空间"
+    },
+    {
+      "name": "OST_PipeInsulations",
+      "CName": "管道隔热层"
+    },
+    {
+      "name": "OST_Entourage",
+      "CName": "环境"
+    },
+    {
+      "name": "OST_DetailComponents",
+      "CName": "详图项目"
+    },
+    {
+      "name": "OST_CommunicationDevices",
+      "CName": "通讯设备"
+    },
+    {
+      "name": "OST_Roads",
+      "CName": "道路"
+    },
+    {
+      "name": "OST_Areas",
+      "CName": "面积"
+    },
+    {
+      "name": "OST_DuctLinings",
+      "CName": "风管内衬"
+    },
+    {
+      "name": "OST_PlaceHolderDucts",
+      "CName": "风管占位符"
+    },
+    {
+      "name": "OST_DuctInsulations",
+      "CName": "风管隔热层"
+    },
+    {
+      "name": "OST_PlaceHolderPipes",
+      "CName": "管道占位符"
+    },
+    {
+      "name": "OST_Lines",
+      "CName": "线"
+    },
+    {
+      "name": "OST_Conduit",
+      "CName": "线管"
+    },
+    {
+      "name": "OST_ConduitFitting",
+      "CName": "线管配件"
+    },
+    {
+      "name": "OST_Parts",
+      "CName": "组成部分"
+    },
+    {
+      "name": "OST_StructuralFramingSystem",
+      "CName": "结构梁系统"
+    },
+    {
+      "name": "OST_PathRein",
+      "CName": "结构路径钢筋"
+    },
+    {
+      "name": "OST_StructConnections",
+      "CName": "结构连接"
+    },
+    {
+      "name": "OST_Rebar",
+      "CName": "结构钢筋"
+    },
+    {
+      "name": "OST_FabricReinforcement",
+      "CName": "结构钢筋网"
+    },
+    {
+      "name": "OST_FabricAreas",
+      "CName": "结构钢筋网区域"
+    },
+    {
+      "name": "OST_ShaftOpening",
+      "CName": "竖井洞口"
+    }
+  ],
+  "CodeString":{
+    "SpaceCatName":"OST_Space",
+    "OutLineUnit":0.00328083989501
+  }
+}

File diff suppressed because it is too large
+ 1 - 0
app/src/main/assets/dist/css/app.9e7e8a89.css


File diff suppressed because it is too large
+ 1 - 0
app/src/main/assets/dist/css/chunk-vendors.a16c4353.css


BIN
app/src/main/assets/dist/favicon.ico


BIN
app/src/main/assets/dist/fonts/element-icons.535877f5.woff


BIN
app/src/main/assets/dist/fonts/element-icons.732389de.ttf


File diff suppressed because it is too large
+ 18 - 0
app/src/main/assets/dist/index.html


File diff suppressed because it is too large
+ 2 - 0
app/src/main/assets/dist/js/app.90127e5f.js


File diff suppressed because it is too large
+ 1 - 0
app/src/main/assets/dist/js/app.90127e5f.js.map


File diff suppressed because it is too large
+ 74 - 0
app/src/main/assets/dist/js/chunk-vendors.47a002f1.js


File diff suppressed because it is too large
+ 1 - 0
app/src/main/assets/dist/js/chunk-vendors.47a002f1.js.map


+ 4 - 0
app/src/main/java/com/ys/bdtp/adm/di/Di.kt

@@ -8,6 +8,8 @@ import com.ys.bdtp.adm.app.interceptor.GzipInterceptor
 import com.ys.bdtp.adm.app.interceptor.TokenInterceptor
 import com.ys.bdtp.adm.mvvm.model.db.AdmDatabase
 import com.ys.bdtp.adm.mvvm.model.nt.Api
+import com.ys.bdtp.adm.mvvm.vm.examine.Space3DRepository
+import com.ys.bdtp.adm.mvvm.vm.examine.Space3DViewModel
 import com.ys.bdtp.adm.mvvm.vm.cad.CadRepository
 import com.ys.bdtp.adm.mvvm.vm.cad.CadViewModel
 import com.ys.bdtp.adm.mvvm.vm.flash.FlashRepository
@@ -98,6 +100,7 @@ val repositoryModule = DI.Module("repository") {
     bind { provider { ProjectRepository(instance(), instance()) } }
     bind { provider { TaskRepository(instance(), instance()) } }
     bind { provider { OfflineRepository(instance(), instance()) } }
+    bind { provider { Space3DRepository(instance(), instance()) } }
     bind { provider { CadRepository(instance(), instance()) } }
 }
 
@@ -108,6 +111,7 @@ val viewModelModule = DI.Module("viewModel") {
     bind { provider { ProjectViewModel(instance()) } }
     bind { provider { TaskViewModel(instance()) } }
     bind { provider { OfflineViewModel(instance()) } }
+    bind { provider { Space3DViewModel(instance()) } }
     bind { provider { CadViewModel(instance()) } }
 }
 

+ 6 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/db/dao/config/ProblemInfoConfigDao.kt

@@ -3,7 +3,9 @@ package com.ys.bdtp.adm.mvvm.model.db.dao.config
 import androidx.room.Dao
 import androidx.room.Insert
 import androidx.room.OnConflictStrategy
+import androidx.room.Query
 import com.ys.bdtp.adm.mvvm.model.db.entity.config.ProblemInfoConfigEntity
+import com.ys.bdtp.adm.mvvm.model.db.entity.task.BuildingEntity
 
 /**
  * problem_info 表访问接口
@@ -16,4 +18,8 @@ interface ProblemInfoConfigDao {
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     fun insProblemInfos(problemInfos: List<ProblemInfoConfigEntity>)
 
+    @Query("select * from problem_info_config where problem_type_code = :typeCode")
+    suspend fun getProblemInfoByTypeCode(typeCode: String): List<ProblemInfoConfigEntity>?
+
+
 }

+ 6 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/db/dao/config/ProblemTypeConfigDao.kt

@@ -3,6 +3,8 @@ package com.ys.bdtp.adm.mvvm.model.db.dao.config
 import androidx.room.Dao
 import androidx.room.Insert
 import androidx.room.OnConflictStrategy
+import androidx.room.Query
+import com.ys.bdtp.adm.mvvm.model.db.entity.config.ProblemInfoConfigEntity
 import com.ys.bdtp.adm.mvvm.model.db.entity.config.ProblemTypeConfigEntity
 
 /**
@@ -15,4 +17,8 @@ interface ProblemTypeConfigDao {
 
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     fun insProblemTypes(problemTypes: List<ProblemTypeConfigEntity>)
+
+    @Query("select * from problem_type_config where problem_type_code = :typeCode")
+    suspend fun getProblemsTypeInfoByTypeCode(typeCode: String): ProblemTypeConfigEntity?
+
 }

+ 4 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/db/dao/task/BuildingDao.kt

@@ -16,6 +16,10 @@ interface BuildingDao {
     @Query("select * from building where id = :id")
     suspend fun getBuildingById(id: String): BuildingEntity?
 
+    @Query("select * from building where project_id = :projectId and valid = 1")
+    suspend fun getBuildingByProjectId(projectId: String): List<BuildingEntity>?
+
+
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     suspend fun insBuilding(vararg floor: BuildingEntity)
 

+ 3 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/db/dao/task/FloorDao.kt

@@ -17,6 +17,9 @@ interface FloorDao {
     @Query("select * from floor where id = :id")
     suspend fun getFloorById(id: String): FloorEntity?
 
+    @Query("select * from floor where building_id = :buildingId and valid = 1")
+    suspend fun getFloorsByBuildingId(buildingId: String): List<FloorEntity>?
+
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     suspend fun insFloor(vararg floor: FloorEntity)
 

+ 6 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/db/dao/task/ProblemDao.kt

@@ -17,9 +17,15 @@ interface ProblemDao {
     @Query("select * from problem")
     fun getProblems(): List<ProblemEntity>
 
+    @Query("select * from problem where floor_id = :floorId")
+    fun getProblemsByFloorId(floorId: String): List<ProblemEntity>
+
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     suspend fun insProblem(problem: ProblemEntity)
 
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     suspend fun insProblems(problems: List<ProblemEntity>)
+
+    @Query("select * from problem where obj_id = :objId")
+    fun getProblemByObjId(objId: String): ProblemEntity
 }

+ 2 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/InfosforFloor.kt

@@ -4,4 +4,6 @@ data class InfosforFloor(
     val digitalDeliveryID: String,
     val bimIdPre: String,
     val floorElevation: Double,
+    val height: Double,
+    val floorSequenceID: Int,
 )

+ 15 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/LineArray.java

@@ -0,0 +1,15 @@
+package com.ys.bdtp.adm.mvvm.model.vo;
+
+import java.util.ArrayList;
+
+public class LineArray {
+    public String ID;
+    public ArrayList<PointZ> Points = new ArrayList<>();
+    public String Color = "#ff0000";
+    public Double Opacity = 0.5;
+    public Boolean IsLoop;
+    public Boolean IsLaQi;
+    public Boolean IsFullColor = false;
+    public Double LineWidth = 3d;
+
+}

+ 7 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/LineObject.java

@@ -0,0 +1,7 @@
+package com.ys.bdtp.adm.mvvm.model.vo;
+
+import java.util.ArrayList;
+
+public class LineObject {
+    public ArrayList<PointZ> Points = new ArrayList<>();
+}

+ 1 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/MeshObjectModel.kt

@@ -7,4 +7,5 @@ data class MeshObjectModel(
     val ID: String,//模型ID
     val Type: String,//Build 建筑 Space 空间  Other 设备或者管道
     val SystemType: String,
+    val CenterPosition: PointZ,
 )

+ 3 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/Options.kt

@@ -0,0 +1,3 @@
+package com.ys.bdtp.adm.mvvm.model.vo
+
+data class Options(val name: String, val code: String)

+ 22 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/Photos.java

@@ -0,0 +1,22 @@
+package com.ys.bdtp.adm.mvvm.model.vo;
+
+import android.graphics.Bitmap;
+
+import java.io.Serializable;
+
+/**
+ * created by lihao on 2018/11/19
+ */
+public class Photos implements Serializable {
+    public String id;
+    public String type;
+    public String name;
+    public String key;
+    public String creator_id;
+    public String creator_name;
+    public String create_time;
+    public Bitmap bitmap;
+
+    public int itemType;//0-图片 1-添加按钮 2-bitmap
+    public String path;//本地bitmap路径
+}

+ 5 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/PointModel.java

@@ -0,0 +1,5 @@
+package com.ys.bdtp.adm.mvvm.model.vo;
+
+public class PointModel {
+    public PointZ Position;
+}

+ 9 - 15
app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/PointZ.java

@@ -2,29 +2,23 @@ package com.ys.bdtp.adm.mvvm.model.vo;
 
 import com.google.gson.annotations.SerializedName;
 
+import java.io.Serializable;
+
 /**
  * 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 class PointZ implements Serializable {
+    public float X;
+    public float Y;
+    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;
+        X = x;
+        Y = y;
+        Z = z;
     }
 }

+ 12 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/PositionInfo.java

@@ -0,0 +1,12 @@
+package com.ys.bdtp.adm.mvvm.model.vo;
+
+public class PositionInfo {
+    public Position position;
+
+    public static class Position {
+        public String left;
+        public String right;
+        public String up;
+        public String down;
+    }
+}

+ 1 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/SetFloorPathModel.kt

@@ -4,4 +4,5 @@ data class SetFloorPathModel(
     val PorjectID: String,
     val FloorID: String,
     val FloorElevation: Double,
+    val FloorHeight: Double,
 )

+ 12 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/StyleObject.java

@@ -0,0 +1,12 @@
+package com.ys.bdtp.adm.mvvm.model.vo;
+
+import java.util.ArrayList;
+
+public class StyleObject {
+    public ArrayList<String> ID = new ArrayList<>();
+    public Style Style = new Style();
+
+    public static class Style {
+        public String color = "#FF0000";
+    }
+}

+ 20 - 1
app/src/main/java/com/ys/bdtp/adm/mvvm/model/vo/TipArray.java

@@ -3,8 +3,27 @@ package com.ys.bdtp.adm.mvvm.model.vo;
 public class TipArray {
     public String ID;
     public Param Param = new Param();
+    public PointZ Position;
+    public boolean IsShowIconMesh = true;
+    public TipMeshStyle TipMeshStyle = new TipMeshStyle();
 
-    public static class Param{
+    public static class Param {
+        public String Content;
+        //图标类型 0 多余 1 缺少 2 错误
+        public int Type;
+        public String ID;
 
+        public Param(String content, int type, String Id) {
+            Content = content;
+            Type = type;
+            ID = Id;
+        }
+
+        public Param() {
+        }
+    }
+
+    public static class TipMeshStyle {
+        public String color = "#ff0000";
     }
 }

+ 348 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/BaseRecyclerViewAdapter.java

@@ -0,0 +1,348 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.TextView;
+
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.List;
+
+/**
+ * function="基于Recycleview的万能适配器"
+ * Created by wangmaobo on 2018/4/3.
+ */
+public abstract class BaseRecyclerViewAdapter<T>
+        extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+    protected List<T> mBeans;
+    protected Context mContext;
+    private int mLastAnimatedPosition = -1;
+    public OnItemClickListener mOnItemClickListener;
+    protected LayoutInflater inflater;
+    /*
+     * 是否开启item动画
+     */
+    private boolean mAnimateItems = false;
+    private int viewType;
+    private boolean mIsFirst = true;
+    public ViewGroup parent;
+
+    public BaseRecyclerViewAdapter(Context context, List<T> beans) {
+        mContext = context;
+        mBeans = beans;
+    }
+
+    @Override
+    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        this.viewType = viewType;
+        this.parent = parent;
+        inflater = LayoutInflater.from(mContext);
+        View view = inflater.inflate(getItemLayoutId(viewType), parent, false);
+        ViewHolder viewHolder = new ViewHolder(view);
+        return viewHolder;
+    }
+
+    @Override
+    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+        itemAnimation(holder.itemView, position);
+        ViewHolder viewHolder = (ViewHolder) holder;
+        onBindDataToView(viewHolder, mBeans.get(position));
+    }
+
+    @Override
+    public int getItemCount() {
+        return mBeans == null ? 0 : mBeans.size();
+    }
+
+    public void add(T bean) {
+        mBeans.add(bean);
+        notifyDataSetChanged();
+    }
+
+    public void addAll(List<T> beans) {
+        mBeans.addAll(beans);
+        notifyDataSetChanged();
+    }
+
+    public void clear() {
+        mBeans.clear();
+        notifyDataSetChanged();
+    }
+
+    /**
+     * item动画
+     */
+    private void itemAnimation(View itemView, int position) {
+        if (!mAnimateItems) return;
+        if (position > mLastAnimatedPosition) {
+            mLastAnimatedPosition = position;
+            itemView.setTranslationY(getScreenHeight());
+            itemView.setRotation(360);
+            itemView.animate()
+                    .translationY(0)
+                    .rotation(0)
+                    .setStartDelay(1000 * position)
+                    .setInterpolator(new DecelerateInterpolator(3.f))
+                    .setDuration(800)
+                    .start();
+        }
+    }
+
+    private int getScreenHeight() {
+        return mContext.getResources().getDisplayMetrics().heightPixels;
+    }
+
+    public class ViewHolder extends RecyclerView.ViewHolder {
+        private final SparseArray<View> mViews;
+        private View itemView;
+
+        public ViewHolder(View itemView) {
+            super(itemView);
+            mViews = new SparseArray<>();
+            this.itemView = itemView;
+            this.itemView.setOnClickListener(v -> {
+                onItemClick(getAdapterPosition());
+                if (mOnItemClickListener != null)
+                    setOnItemClick(v, getAdapterPosition());
+            });
+            setTextChangedListener(this, itemView);
+            setRatingBarListener(this, itemView);
+        }
+
+        public <T extends View> T getView(int viewId) {
+            View view = mViews.get(viewId);
+            if (view == null) {
+                view = itemView.findViewById(viewId);
+                mViews.put(viewId, view);
+            }
+            return (T) view;
+        }
+
+        public ViewHolder setText(int viewId, String text) {
+            if (TextUtils.isEmpty(text)) {
+                text = "";
+            }
+            TextView tv = getView(viewId);
+            tv.setText(text);
+            return this;
+        }
+
+        public ViewHolder setHint(int viewId, String text) {
+            TextView tv = getView(viewId);
+            tv.setHint(text);
+            return this;
+        }
+
+        public ViewHolder setAlpha(int viewId, float alpha) {
+            View view = getView(viewId);
+            view.setAlpha(alpha);
+            return this;
+        }
+
+        /**
+         * 如果text为空,显示“--”
+         *
+         * @param viewId
+         * @param text
+         * @return
+         */
+        public ViewHolder setTextNotNull(int viewId, String text) {
+            if (TextUtils.isEmpty(text)) {
+                text = "--";
+            }
+            TextView tv = getView(viewId);
+            tv.setText(text);
+
+            return this;
+        }
+
+        public ViewHolder setTextHint(int viewId, String hint) {
+            if (TextUtils.isEmpty(hint)) {
+                return this;
+            }
+            TextView tv = getView(viewId);
+            tv.setHint(hint);
+            return this;
+        }
+
+        public ViewHolder setRightIconGone(int viewId, boolean isGone) {
+            if (isGone) {
+                getView(viewId).getLayoutParams().width = 0;
+            } else {
+                getView(viewId).getLayoutParams().width = 16;
+            }
+            return this;
+        }
+
+        public ViewHolder setEditEnable(int viewId, boolean isEnable) {
+            if (isEnable) {
+                getView(viewId).setEnabled(isEnable);
+            } else {
+                getView(viewId).setEnabled(isEnable);
+            }
+            return this;
+        }
+
+        public ViewHolder setBackground(int viewId, int drawableId) {
+            View view = getView(viewId);
+            view.setBackground(mContext.getResources().getDrawable(drawableId));
+            return this;
+        }
+
+        /**
+         * 如果text为空,控件隐藏
+         *
+         * @param viewId
+         * @param text
+         * @return
+         */
+        public ViewHolder setTextAndView(int viewId, String text) {
+            TextView tv = getView(viewId);
+            if (TextUtils.isEmpty(text)) {
+                tv.setVisibility(View.GONE);
+            } else {
+                tv.setText(text);
+                tv.setVisibility(View.VISIBLE);
+            }
+            return this;
+        }
+
+        public ViewHolder setProjectName(int viewId, String text) {
+            TextView tv = getView(viewId);
+            return this;
+        }
+
+        public ViewHolder setTextColor(int viewId, int textColorId) {
+            TextView tv = getView(viewId);
+            tv.setTextColor(textColorId);
+            return this;
+        }
+
+
+        public ViewHolder setClickListener(int viewId) {
+            View v = getView(viewId);
+            v.setOnClickListener(v1 -> onSingleViewClick(v1, getAdapterPosition()));
+            return this;
+        }
+
+        public ViewHolder cancelClickListener(int viewId) {
+            View v = getView(viewId);
+            v.setOnClickListener(null);
+            return this;
+        }
+
+        public ViewHolder setVisible(int viewId) {
+            View v = getView(viewId);
+            v.setVisibility(View.VISIBLE);
+            return this;
+        }
+
+        public ViewHolder setInVisible(int viewId) {
+            View v = getView(viewId);
+            v.setVisibility(View.GONE);
+            return this;
+        }
+
+        public ViewHolder setInVisibleTwo(int viewId) {
+            View v = getView(viewId);
+            v.setVisibility(View.INVISIBLE);
+            return this;
+        }
+
+        public int getCurrentPosition() {
+            return getAdapterPosition();
+        }
+
+    }
+
+    /**
+     * 绑定布局id
+     *
+     * @param viewType
+     * @return
+     */
+    protected abstract int getItemLayoutId(int viewType);
+
+    /**
+     * 绑定数据
+     *
+     * @param holder
+     * @param t
+     */
+    protected abstract void onBindDataToView(ViewHolder holder, T t);
+
+    /**
+     * 支持多种ItemType
+     *
+     * @param position
+     * @return
+     */
+    @Override
+    public abstract int getItemViewType(int position);
+
+    /**
+     * ItemView里的某个子控件的单击事件(如果需要,重写此方法就行)
+     * 只有在{@link #onBindDataToView}注册了{@link ViewHolder#setClickListener}才有效果
+     *
+     * @param position
+     */
+    protected void onSingleViewClick(View view, int position) {
+
+    }
+
+    /**
+     * ItemView的单击事件(如果需要,重写此方法就行)
+     *
+     * @param position
+     */
+    protected void onItemClick(int position) {
+
+    }
+
+    /**
+     * 为edittext添加文本监听(如果需要,重写此方法就行)
+     *
+     * @param holder
+     * @param itemView
+     */
+    protected void setTextChangedListener(ViewHolder holder, View itemView) {
+
+    }
+
+    protected void setRatingBarListener(ViewHolder holder, View itemView) {
+
+    }
+
+    /**
+     * 为Adapter添加item点击方法
+     */
+    public BaseRecyclerViewAdapter setOnItemClickListener(OnItemClickListener listener) {
+        mOnItemClickListener = listener;
+        return this;
+    }
+
+    public interface OnItemClickListener {
+        void onItemClick(BaseRecyclerViewAdapter adapter, View view, int position);
+    }
+
+    private void setOnItemClick(View v, int position) {
+        mOnItemClickListener.onItemClick(BaseRecyclerViewAdapter.this, v, position);
+    }
+
+    public View.OnTouchListener onTouchListener = (v, event) -> {
+        if (MotionEvent.ACTION_DOWN == event.getAction()) {
+            v.getParent().requestDisallowInterceptTouchEvent(true);
+        } else if (MotionEvent.ACTION_UP == event.getAction()) {
+            v.getParent().requestDisallowInterceptTouchEvent(false);
+        }
+        return false;
+    };
+
+}

+ 16 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/BaseViewHolder.java

@@ -0,0 +1,16 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+import android.view.View;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+/**
+ * Created by Administrator on 2015/11/9.
+ */
+
+public class BaseViewHolder extends RecyclerView.ViewHolder {
+
+    public BaseViewHolder(View itemView) {
+        super(itemView);
+    }
+}

+ 17 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/BaseViewModelInterface.java

@@ -0,0 +1,17 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+/**
+ * Created by yanfapersagy on 2017/6/29.
+ */
+
+public interface BaseViewModelInterface {
+
+
+    /**
+     * wangmaobo
+     * 在ViewModel初始化的过程中需要传入改接口的实现用于ViewModel向View层发布命令
+     * @param name 命令
+     * @param params 附带的参数,一般情况下为Null
+     */
+    public void SendDirective(String name, Object params);
+}

+ 83 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/BuildingFloorExpandAdapter.kt

@@ -0,0 +1,83 @@
+package com.sybotan.android.demo.adapter
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.BaseExpandableListAdapter
+import android.widget.TextView
+import com.ys.bdtp.adm.R
+import com.ys.bdtp.adm.mvvm.model.db.entity.task.BuildingEntity
+import com.ys.bdtp.adm.mvvm.model.db.entity.task.FloorEntity
+
+
+class ExpandAdapter(
+    context: Context,
+    groups: List<BuildingEntity>,
+    items: List<List<FloorEntity>>
+) : BaseExpandableListAdapter() {
+    private var mContext: Context = context
+    private var mGroups: List<BuildingEntity> = groups
+    private var mItems: List<List<FloorEntity>> = items
+    private var mLayoutInflater: LayoutInflater = LayoutInflater.from(context)
+
+    override fun getGroupCount(): Int {
+        return mGroups.size
+    }
+
+    override fun getChildrenCount(groupPosition: Int): Int {
+        return mItems[groupPosition].size
+    }
+
+    override fun getGroup(groupPosition: Int): BuildingEntity {
+        return mGroups[groupPosition]
+    }
+
+    override fun getChild(groupPosition: Int, childPosition: Int): FloorEntity {
+        return mItems[groupPosition][childPosition]
+    }
+
+    override fun getGroupId(groupPosition: Int): Long {
+        return groupPosition.toLong()
+    }
+
+    override fun getChildId(groupPosition: Int, childPosition: Int): Long {
+        return childPosition.toLong()
+    }
+
+    override fun isChildSelectable(groupPosition: Int, childPosition: Int): Boolean {
+        return true
+    }
+
+    override fun hasStableIds(): Boolean {
+        return false
+    }
+
+    override fun getGroupView(groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup?): View {
+        var holder = convertView
+        if (holder == null) {
+            holder = mLayoutInflater.inflate(R.layout.group_expand_space, parent, false)
+        }
+        val group: BuildingEntity = mGroups[groupPosition]
+        val tvGroup = holder?.findViewById(R.id.groupSpaceTV) as TextView
+        tvGroup.text = group.localName
+        return holder
+    }
+
+    override fun getChildView(
+        groupPosition: Int,
+        childPosition: Int,
+        isLastChild: Boolean,
+        convertView: View?,
+        parent: ViewGroup?
+    ): View {
+        var holder = convertView
+        if (holder == null) {
+            holder = mLayoutInflater.inflate(R.layout.child_expand_space, parent, false)
+        }
+        val itemTv = holder?.findViewById(R.id.itemSpaceTV) as TextView
+        val item = mItems[groupPosition][childPosition]
+        itemTv.text = item.localName
+        return holder
+    }
+}

+ 112 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/ImageListRVAdapter.java

@@ -0,0 +1,112 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.ImageView;
+
+import com.ys.bdtp.adm.R;
+import com.yuyh.easyadapter.recyclerview.EasyRVAdapter;
+import com.yuyh.easyadapter.recyclerview.EasyRVHolder;
+import com.yuyh.library.imgsel.ImgSelConfig;
+import com.yuyh.library.imgsel.bean.Image;
+import com.yuyh.library.imgsel.common.Constant;
+import com.yuyh.library.imgsel.common.OnItemClickListener;
+import com.yuyh.library.imgsel.widget.SquareRelativeLayout;
+
+import java.util.List;
+
+/**
+ * Created by wangmaobo on 2018/12/10.
+ */
+public class ImageListRVAdapter extends EasyRVAdapter<Image> {
+    private boolean showCamera;
+    private boolean mutiSelect;
+    private boolean hasClick = false;
+
+    private ImgSelConfig config;
+    private Context context;
+    private OnItemClickListener listener;
+
+    public ImageListRVAdapter(Context context, List<Image> list, ImgSelConfig config) {
+        super(context, list, R.layout.common_item_img_sel, R.layout.item_img_sel_take_photo);
+        this.context = context;
+        this.config = config;
+    }
+
+    @Override
+    protected void onBindData(final EasyRVHolder viewHolder, final int position, final Image item) {
+
+        if (position == 0 && showCamera) {
+            if (!hasClick) {
+                hasClick = true;
+                if (listener != null)
+                    listener.onImageClick(position, item);
+            }
+            ImageView iv = viewHolder.getView(R.id.ivTakePhoto);
+            iv.setImageResource(R.drawable.icon_takephoto);
+            SquareRelativeLayout sql = viewHolder.getView(R.id.sql);
+            sql.setOnClickListener(v -> {
+                if (listener != null)
+                    listener.onImageClick(position, item);
+            });
+            return;
+        }
+
+        if (mutiSelect) {
+            viewHolder.getView(com.yuyh.library.imgsel.R.id.ivPhotoCheaked).setOnClickListener(v -> {
+                if (listener != null) {
+                    int ret = listener.onCheckedClick(position, item);
+                    if (ret == 1) { // 局部刷新
+                        if (Constant.imageList.contains(item.path)) {
+                            viewHolder.setImageResource(R.id.ivPhotoCheaked, R.drawable.choseicon_green);
+                        } else {
+                            viewHolder.setImageResource(R.id.ivPhotoCheaked, R.drawable.choseicon_gray);
+                        }
+                    }
+                }
+            });
+        }
+
+        viewHolder.setOnItemViewClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (listener != null)
+                    listener.onImageClick(position, item);
+            }
+        });
+
+        final ImageView iv = viewHolder.getView(com.yuyh.library.imgsel.R.id.ivImage);
+        config.loader.displayImage(context, item.path, iv);
+
+        if (mutiSelect) {
+            viewHolder.setVisible(com.yuyh.library.imgsel.R.id.ivPhotoCheaked, true);
+            if (Constant.imageList.contains(item.path)) {
+                viewHolder.setImageResource(R.id.ivPhotoCheaked, R.drawable.choseicon_green);
+            } else {
+                viewHolder.setImageResource(R.id.ivPhotoCheaked, R.drawable.choseicon_gray);
+            }
+        } else {
+            viewHolder.setVisible(com.yuyh.library.imgsel.R.id.ivPhotoCheaked, false);
+        }
+    }
+
+    public void setShowCamera(boolean showCamera) {
+        this.showCamera = showCamera;
+    }
+
+    public void setMutiSelect(boolean mutiSelect) {
+        this.mutiSelect = mutiSelect;
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        if (position == 0 && showCamera) {
+            return 1;
+        }
+        return 0;
+    }
+
+    public void setOnItemClickListener(OnItemClickListener listener) {
+        this.listener = listener;
+    }
+}

+ 284 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/InfoAdapter.java

@@ -0,0 +1,284 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.view.Gravity;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.TextView;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.ys.bdtp.adm.R;
+import com.ys.bdtp.adm.mvvm.model.db.entity.config.ProblemInfoConfigEntity;
+import com.ys.bdtp.adm.mvvm.model.db.entity.task.CustomInfoEntity;
+import com.ys.bdtp.adm.mvvm.model.vo.Options;
+import com.ys.bdtp.adm.mvvm.model.vo.Photos;
+import com.ys.bdtp.adm.mvvm.model.vo.PositionInfo;
+import kotlinx.serialization.descriptors.PrimitiveKind;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Objects;
+
+public class InfoAdapter extends BaseRecyclerViewAdapter<ProblemInfoConfigEntity> {
+    public static final int TEXT = 1;
+    public static final int ENUM = 2;
+    public static final int PHOTO = 3;
+    public static final int POSITION = 4;
+
+    public HashMap<String, Object> hashMap = new HashMap<>();
+    public ArrayList<String> valueList = new ArrayList<>();
+    private AddPic addPic;
+    public Gson gson = new Gson();
+    public boolean isDetail;
+
+
+    public InfoAdapter(Context context, List<ProblemInfoConfigEntity> beans) {
+        super(context, beans);
+    }
+
+    @Override
+    protected int getItemLayoutId(int viewType) {
+        switch (viewType) {
+            case TEXT:
+                return R.layout.view_text;
+            case ENUM:
+                return R.layout.view_enum;
+            case PHOTO:
+                return R.layout.view_photo;
+            case POSITION:
+                return R.layout.view_position;
+            default:
+                return R.layout.empty;
+        }
+    }
+
+    @Override
+    protected void onBindDataToView(BaseRecyclerViewAdapter<ProblemInfoConfigEntity>.ViewHolder holder, ProblemInfoConfigEntity info) {
+        if ("coordinate".equals(info.getCode()) || "objectId".equals(info.getCode())) {
+            return;
+        }
+        switch (mBeans.get(holder.getCurrentPosition()).getDataType()) {
+            case "STRING":
+            case "DOUBLE":
+            case "INTEGER":
+                TextView title = holder.getView(R.id.title);
+                TextView unit = holder.getView(R.id.unit);
+                EditText edt = holder.getView(R.id.edt);
+                if (TextUtils.isEmpty(info.getUnit())) {
+                    unit.setVisibility(View.GONE);
+                } else {
+                    unit.setVisibility(View.VISIBLE);
+                    unit.setText(info.getUnit());
+                }
+                if ("remark".equals(info.getCode())) {
+                    edt.setMinHeight(150);
+                    if (isDetail) {
+                        holder.setVisible(R.id.switchLl);
+                    } else {
+                        holder.setInVisible(R.id.switchLl);
+                    }
+                } else {
+                    edt.setMinHeight(30);
+                    holder.setInVisible(R.id.switchLl);
+                }
+                title.setText(info.getName());
+                initEditTextTouch(edt, info);
+                break;
+            case "PHOTO":
+                TextView titlePhoto = holder.getView(R.id.title);
+                RecyclerView rv = holder.getView(R.id.rv);
+                titlePhoto.setText(info.getName());
+                List<Photos> beans = new ArrayList<>();
+                Photos photo = new Photos();
+                photo.itemType = 1;
+                beans.add(photo);
+                if (!valueList.contains(info.getCode())) {
+                    if (hashMap != null && hashMap.get(info.getCode()) != null) {
+                        ArrayList<Photos> value = new Gson().fromJson(new Gson().toJson(hashMap.get(info.getCode())), new TypeToken<List<Photos>>() {
+                        }.getType());
+                        ArrayList<Photos> photos = value;
+                        beans.addAll(photos);
+                    }
+                    rv.setLayoutManager(new GridLayoutManager(mContext, 3));
+                    PictureAdapter adapter = new PictureAdapter(mContext, beans, "", false, 0);
+                    adapter.setOnPicAdd(new PictureAdapter.PicAdd() {
+                        @Override
+                        public void onPicAdd() {
+                            if (addPic != null) {
+                                addPic.onAddPic(info, holder.getCurrentPosition());
+                            }
+                        }
+                    });
+                    rv.setAdapter(adapter);
+                }
+                valueList.add(info.getCode());
+                break;
+            case "ENUM":
+                TextView enumTv = holder.getView(R.id.tv);
+//                TextView enumUnit = holder.getView(R.id.unit);
+                TextView enumTitle = holder.getView(R.id.title);
+                enumTitle.setText(info.getName());
+//                if (TextUtils.isEmpty(info.getUnit())) {
+//                    enumUnit.setVisibility(View.GONE);
+//                } else {
+//                    enumUnit.setVisibility(View.VISIBLE);
+//                    enumUnit.setText(info.getUnit());
+//                }
+                if (!valueList.contains(info.getCode())) {
+                    if (hashMap != null && hashMap.get(info.getCode()) != null) {
+                        ArrayList<String> value = new Gson().fromJson(Objects.requireNonNull(hashMap.get(info.getCode())).toString(), new TypeToken<List<String>>() {
+                        }.getType());
+                        StringBuilder sb = new StringBuilder();
+                        for (int i = 0; i < value.size(); i++) {
+//                            for (int j = 0; j < info.getDataSource().size(); j++) {
+//                                if (info.getDataSource().get(j).getCode().equals(value.get(i))) {
+//                                    sb.append(info.getDataSource().get(j).getName()).append("、");
+//                                }
+//                            }
+                        }
+                        enumTv.setText(sb.toString());
+                    }
+                }
+                valueList.add(info.getCode());
+
+                enumTv.setOnClickListener(v -> {
+                    SelectListSinglePopupWindow popupWindow = new SelectListSinglePopupWindow(mContext);
+                    List<Options> models = gson.fromJson(info.getDataSource(), new TypeToken<List<Options>>() {
+                    }.getType());
+                    popupWindow.setGenList(models, "TYPE1");
+                    popupWindow.setOnItemClickListener(new SelectListSinglePopupWindow.OnRecyclerViewItemClickListener() {
+                        @Override
+                        public void onItemClick(int position) {
+                            hashMap.put(info.getCode(), models.get(position).getCode());
+                            enumTv.setText(models.get(position).getName());
+                        }
+                    });
+                    popupWindow.showAtLocation(enumTv, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
+                });
+                break;
+            case "POSITION":
+                EditText left = holder.getView(R.id.left);
+                EditText right = holder.getView(R.id.right);
+                EditText up = holder.getView(R.id.up);
+                EditText down = holder.getView(R.id.down);
+                if (!valueList.contains(info.getCode())) {
+                    if (hashMap.get(info.getCode()) != null && !TextUtils.isEmpty(hashMap.get(info.getCode()).toString())) {
+                        PositionInfo positionInfo = new Gson().fromJson(Objects.requireNonNull(hashMap.get(info.getCode())).toString(), PositionInfo.class);
+                        left.setText(positionInfo.position.left);
+                        right.setText(positionInfo.position.right);
+                        up.setText(positionInfo.position.up);
+                        down.setText(positionInfo.position.down);
+                    }
+                }
+                PositionInfo positionInfo = new PositionInfo();
+                PositionInfo.Position position = new PositionInfo.Position();
+                position.left = left.getText().toString();
+                position.right = right.getText().toString();
+                position.up = up.getText().toString();
+                position.down = down.getText().toString();
+                positionInfo.position = position;
+                hashMap.put(info.getCode(), new Gson().toJson(positionInfo));
+                valueList.add(info.getCode());
+                break;
+        }
+    }
+
+    private void initEditTextTouch(EditText editText, ProblemInfoConfigEntity info) {
+//        editText.setOnTouchListener((v, event) -> {
+//            if (MotionEvent.ACTION_DOWN == event.getAction()) {
+//                v.getParent().requestDisallowInterceptTouchEvent(true);
+//            } else if (MotionEvent.ACTION_UP == event.getAction()) {
+//                v.getParent().requestDisallowInterceptTouchEvent(false);
+//            }
+//            return false;
+//        });
+        TextWatcher textWatcher = new TextWatcher() {
+            @Override
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+            }
+
+            @Override
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+            }
+
+            @Override
+            public void afterTextChanged(Editable s) {
+                hashMap.put(info.getCode(), s.toString());
+            }
+        };
+        if (editText.getTag() instanceof TextWatcher) {
+            editText.removeTextChangedListener((TextWatcher) editText.getTag());
+        }
+        if (!valueList.contains(info.getCode())) {
+            if (hashMap != null && hashMap.get(info.getCode()) != null) {
+                editText.setText(hashMap.get(info.getCode()).toString());
+            }
+        }
+        valueList.add(info.getCode());
+        editText.addTextChangedListener(textWatcher);
+        editText.setTag(textWatcher);
+
+        editText.getViewTreeObserver().addOnGlobalLayoutListener(
+                () -> {
+                    Rect r = new Rect();
+                    editText.getWindowVisibleDisplayFrame(r);
+                    int screenHeight = editText.getRootView()
+                            .getHeight();
+                    int heightDifference = screenHeight - (r.bottom);
+                    if (heightDifference > 200) {
+                        //软键盘显示
+                        editText.setFocusable(true);
+                    } else {
+                        //软键盘隐藏
+                        editText.clearFocus();
+
+                    }
+                });
+        editText.setOnClickListener(v -> {
+            editText.setFocusable(true);
+            editText.setFocusableInTouchMode(true);
+            editText.requestFocus();
+            editText.findFocus();
+            InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+            imm.showSoftInput(editText, InputMethodManager.SHOW_FORCED);// 显示输入法
+        });
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        if ("coordinate".equals(mBeans.get(position).getCode()) || "objectId".equals(mBeans.get(position).getCode())) {
+            return -1;
+        }
+        switch (mBeans.get(position).getDataType()) {
+            case "STRING":
+            case "DOUBLE":
+            case "INTEGER":
+                return TEXT;
+            case "PHOTO":
+                return PHOTO;
+            case "ENUM":
+                return ENUM;
+            case "POSITION":
+                return POSITION;
+        }
+        return 0;
+    }
+
+    public interface AddPic {
+        void onAddPic(ProblemInfoConfigEntity info, int currentPosition);
+    }
+
+    public void setOnAddPic(AddPic addPic) {
+        this.addPic = addPic;
+    }
+}

+ 96 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/LocalDataOperation.java

@@ -0,0 +1,96 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+import android.app.Activity;
+import android.content.Context;
+import android.text.TextUtils;
+
+import java.io.File;
+import java.util.List;
+
+import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
+import io.reactivex.Observable;
+import io.reactivex.ObservableOnSubscribe;
+import io.reactivex.Observer;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * Created by wangjie on 2019/10/15
+ * 利用Observable处理耗时操作时的线程切换类
+ * 诸如:本地文件读写、数据库操作等
+ */
+public class LocalDataOperation {
+    //在子线程处理耗时操作
+    public static final String DEAL_IO_DATA = "DEAL_IO_DATA";
+    //可以具体开始子线程的耗时操作前显示操作等待弹窗之类的
+    public static final String SHOW_DIALOG_IN_MAIN = "SHOW_DIALOG_IN_MAIN";
+    //子线程数据处理完毕,回到主线程
+    public static final String DEAL_DATA_NEXT = "DEAL_DATA_NEXT";
+    //子线程数据处理出现异常
+    public static final String DEAL_DATA_ERROR = "DEAL_DATA_ERROR";
+    //承接查验离线自动上传
+    public String ALL_NEED_SUBMIT_CHECK = "ALL_NEED_SUBMIT_CHECK";
+    //离线保存的工单待执行列表数据
+    public String ALL_NEED_SUBMIT_ORDER = "ALL_NEED_SUBMIT_ORDER";
+    //离线数据上传接口类
+    public OfflineSendRequest offlineSendRequest;
+
+
+    private LocalDataOperation() {
+        offlineSendRequest = new OfflineSendRequest();
+    }
+
+    private static class SingletonHolder {
+        private static final LocalDataOperation INSTANCE = new LocalDataOperation();
+    }
+
+    public static LocalDataOperation getInstance() {
+        return SingletonHolder.INSTANCE;
+    }
+
+    /**
+     * 在子线程中处理耗时操作,处理完回到主线程
+     *
+     * @param mActivity
+     * @param object
+     * @param <T>
+     */
+    public <T> void dealLocalData(RxAppCompatActivity mActivity, BaseViewModelInterface object) {
+        Observable<T> observable = Observable.create((ObservableOnSubscribe<T>) e -> {
+            object.SendDirective(DEAL_IO_DATA, e);
+        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
+        observable.compose(mActivity.bindToLifecycle()).subscribe(new Observer<T>() {
+            @Override
+            public void onSubscribe(Disposable d) {
+                object.SendDirective(SHOW_DIALOG_IN_MAIN, d);
+            }
+
+            @Override
+            public void onNext(T s) {
+                object.SendDirective(DEAL_DATA_NEXT, s);
+            }
+
+            @Override
+            public void onError(Throwable e) {
+                object.SendDirective(DEAL_DATA_ERROR, e);
+            }
+
+            @Override
+            public void onComplete() {
+
+            }
+        });
+    }
+
+    /**
+     * 离线操作的图片存储路径
+     *
+     * @param context
+     * @return
+     */
+    public String getOfflineImageFilePath(Context context) {
+        return SDCardHelper.getSDCardBaseDir() + "/Android/data/" + context.getPackageName() + "/offlineImages";
+    }
+
+}

+ 151 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/LookBigPicActivity.java

@@ -0,0 +1,151 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+
+import com.bumptech.glide.Glide;
+
+import com.ys.bdtp.adm.R;
+
+import java.io.File;
+
+/**
+ * created by lihao on 2018/11/14
+ * 查看大图片
+ */
+public class LookBigPicActivity extends Activity {
+
+
+    ImageView mImageView;
+    private String mUrl;
+    private String mId;
+    private boolean mCanEdit;
+    private int position;
+    //图片key
+    private String mKey;
+    private String mPath;
+    private String localPath;
+    private int type;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_look_big_pic);
+        mImageView = findViewById(R.id.look_big_pic_iv);
+        mUrl = getIntent().getStringExtra("url");
+        mId = getIntent().getStringExtra("id");
+        mKey = getIntent().getStringExtra("key");
+        mPath = getIntent().getStringExtra("path");
+        localPath = getIntent().getStringExtra("localPath");
+        mCanEdit = getIntent().getBooleanExtra("canEdit", false);
+        position = getIntent().getIntExtra("position", 0);
+        type = getIntent().getIntExtra("type", 0);
+        initView();
+    }
+
+    /**
+     * 图片压缩
+     */
+    public static Bitmap getScaledBitmap(String filePath, int width) {
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inJustDecodeBounds = true;
+        BitmapFactory.decodeFile(filePath, options);
+
+        int sampleSize = options.outWidth > width ? options.outWidth / width
+                + 1 : 1;
+        options.inJustDecodeBounds = false;
+        options.inSampleSize = sampleSize;
+        return BitmapFactory.decodeFile(filePath, options);
+    }
+
+    private void initView() {
+        if (!TextUtils.isEmpty(localPath)) {
+            WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
+            mImageView.setImageBitmap(getScaledBitmap(localPath, wm.getDefaultDisplay().getWidth()));
+            return;
+        }
+        if (!TextUtils.isEmpty(mPath)) {
+            Bitmap bitmap = getLoacalBitmap(mPath);
+            mImageView.setImageBitmap(bitmap);
+        } else {
+            //GlideUtils.loadImage(this, mUrl, mImageView, false);
+            if (TextUtils.isEmpty(mUrl)) {
+                return;
+            }
+            showImgWithThumbnail(this, mUrl, 1.0f, mImageView, getIntent().getBooleanExtra("isFile", false));
+        }
+    }
+
+    /**
+     * 加载图片若引起oom则缩略加载
+     *
+     * @param context
+     * @param url
+     * @param thumb
+     * @param mImageView
+     */
+    public static void showImgWithThumbnail(Context context, String url, float thumb, ImageView mImageView, boolean isFile) {
+        try {
+            if (isFile) {
+                Glide.with(context).load(new File(url)).thumbnail(thumb).into(mImageView);
+            } else {
+                Glide.with(context).load(url).thumbnail(thumb).into(mImageView);
+            }
+        } catch (OutOfMemoryError e) {
+            thumb -= 0.2f;
+            if (thumb <= 0) {
+                thumb = 0.1f;
+            }
+            showImgWithThumbnail(context, url, thumb, mImageView, isFile);
+        }
+    }
+
+    /**
+     * 加载本地图片
+     * http://bbs.3gstdy.com
+     *
+     * @param url
+     * @return
+     */
+    public static Bitmap getLoacalBitmap(String url) {
+        try {
+            BitmapFactory.Options options = new BitmapFactory.Options();
+            Bitmap bmp = BitmapFactory.decodeFile(url, options);
+            return bmp;
+        } catch (Error e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public static void launch(Context activity, String url, boolean canEdit) {
+        activity.startActivity(new Intent(activity, LookBigPicActivity.class)
+                .putExtra("url", url).putExtra("canEdit", canEdit));
+    }
+
+    public static void launch(Context activity, String url, boolean canEdit, boolean isFile) {
+        activity.startActivity(new Intent(activity, LookBigPicActivity.class)
+                .putExtra("url", url).putExtra("canEdit", canEdit)
+                .putExtra("isFile", isFile));
+    }
+
+    public static void launch(Context activity, String url, boolean canEdit, int type, String time, String projectName, boolean isFile) {
+        activity.startActivity(new Intent(activity, LookBigPicActivity.class)
+                .putExtra("url", url).putExtra("canEdit", canEdit)
+                .putExtra("type", type)
+                .putExtra("time", time)
+                .putExtra("projectName", projectName)
+                .putExtra("isFile", isFile));
+    }
+}

+ 94 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/MyDialogViewSingle.java

@@ -0,0 +1,94 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import com.ys.bdtp.adm.R;
+
+
+/**
+ * Created by 何鑫欣 on 2017/8/16.
+ */
+
+public abstract class MyDialogViewSingle extends Dialog {
+    private TextView contentview, bottomview, tv_info;
+    private CheckBox checkBox;
+
+    public MyDialogViewSingle(@NonNull Context context) {
+        super(context);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        super.onCreate(savedInstanceState);
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+        setContentView(R.layout.activity_newcreate_dialog);
+        contentview = (TextView) findViewById(R.id.contentTV);
+        tv_info = findViewById(R.id.tv_info);
+        bottomview = (TextView) findViewById(R.id.IKnowTV);
+        checkBox = (CheckBox) findViewById(R.id.check_single);
+        checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+
+            }
+        });
+        View.OnClickListener listener = new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                switch (v.getId()) {
+                    case R.id.IKnowTV:
+                        try {
+                            onBottomClick();
+                        } catch (InterruptedException e) {
+                            e.printStackTrace();
+                        }
+                        dismiss();
+                        break;
+                }
+            }
+        };
+        bottomview.setOnClickListener(listener);
+    }
+
+    public void setContent(String info) {
+        contentview.setText(info);
+    }
+
+    public void setInfo(String info) {
+        if (null == tv_info) {
+            tv_info = findViewById(R.id.tv_info);
+        }
+        tv_info.setVisibility(View.VISIBLE);
+        tv_info.setText(info);
+    }
+
+    public void setButtonNotice(String info) {
+        bottomview.setText(info);
+    }
+
+    public void setCancel(boolean isCancel) {
+        setCancelable(isCancel);
+    }
+
+    protected abstract void onBottomClick() throws InterruptedException;
+
+    public MyDialogViewSingle setButtonviewText(String leftText) {
+        bottomview.setText(leftText);
+        return this;
+    }
+
+    public MyDialogViewSingle setContentviewText(String rightText) {
+        contentview.setText(rightText);
+        return this;
+    }
+}

+ 63 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/MyGlideModules.java

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

+ 9 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/MyProvider.java

@@ -0,0 +1,9 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+import androidx.core.content.FileProvider;
+
+/**
+ * Created by Administrator on 2018/6/11.
+ */
+public class MyProvider extends FileProvider {
+}

+ 72 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/OfflineSendRequest.java

@@ -0,0 +1,72 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+import android.content.Context;
+
+import com.google.gson.Gson;
+import com.ys.bdtp.adm.mvvm.vm.examine.Space3DViewModel;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author wangjie
+ * @date 2020.06.13
+ * 不基于任何Activity的网络请求发送
+ * 本地离线缓存的各种数据发送至服务器
+ */
+public class OfflineSendRequest {
+    private Gson mGson;
+
+    public OfflineSendRequest() {
+        mGson = new Gson();
+    }
+
+
+    /**
+     * 新的离线图片存储上传
+     *
+     * @param context
+     * @param mVm
+     */
+    public void uploadImageNew(Context context, Space3DViewModel mVm, String projectId, String groupCode, String userId) {
+        String imageFilePath = LocalDataOperation.getInstance().getOfflineImageFilePath(context);
+        File imageFile = new File(imageFilePath);
+        if (imageFile.exists()) {
+            File[] files = imageFile.listFiles();
+            if (files != null && files.length > 0) {
+                for (File file : files) {
+                    Map<String, String> param = new HashMap<>();
+                    param.put("appId", "adm");
+                    param.put("userId", userId);
+                    param.put("groupCode", groupCode);
+                    param.put("projectId", projectId);
+                    mVm.fileUpload(param, file);
+//                    if (!TextUtils.isEmpty(file.getName()) && !file.getName().startsWith("uploaded")) {
+//                        final String url = Constant.ServerImgIPUp + file.getName();
+//                        Log.e("uploadImageNew url", url);
+//                        String result = UploadImage.uploadFiles(file, url);
+//                        if (!TextUtils.isEmpty(result)) {
+//                            String resultString = null;
+//                            try {
+//                                JSONObject object = new JSONObject(result);
+//                                resultString = object.getString("Result");
+//                                Log.e("resultString", resultString);
+//                            } catch (JSONException e) {
+//                                e.printStackTrace();
+//                            }
+//                            if ("success".equals(resultString)) {
+//                                //不管是那种情况,只要成功都需要从本地删除该图片
+//                                boolean b = file.renameTo(new File(imageFilePath + File.separator + "uploaded" + file.getName()));
+//                                //file.delete();
+//                                LogUtils.e("uploadImageNew", "上传成功" + b + file.getName());
+//                            } else {
+//                                LogUtils.e("uploadImageNew", "上传失败");
+//                            }
+//                        }
+//                    }
+                }
+            }
+        }
+    }
+}

+ 119 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/PersonalSelectSingleAdapter.java

@@ -0,0 +1,119 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.text.TextUtils;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.recyclerview.widget.RecyclerView;
+import com.ys.bdtp.adm.R;
+import com.ys.bdtp.adm.mvvm.model.vo.Options;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Created by cunwen on 16/6/21.
+ */
+public class PersonalSelectSingleAdapter extends RecyclerView.Adapter<PersonalSelectSingleAdapter.BuildViewHolder> {
+    private List<?> items = new ArrayList<>();
+    private Context context;
+    private int selectPosition;
+    private String type;
+    private boolean isRed;
+    private int redPosition;
+    private Boolean flag;
+
+    public void setItems(List<?> items, Context context, int position, String type) {
+        this.items = items;
+        this.context = context;
+        this.selectPosition = position;
+        this.type = type;
+    }
+
+
+    @Override
+    public BuildViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        View mRootView = LayoutInflater.from(parent.getContext())
+                .inflate(R.layout.personal_select_text_single_item, parent, false);
+        return new BuildViewHolder(mRootView);
+    }
+
+    @Override
+    public void onBindViewHolder(final BuildViewHolder holder, @SuppressLint("RecyclerView") int position) {
+        final Object item = items.get(position);
+        if (type.equals("TYPE1")) {
+            Options options = (Options) item;
+            holder.choice_name.setText(options.getName());
+        }
+
+//        if (selectPosition > 0 && selectPosition - 1 == position) {
+//            holder.choice_name.setTextColor(context.getResources().getColor(R.color.blue_2f48b7));
+//        } else {
+//            holder.choice_name.setTextColor(context.getResources().getColor(R.color.black_272727));
+//        }
+//        if (isRed && position == redPosition) {
+//            holder.choice_name.setTextColor(context.getResources().getColor(R.color.red_D44D44));
+//        } else if (isRed) {
+//            holder.choice_name.setTextColor(context.getResources().getColor(R.color.black_272727));
+//        }
+        holder.choice_layout.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mOnItemClickListener != null) {
+                    mOnItemClickListener.onItemClick(holder.choice_layout, position);
+                }
+            }
+        });
+//        if (flag) {
+//            holder.choice_name.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
+//        } else {
+        holder.choice_name.setGravity(Gravity.CENTER);
+//        }
+    }
+
+    @Override
+    public int getItemCount() {
+        return items.size();
+    }
+
+    public void setRedText(int i, boolean isRed) {
+        this.isRed = true;
+        this.redPosition = i;
+        notifyDataSetChanged();
+    }
+
+    public void setFlag(Boolean flag) {
+        this.flag = flag;
+        notifyDataSetChanged();
+    }
+
+
+    static class BuildViewHolder extends BaseViewHolder {
+        TextView choice_name;
+        LinearLayout choice_layout;
+
+        public BuildViewHolder(View mRootView) {
+            super(mRootView);
+            choice_name = (TextView) mRootView.findViewById(R.id.choice_name);
+            choice_layout = (LinearLayout) mRootView.findViewById(R.id.choice_layout);
+
+        }
+    }
+
+    private OnRecyclerViewItemClickListener mOnItemClickListener = null;
+
+    public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
+        this.mOnItemClickListener = listener;
+    }
+
+    public interface OnRecyclerViewItemClickListener {
+        void onItemClick(View view, int position);
+    }
+}

+ 156 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/PictureAdapter.java

@@ -0,0 +1,156 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.RequestOptions;
+
+
+import com.ys.bdtp.adm.R;
+import com.ys.bdtp.adm.mvvm.model.vo.Photos;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.util.List;
+
+/**
+ * created by lihao on 2018/12/11
+ * 九图
+ */
+public class PictureAdapter extends BaseRecyclerViewAdapter<Photos> {
+    private int currentPosition;
+    private String id;
+    private boolean canEdit;
+    private PicAdd picAdd;
+
+    public PictureAdapter(Context context, List<Photos> beans, String id, boolean canEdit, int currentPosition) {
+        super(context, beans);
+        this.id = id;
+        this.canEdit = canEdit;
+        this.currentPosition = currentPosition;
+    }
+
+    @Override
+    protected int getItemLayoutId(int viewType) {
+        return R.layout.item_node_nine_pic;
+    }
+
+    @Override
+    protected void onBindDataToView(ViewHolder holder, Photos photos) {
+        ViewGroup.LayoutParams layoutParams = holder.getView(R.id.node_nine_pic_iv).getLayoutParams();
+        holder.getView(R.id.node_nine_pic_iv).setLayoutParams(layoutParams);
+        switch (photos.itemType) {
+            case 0:
+                if (canEdit) {
+                    holder.setVisible(R.id.node_nine_pic_delete);
+                    holder.getView(R.id.node_nine_pic_delete).setOnClickListener(v -> {
+
+                    });
+                } else {
+                    holder.setInVisible(R.id.node_nine_pic_delete);
+                }
+                String url = "Constant.ServerImgIPDown + photos.key";
+                FileInputStream fis = null;
+                try {
+                    if (!TextUtils.isEmpty(photos.path)) {
+                        fis = new FileInputStream(photos.path);
+                        Bitmap bitmap = BitmapFactory.decodeStream(fis);
+                        ImageView imageView = (ImageView) holder.getView(R.id.node_nine_pic_iv);
+                        imageView.setImageBitmap(bitmap);
+                    } else {
+                        loadImageViewCornersByPath(mContext, url, holder.getView(R.id.node_nine_pic_iv));
+                    }
+                } catch (FileNotFoundException e) {
+                    e.printStackTrace();
+                    loadImageViewCornersByPath(mContext, url, holder.getView(R.id.node_nine_pic_iv));
+                }
+
+                holder.getView(R.id.node_nine_pic_iv).setOnClickListener(v -> {
+                    Intent intent = new Intent(mContext, LookBigPicActivity.class);
+                    intent.putExtra("url", url);
+                    intent.putExtra("key", photos.key);
+                    intent.putExtra("id", id);
+                    intent.putExtra("canEdit", canEdit);
+                    intent.putExtra("position", currentPosition);
+                    mContext.startActivity(intent);
+                });
+                holder.setText(R.id.node_nine_pic_position, holder.getCurrentPosition() + ".");
+                break;
+            case 2:
+                if (canEdit) {
+                    holder.setVisible(R.id.node_nine_pic_delete);
+                    holder.getView(R.id.node_nine_pic_delete).setOnClickListener(v -> {
+
+                    });
+                } else {
+                    holder.setInVisible(R.id.node_nine_pic_delete);
+                }
+                holder.setText(R.id.node_nine_pic_position, holder.getCurrentPosition() + 1 + ".");
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                photos.bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
+                byte[] bytes = baos.toByteArray();
+                ImageView view = holder.getView(R.id.node_nine_pic_iv);
+                view.setImageBitmap(photos.bitmap);
+                holder.getView(R.id.node_nine_pic_iv).setOnClickListener(v -> {
+                    Intent intent = new Intent(mContext, LookBigPicActivity.class);
+                    intent.putExtra("path", photos.path);
+                    intent.putExtra("key", photos.key);
+//                    intent.putExtra("id", id);
+                    intent.putExtra("canEdit", canEdit);
+                    intent.putExtra("position", currentPosition);
+                    mContext.startActivity(intent);
+                });
+                break;
+            case 1:
+                holder.setText(R.id.node_nine_pic_position, "");
+                holder.setInVisible(R.id.node_nine_pic_delete);
+                holder.getView(R.id.node_nine_pic_iv).setOnClickListener(v -> {
+                    if (picAdd != null) {
+                        picAdd.onPicAdd();
+                    }
+                });
+                break;
+        }
+    }
+
+    public void loadImageViewCornersByPath(Context mContext, String path, ImageView mImageView) {
+        if (TextUtils.isEmpty(path) || (path.contains("key=null") || path.endsWith("key="))) {
+            mImageView.setImageResource(R.drawable.image_error_icon);
+            return;
+        }
+        RequestOptions myoptions = new RequestOptions()
+                .placeholder(R.drawable.image_loading_icon)
+                .error(R.drawable.image_error_icon);
+
+        Glide.with(mContext)
+                .load(path)
+//                .diskCacheStrategy(DiskCacheStrategy.ALL)
+                .apply(myoptions)
+                .into(mImageView);
+        Log.e("path:" , path);
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        return mBeans.get(position).itemType;
+    }
+
+    public interface PicAdd {
+        void onPicAdd();
+    }
+
+    public void setOnPicAdd(PicAdd picAdd) {
+        this.picAdd = picAdd;
+    }
+}

+ 115 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/PictureUtils.java

@@ -0,0 +1,115 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+import android.media.ExifInterface;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Created by mengxy on 2017/10/26.
+ */
+
+public class PictureUtils {
+
+    public static String compressImage(String filePath, String targetPath, int quality) {
+        Bitmap bm = getSmallBitmap(filePath);//获取一定尺寸的图片
+        int degree = readPictureDegree(filePath);//获取相片拍摄角度
+        if (degree != 0) {//旋转照片角度,防止头像横着显示
+            bm = rotateBitmap(bm, degree);
+        }
+        File outputFile = new File(targetPath);
+        try {
+            if (!outputFile.exists()) {
+                outputFile.getParentFile().mkdirs();
+                //outputFile.createNewFile();
+            } else {
+                outputFile.delete();
+            }
+            FileOutputStream out = new FileOutputStream(outputFile);
+            bm.compress(Bitmap.CompressFormat.PNG, quality, out);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return outputFile.getPath();
+    }
+
+    /**
+     * 根据路径获得图片信息并按比例压缩,返回bitmap
+     */
+    public static Bitmap getSmallBitmap(String filePath) {
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inJustDecodeBounds = true;//只解析图片边沿,获取宽高
+        BitmapFactory.decodeFile(filePath, options);
+        // 计算缩放比
+        options.inSampleSize = calculateInSampleSize(options, 480, 800);
+        // 完整解析图片返回bitmap
+        options.inJustDecodeBounds = false;
+        return BitmapFactory.decodeFile(filePath, options);
+    }
+
+
+    /**
+     * 获取照片角度
+     *
+     * @param path
+     * @return
+     */
+    public static int readPictureDegree(String path) {
+        int degree = 0;
+        try {
+            ExifInterface exifInterface = new ExifInterface(path);
+            int orientation = exifInterface.getAttributeInt(
+                    ExifInterface.TAG_ORIENTATION,
+                    ExifInterface.ORIENTATION_NORMAL);
+            switch (orientation) {
+                case ExifInterface.ORIENTATION_ROTATE_90:
+                    degree = 90;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_180:
+                    degree = 180;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_270:
+                    degree = 270;
+                    break;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return degree;
+    }
+
+    /**
+     * 旋转照片
+     *
+     * @param bitmap
+     * @param degress
+     * @return
+     */
+    public static Bitmap rotateBitmap(Bitmap bitmap, int degress) {
+        if (bitmap != null) {
+            Matrix m = new Matrix();
+            m.postRotate(degress);
+            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
+                    bitmap.getHeight(), m, true);
+            return bitmap;
+        }
+        return bitmap;
+    }
+
+    public static int calculateInSampleSize(BitmapFactory.Options options,
+                                            int reqWidth, int reqHeight) {
+        final int height = options.outHeight;
+        final int width = options.outWidth;
+        int inSampleSize = 1;
+        if (height > reqHeight || width > reqWidth) {
+            final int heightRatio = Math.round((float) height / (float) reqHeight);
+            final int widthRatio = Math.round((float) width / (float) reqWidth);
+            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
+        }
+        return inSampleSize;
+    }
+}

+ 292 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/Repair_ImgSelActivity.java

@@ -0,0 +1,292 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.ContentValues;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.MediaStore;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+
+import com.yuyh.library.imgsel.ImgSelConfig;
+import com.yuyh.library.imgsel.R;
+import com.yuyh.library.imgsel.common.Callback;
+import com.yuyh.library.imgsel.common.Constant;
+import com.yuyh.library.imgsel.utils.FileUtils;
+import com.yuyh.library.imgsel.utils.StatusBarCompat;
+
+import java.io.File;
+import java.util.ArrayList;
+
+/**
+ * https://github.com/smuyyh/ImageSelector
+ * 选择相册图片列表通用页
+ *
+ * @author yuyh.
+ * @date 2016/8/5.
+ */
+public class Repair_ImgSelActivity extends FragmentActivity implements View.OnClickListener, Callback {
+
+    public static final String INTENT_RESULT = "result";
+    private static final int IMAGE_CROP_CODE = 1;
+    private static final int STORAGE_REQUEST_CODE = 1;
+
+    private ImgSelConfig config;
+
+    private RelativeLayout rlTitleBar;
+    private TextView tvTitle;
+    private Button btnConfirm;
+    private ImageView ivBack;
+    private String cropImagePath;
+
+    private Repair_ImgSelFragment fragment;
+
+    private ArrayList<String> result = new ArrayList<>();
+
+    public static void startActivity(Activity activity, ImgSelConfig config, int RequestCode) {
+        Intent intent = new Intent(activity, Repair_ImgSelActivity.class);
+        Constant.config = config;
+        activity.startActivityForResult(intent, RequestCode);
+    }
+
+    public static void startActivity(Fragment fragment, ImgSelConfig config, int RequestCode) {
+        Intent intent = new Intent(fragment.getActivity(), Repair_ImgSelActivity.class);
+        Constant.config = config;
+        fragment.startActivityForResult(intent, RequestCode);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_img_sel);
+        config = Constant.config;
+        // Android 6.0 checkSelfPermission
+        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
+                != PackageManager.PERMISSION_GRANTED) {
+            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+                    STORAGE_REQUEST_CODE);
+        } else {
+            fragment = Repair_ImgSelFragment.instance();
+            getSupportFragmentManager().beginTransaction()
+                    .add(R.id.fmImageList, fragment, null)
+                    .commit();
+        }
+
+        initView();
+        if (!FileUtils.isSdCardAvailable()) {
+            Toast.makeText(this, getString(R.string.sd_disable), Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    private void initView() {
+        rlTitleBar = (RelativeLayout) findViewById(R.id.rlTitleBar);
+        tvTitle = (TextView) findViewById(R.id.tvTitle);
+
+        btnConfirm = (Button) findViewById(R.id.btnConfirm);
+        btnConfirm.setOnClickListener(this);
+
+        ivBack = (ImageView) findViewById(R.id.ivBack);
+        ivBack.setOnClickListener(this);
+
+        if (config != null) {
+            if (config.backResId != -1) {
+                ivBack.setImageResource(config.backResId);
+            }
+
+            if (config.statusBarColor != -1) {
+                StatusBarCompat.compat(this, config.statusBarColor);
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
+                        && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+                    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+                    //getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+                }
+            }
+            rlTitleBar.setBackgroundColor(config.titleBgColor);
+            tvTitle.setTextColor(config.titleColor);
+            tvTitle.setText(config.title);
+            btnConfirm.setBackgroundColor(config.btnBgColor);
+            btnConfirm.setTextColor(config.btnTextColor);
+
+            if (config.multiSelect) {
+                if (!config.rememberSelected) {
+                    Constant.imageList.clear();
+                }
+                btnConfirm.setText(String.format(getString(R.string.confirm_format), config.btnText, Constant.imageList
+                        .size(), config.maxNum));
+            } else {
+                Constant.imageList.clear();
+                btnConfirm.setVisibility(View.GONE);
+            }
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        int id = v.getId();
+        if (id == R.id.btnConfirm) {
+            if (Constant.imageList != null && !Constant.imageList.isEmpty()) {
+                exit();
+            } else {
+                Toast.makeText(this, getString(R.string.minnum), Toast.LENGTH_SHORT).show();
+            }
+        } else if (id == R.id.ivBack) {
+            onBackPressed();
+        }
+    }
+
+    @Override
+    public void onSingleImageSelected(String path) {
+        if (config.needCrop) {
+            crop(path);
+        } else {
+            Constant.imageList.add(path);
+            exit();
+        }
+    }
+
+    @Override
+    public void onImageSelected(String path) {
+        btnConfirm.setText(String.format(getString(R.string.confirm_format), config.btnText, Constant.imageList.size(),
+                config.maxNum));
+    }
+
+    @Override
+    public void onImageUnselected(String path) {
+        btnConfirm.setText(String.format(getString(R.string.confirm_format), config.btnText, Constant.imageList.size(),
+                config.maxNum));
+    }
+
+    @Override
+    public void onCameraShot(File imageFile) {
+        if (imageFile != null) {
+            if (config.needCrop) {
+                crop(imageFile.getAbsolutePath());
+            } else {
+                Constant.imageList.add(imageFile.getAbsolutePath());
+                config.multiSelect = false; // 多选点击拍照,强制更改为单选
+                exit();
+            }
+        }
+    }
+
+    @Override
+    public void onPreviewChanged(int select, int sum, boolean visible) {
+        if (visible) {
+            tvTitle.setText(select + "/" + sum);
+        } else {
+            tvTitle.setText(config.title);
+        }
+    }
+
+    private void crop(String imagePath) {
+        File file = new File(FileUtils.createRootPath(this) + "/" + System.currentTimeMillis() + ".jpg");
+
+        cropImagePath = file.getAbsolutePath();
+        Intent intent = new Intent("com.android.camera.action.CROP");
+        intent.setDataAndType(getImageContentUri(new File(imagePath)), "image/*");
+        intent.putExtra("crop", "true");
+        intent.putExtra("aspectX", config.aspectX);
+        intent.putExtra("aspectY", config.aspectY);
+        intent.putExtra("outputX", config.outputX);
+        intent.putExtra("outputY", config.outputY);
+        intent.putExtra("scale", true);
+        intent.putExtra("return-data", false);
+        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
+        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
+        intent.putExtra("noFaceDetection", true);
+        startActivityForResult(intent, IMAGE_CROP_CODE);
+    }
+
+    public Uri getImageContentUri(File imageFile) {
+        String filePath = imageFile.getAbsolutePath();
+        Cursor cursor = getContentResolver().query(
+                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+                new String[]{MediaStore.Images.Media._ID},
+                MediaStore.Images.Media.DATA + "=? ",
+                new String[]{filePath}, null);
+
+        if (cursor != null && cursor.moveToFirst()) {
+            int id = cursor.getInt(cursor
+                    .getColumnIndex(MediaStore.MediaColumns._ID));
+            Uri baseUri = Uri.parse("content://media/external/images/media");
+            return Uri.withAppendedPath(baseUri, "" + id);
+        } else {
+            if (imageFile.exists()) {
+                ContentValues values = new ContentValues();
+                values.put(MediaStore.Images.Media.DATA, filePath);
+                return getContentResolver().insert(
+                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
+            } else {
+                return null;
+            }
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == IMAGE_CROP_CODE && resultCode == RESULT_OK) {
+            Constant.imageList.add(cropImagePath);
+            config.multiSelect = false; // 多选点击拍照,强制更改为单选
+            exit();
+        }
+        super.onActivityResult(requestCode, resultCode, data);
+    }
+
+    public void exit() {
+        Intent intent = new Intent();
+        result.clear();
+        result.addAll(Constant.imageList);
+        intent.putStringArrayListExtra(INTENT_RESULT, result);
+        setResult(RESULT_OK, intent);
+
+        if (!config.multiSelect) {
+            Constant.imageList.clear();
+        }
+
+        finish();
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+        switch (requestCode) {
+            case STORAGE_REQUEST_CODE:
+                if (grantResults.length >= 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+                    getSupportFragmentManager()
+                            .beginTransaction()
+                            .add(R.id.fmImageList, Repair_ImgSelFragment.instance(), null)
+                            .commitAllowingStateLoss();
+                } else {
+                    Toast.makeText(this, getString(R.string.permission_storage_denied), Toast.LENGTH_SHORT).show();
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    @Override
+    public void onBackPressed() {
+        if (fragment == null || !fragment.hidePreview()) {
+            Constant.imageList.clear();
+            super.onBackPressed();
+        }
+    }
+}

+ 460 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/Repair_ImgSelFragment.java

@@ -0,0 +1,460 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+/**
+ * 选择相册图片列表fragment通用页
+ * Created by cunwen on 17/9/5.
+ */
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.database.Cursor;
+import android.graphics.drawable.ColorDrawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.MediaStore;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.ListPopupWindow;
+import androidx.core.content.ContextCompat;
+import androidx.core.content.FileProvider;
+import androidx.fragment.app.Fragment;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.content.CursorLoader;
+import androidx.loader.content.Loader;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.viewpager.widget.ViewPager;
+
+import com.ys.bdtp.adm.R;
+import com.yuyh.library.imgsel.ImgSelConfig;
+import com.yuyh.library.imgsel.adapter.FolderListAdapter;
+import com.yuyh.library.imgsel.adapter.PreviewAdapter;
+import com.yuyh.library.imgsel.bean.Folder;
+import com.yuyh.library.imgsel.bean.Image;
+import com.yuyh.library.imgsel.common.Callback;
+import com.yuyh.library.imgsel.common.Constant;
+import com.yuyh.library.imgsel.common.OnFolderChangeListener;
+import com.yuyh.library.imgsel.common.OnItemClickListener;
+import com.yuyh.library.imgsel.utils.FileUtils;
+import com.yuyh.library.imgsel.utils.LogUtils;
+import com.yuyh.library.imgsel.widget.CustomViewPager;
+import com.yuyh.library.imgsel.widget.DividerGridItemDecoration;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class Repair_ImgSelFragment extends Fragment implements View.OnClickListener, ViewPager.OnPageChangeListener {
+
+    private RecyclerView rvImageList;
+    private Button btnAlbumSelected;
+    private View rlBottom;
+    private CustomViewPager viewPager;
+
+    private ImgSelConfig config;
+    private Callback callback;
+    private List<Folder> folderList = new ArrayList<>();
+    private List<Image> imageList = new ArrayList<>();
+
+    private ListPopupWindow folderPopupWindow;
+    private ImageListRVAdapter imageListAdapter;
+    private FolderListAdapter folderListAdapter;
+    private PreviewAdapter previewAdapter;
+
+    private boolean hasFolderGened = false;
+
+    private static final int LOADER_ALL = 0;
+    private static final int LOADER_CATEGORY = 1;
+    private static final int REQUEST_CAMERA = 5;
+
+    private static final int CAMERA_REQUEST_CODE = 1;
+
+    private File tempFile;
+
+    public static Repair_ImgSelFragment instance() {
+        Repair_ImgSelFragment fragment = new Repair_ImgSelFragment();
+        Bundle bundle = new Bundle();
+        fragment.setArguments(bundle);
+        return fragment;
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.common_fragment_img_sel, container, false);
+        rvImageList = (RecyclerView) view.findViewById(R.id.rvImageList);
+        btnAlbumSelected = (Button) view.findViewById(R.id.btnAlbumSelected);
+        btnAlbumSelected.setOnClickListener(this);
+        rlBottom = view.findViewById(R.id.rlBottom);
+        viewPager = (CustomViewPager) view.findViewById(R.id.viewPager);
+        viewPager.addOnPageChangeListener(this);
+        return view;
+    }
+
+    @Override
+    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        config = Constant.config;
+        try {
+            callback = (Callback) getActivity();
+        } catch (Exception e) {
+
+        }
+
+        btnAlbumSelected.setText(config.allImagesText);
+
+        rvImageList.setLayoutManager(new GridLayoutManager(rvImageList.getContext(), 3));
+        rvImageList.addItemDecoration(new DividerGridItemDecoration(rvImageList.getContext()));
+        if (config.needCamera)
+            imageList.add(new Image());
+
+        imageListAdapter = new ImageListRVAdapter(getActivity(), imageList, config);
+        imageListAdapter.setShowCamera(config.needCamera);
+        imageListAdapter.setMutiSelect(config.multiSelect);
+        rvImageList.setAdapter(imageListAdapter);
+        imageListAdapter.setOnItemClickListener(new OnItemClickListener() {
+            @Override
+            public int onCheckedClick(int position, Image image) {
+                return checkedImage(position, image);
+            }
+
+            @Override
+            public void onImageClick(int position, Image image) {
+                if (config.needCamera && position == 0) {
+                    showCameraAction();
+                } else {
+                    if (config.multiSelect) {
+                        viewPager.setAdapter((previewAdapter = new PreviewAdapter(getActivity(), imageList, config)));
+                        previewAdapter.setListener(new OnItemClickListener() {
+                            @Override
+                            public int onCheckedClick(int position, Image image) {
+                                return checkedImage(position, image);
+                            }
+
+                            @Override
+                            public void onImageClick(int position, Image image) {
+                                hidePreview();
+                            }
+                        });
+                        if (config.needCamera) {
+                            callback.onPreviewChanged(position, imageList.size() - 1, true);
+                        } else {
+                            callback.onPreviewChanged(position + 1, imageList.size(), true);
+                        }
+                        viewPager.setCurrentItem(config.needCamera ? position - 1 : position);
+                        viewPager.setVisibility(View.VISIBLE);
+                    } else {
+                        if (callback != null) {
+                            callback.onSingleImageSelected(image.path);
+                        }
+                    }
+                }
+            }
+        });
+
+        folderListAdapter = new FolderListAdapter(getActivity(), folderList, config);
+
+        getActivity().getSupportLoaderManager().initLoader(LOADER_ALL, null, mLoaderCallback);
+    }
+
+    private int checkedImage(int position, Image image) {
+        if (image != null) {
+            if (Constant.imageList.contains(image.path)) {
+                Constant.imageList.remove(image.path);
+                if (callback != null) {
+                    callback.onImageUnselected(image.path);
+                }
+            } else {
+                if (config.maxNum <= Constant.imageList.size()) {
+//                    Toast.makeText(getActivity(), String.format(getString(R.string.maxnum), config.maxNum), Toast.LENGTH_SHORT).show();
+//                    Toast.makeText(getActivity(), "哈哈", Toast.LENGTH_SHORT).show();
+
+                    MyDialogViewSingle dialog = new MyDialogViewSingle(getActivity()) {
+                        @Override
+                        protected void onBottomClick() {
+                            dismiss();
+                        }
+                    };
+                    dialog.show();
+                    dialog.setContentviewText(String.format(getString(R.string.maxnum), config.maxNum));
+                    dialog.setButtonviewText("我知道了");
+
+                    return 0;
+                }
+
+                Constant.imageList.add(image.path);
+                if (callback != null) {
+                    callback.onImageSelected(image.path);
+                }
+            }
+            return 1;
+        }
+        return 0;
+    }
+
+    private LoaderManager.LoaderCallbacks<Cursor> mLoaderCallback = new LoaderManager.LoaderCallbacks<Cursor>() {
+
+        private final String[] IMAGE_PROJECTION = {
+                MediaStore.Images.Media.DATA,
+                MediaStore.Images.Media.DISPLAY_NAME,
+                MediaStore.Images.Media.DATE_ADDED,
+                MediaStore.Images.Media._ID};
+
+        @Override
+        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+            if (id == LOADER_ALL) {
+                CursorLoader cursorLoader = new CursorLoader(getActivity(),
+                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION,
+                        null, null, IMAGE_PROJECTION[2] + " DESC");
+                return cursorLoader;
+            } else if (id == LOADER_CATEGORY) {
+                CursorLoader cursorLoader = new CursorLoader(getActivity(),
+                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION,
+                        IMAGE_PROJECTION[0] + " like '%" + args.getString("path") + "%'", null, IMAGE_PROJECTION[2] + " DESC");
+                return cursorLoader;
+            }
+            return null;
+        }
+
+        @Override
+        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+            if (data != null) {
+                int count = data.getCount();
+                if (count > 0) {
+                    List<Image> tempImageList = new ArrayList<>();
+                    data.moveToFirst();
+                    do {
+                        String path = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]));
+                        String name = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]));
+                        long dateTime = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]));
+                        Image image = new Image(path, name, dateTime);
+                        if (!image.path.endsWith("gif")) {
+                            File file = new File(path);
+                            if (file.exists()) {
+                                tempImageList.add(image);
+                            }
+                        }
+                        if (!hasFolderGened) {
+                            File imageFile = new File(path);
+                            File folderFile = imageFile.getParentFile();
+                            if (folderFile == null) {
+                                System.out.println(path);
+                                return;
+                            }
+                            Folder folder = new Folder();
+                            folder.name = folderFile.getName();
+                            folder.path = folderFile.getAbsolutePath();
+                            folder.cover = image;
+                            if (!folderList.contains(folder)) {
+                                List<Image> imageList = new ArrayList<>();
+                                imageList.add(image);
+                                folder.images = imageList;
+                                folderList.add(folder);
+                            } else {
+                                Folder f = folderList.get(folderList.indexOf(folder));
+                                f.images.add(image);
+                            }
+                        }
+
+                    } while (data.moveToNext());
+
+                    imageList.clear();
+                    if (config.needCamera) {
+                        imageList.add(new Image());
+                    }
+                    imageList.addAll(tempImageList);
+
+
+                    imageListAdapter.notifyDataSetChanged();
+
+                    if (Constant.imageList != null && Constant.imageList.size() > 0) {
+                        //imageListAdapter.setDefaultSelected(Constant.imageList);
+                    }
+
+                    folderListAdapter.notifyDataSetChanged();
+
+                    hasFolderGened = true;
+                }
+            }
+        }
+
+        @Override
+        public void onLoaderReset(Loader<Cursor> loader) {
+
+        }
+    };
+
+    private void createPopupFolderList(int width, int height) {
+        folderPopupWindow = new ListPopupWindow(getActivity());
+        folderPopupWindow.setBackgroundDrawable(getContext().getResources().getDrawable(R.color.gray_a6a6a6));
+        folderPopupWindow.setAdapter(folderListAdapter);
+        folderPopupWindow.setContentWidth(width);
+        folderPopupWindow.setWidth(width);
+        folderPopupWindow.setHeight(height);
+        folderPopupWindow.setAnchorView(rlBottom);
+        folderPopupWindow.setModal(true);
+        folderListAdapter.setOnFloderChangeListener(new OnFolderChangeListener() {
+            @Override
+            public void onChange(int position, Folder folder) {
+                folderPopupWindow.dismiss();
+                if (position == 0) {
+                    getActivity().getSupportLoaderManager().restartLoader(LOADER_ALL, null, mLoaderCallback);
+                    btnAlbumSelected.setText(config.allImagesText);
+                } else {
+                    imageList.clear();
+                    if (config.needCamera)
+                        imageList.add(new Image());
+                    imageList.addAll(folder.images);
+                    imageListAdapter.notifyDataSetChanged();
+
+                    btnAlbumSelected.setText(folder.name);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == btnAlbumSelected.getId()) {
+            if (folderPopupWindow == null) {
+                WindowManager wm = getActivity().getWindowManager();
+                int width = wm.getDefaultDisplay().getWidth();
+                createPopupFolderList(width / 3 * 2, width / 3 * 2);
+            }
+
+            if (folderPopupWindow.isShowing()) {
+                folderPopupWindow.dismiss();
+            } else {
+                folderPopupWindow.show();
+                if (folderPopupWindow.getListView() != null) {
+                    folderPopupWindow.getListView().setDivider(new ColorDrawable(ContextCompat.getColor(getActivity(), R.color.bottom_bg)));
+                }
+                int index = folderListAdapter.getSelectIndex();
+                index = index == 0 ? index : index - 1;
+                folderPopupWindow.getListView().setSelection(index);
+            }
+        }
+    }
+
+    private void showCameraAction() {
+
+        if (config.maxNum <= Constant.imageList.size()) {
+//            Toast.makeText(getActivity(), String.format(getString(R.string.maxnum), config.maxNum), Toast.LENGTH_SHORT).show();
+//            Toast.makeText(getActivity(), "哈哈", Toast.LENGTH_SHORT).show();
+            MyDialogViewSingle dialog = new MyDialogViewSingle(getActivity()) {
+                @Override
+                protected void onBottomClick() {
+                    dismiss();
+                }
+            };
+            dialog.show();
+            dialog.setContentviewText(String.format(getString(R.string.maxnum), config.maxNum));
+            dialog.setButtonviewText("我知道了");
+            return;
+        }
+
+        if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
+                != PackageManager.PERMISSION_GRANTED) {
+            requestPermissions(new String[]{Manifest.permission.CAMERA}, CAMERA_REQUEST_CODE);
+            return;
+        }
+
+        Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+
+        if (cameraIntent.resolveActivity(getActivity().getPackageManager()) != null) {
+            tempFile = new File(FileUtils.createRootPath(getActivity()) + "/" + System.currentTimeMillis() + ".jpg");
+            LogUtils.e(tempFile.getAbsolutePath());
+            FileUtils.createFile(tempFile);
+
+            Uri uri = FileProvider.getUriForFile(getActivity(),
+                    FileUtils.getApplicationId(getActivity()) + ".provider", tempFile);
+
+            List<ResolveInfo> resInfoList = getActivity().getPackageManager()
+                    .queryIntentActivities(cameraIntent, PackageManager.MATCH_DEFAULT_ONLY);
+            for (ResolveInfo resolveInfo : resInfoList) {
+                String packageName = resolveInfo.activityInfo.packageName;
+                getActivity().grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                        | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            }
+
+            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); //Uri.fromFile(tempFile)
+            startActivityForResult(cameraIntent, REQUEST_CAMERA);
+        } else {
+            Toast.makeText(getActivity(), getString(R.string.open_camera_failure), Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == REQUEST_CAMERA) {
+            if (resultCode == Activity.RESULT_OK) {
+                if (tempFile != null) {
+                    if (callback != null) {
+                        callback.onCameraShot(tempFile);
+                    }
+                }
+            } else {
+                if (tempFile != null && tempFile.exists()) {
+                    tempFile.delete();
+                }
+            }
+        }
+        super.onActivityResult(requestCode, resultCode, data);
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+        switch (requestCode) {
+            case CAMERA_REQUEST_CODE:
+                if (grantResults.length >= 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+                    showCameraAction();
+                } else {
+                    Toast.makeText(getActivity(), getString(R.string.permission_camera_denied), Toast.LENGTH_SHORT).show();
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    @Override
+    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+
+    }
+
+    @Override
+    public void onPageSelected(int position) {
+        if (config.needCamera) {
+            callback.onPreviewChanged(position + 1, imageList.size() - 1, true);
+        } else {
+            callback.onPreviewChanged(position + 1, imageList.size(), true);
+        }
+    }
+
+    @Override
+    public void onPageScrollStateChanged(int state) {
+
+    }
+
+    public boolean hidePreview() {
+        if (viewPager.getVisibility() == View.VISIBLE) {
+            viewPager.setVisibility(View.GONE);
+            callback.onPreviewChanged(0, 0, false);
+            imageListAdapter.notifyDataSetChanged();
+            return true;
+        } else {
+            return false;
+        }
+    }
+}

+ 393 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/SDCardHelper.java

@@ -0,0 +1,393 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Environment;
+import android.os.StatFs;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+
+public class SDCardHelper {
+
+    // 判断SD卡是否被挂载
+    public static boolean isSDCardMounted() {
+        // return Environment.getExternalStorageState().equals("mounted");
+        return Environment.getExternalStorageState().equals(
+                Environment.MEDIA_MOUNTED);
+    }
+
+    // 获取SD卡的根目录
+    public static String getSDCardBaseDir() {
+        if (isSDCardMounted()) {
+            return Environment.getExternalStorageDirectory().getAbsolutePath();
+        }
+        return "";
+    }
+
+    // 获取SD卡的完整空间大小,返回MB
+    public static long getSDCardSize() {
+        if (isSDCardMounted()) {
+            StatFs fs = new StatFs(getSDCardBaseDir());
+            int count = fs.getBlockCount();
+            int size = fs.getBlockSize();
+            return count * size / 1024 / 1024;
+        }
+        return 0;
+    }
+
+    // 获取SD卡的剩余空间大小
+    public static long getSDCardFreeSize() {
+        if (isSDCardMounted()) {
+            StatFs fs = new StatFs(getSDCardBaseDir());
+            int count = fs.getFreeBlocks();
+            int size = fs.getBlockSize();
+            return count * size / 1024 / 1024;
+        }
+        return 0;
+    }
+
+    // 获取SD卡的可用空间大小
+    public static long getSDCardAvailableSize() {
+        if (isSDCardMounted()) {
+            StatFs fs = new StatFs(getSDCardBaseDir());
+            int count = fs.getAvailableBlocks();
+            int size = fs.getBlockSize();
+            return count * size / 1024 / 1024;
+        }
+        return 0;
+    }
+
+    // 往SD卡的公有目录下保存文件
+    public static boolean saveFileToSDCardPublicDir(byte[] data, String type,
+                                                    String fileName) {
+        BufferedOutputStream bos = null;
+        if (isSDCardMounted()) {
+            File file = Environment.getExternalStoragePublicDirectory(type);
+            try {
+                bos = new BufferedOutputStream(new FileOutputStream(new File(
+                        file, fileName)));
+                bos.write(data);
+                bos.flush();
+                return true;
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    bos.close();
+                } catch (IOException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+            }
+        }
+        return false;
+    }
+
+    // 往SD卡的自定义目录下保存文件
+    public static boolean saveFileToSDCardCustomDir(byte[] data, String dir, String fileName) {
+        BufferedOutputStream bos = null;
+        if (isSDCardMounted()) {
+            File file = new File(getSDCardBaseDir() + File.separator + dir);
+            if (!file.exists()) {
+                file.mkdirs();// 递归创建自定义目录
+            }
+            try {
+                bos = new BufferedOutputStream(new FileOutputStream(new File(file, fileName)));
+                bos.write(data);
+                bos.flush();
+                return true;
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    if (null != bos) {
+                        bos.close();
+                    }
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return false;
+    }
+
+    public static boolean saveBitmap(String dirPath, String fileName, Bitmap bitmap) {
+        if (isSDCardMounted()) {
+            File file = new File(getSDCardBaseDir() + File.separator + dirPath);
+            if (!file.exists()) {
+                file.mkdirs();
+            }
+            File destFile = new File(file,fileName);
+            FileOutputStream out = null;
+            try {
+                out = new FileOutputStream(destFile);
+                bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
+                out.flush();
+                return true;
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    if (out != null) {
+                        out.close();
+                    }
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return false;
+    }
+
+    public static boolean saveFileToSDCardCustomDir(InputStream is, String fileDir, String fileName, long startsPoint, long contentLength) {
+        FileChannel channelOut = null;
+        // 随机访问文件,可以指定断点续传的起始位置
+        RandomAccessFile randomAccessFile = null;
+        if (isSDCardMounted()) {
+            File file = new File(getSDCardBaseDir() + File.separator + fileDir);
+            if (!file.exists()) {
+                file.mkdirs();// 递归创建自定义目录
+            }
+            File destination = new File(file, fileName);
+            try {
+                randomAccessFile = new RandomAccessFile(destination, "rwd");
+                //Chanel NIO中的用法,由于RandomAccessFile没有使用缓存策略,直接使用会使得下载速度变慢,亲测缓存下载3.3秒的文件,用普通的RandomAccessFile需要20多秒。
+                channelOut = randomAccessFile.getChannel();
+                // 内存映射,直接使用RandomAccessFile,是用其seek方法指定下载的起始位置,使用缓存下载,在这里指定下载位置。
+                MappedByteBuffer mappedBuffer = channelOut.map(FileChannel.MapMode.READ_WRITE, startsPoint, contentLength);
+                byte[] buffer = new byte[1024];
+                int len;
+                while ((len = is.read(buffer)) != -1) {
+                    mappedBuffer.put(buffer, 0, len);
+                }
+                return true;
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    is.close();
+                    if (channelOut != null) {
+                        channelOut.close();
+                    }
+                    if (randomAccessFile != null) {
+                        randomAccessFile.close();
+                    }
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return false;
+    }
+
+    // 往SD卡的私有Files目录下保存文件
+    public static boolean saveFileToSDCardPrivateFilesDir(byte[] data,
+                                                          String type, String fileName, Context context) {
+        BufferedOutputStream bos = null;
+        if (isSDCardMounted()) {
+            File file = context.getExternalFilesDir(type);
+            try {
+                bos = new BufferedOutputStream(new FileOutputStream(new File(
+                        file, fileName)));
+                bos.write(data);
+                bos.flush();
+                return true;
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    bos.close();
+                } catch (IOException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+            }
+        }
+        return false;
+    }
+
+    // 往SD卡的私有Cache目录下保存文件
+    public static boolean saveFileToSDCardPrivateCacheDir(byte[] data,
+                                                          String fileName, Context context) {
+        BufferedOutputStream bos = null;
+        if (isSDCardMounted()) {
+            File file = context.getExternalCacheDir();
+            try {
+                bos = new BufferedOutputStream(new FileOutputStream(new File(
+                        file, fileName)));
+                bos.write(data);
+                bos.flush();
+                return true;
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    bos.close();
+                } catch (IOException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+            }
+        }
+        return false;
+    }
+
+    // 保存bitmap图片到SDCard的私有Cache目录
+    public static boolean saveFileToSDCardPrivateCacheDir(Bitmap bitmap,
+                                                          String fileName, Context context) {
+        if (isSDCardMounted()) {
+            BufferedOutputStream bos = null;
+            // 获取私有的Cache缓存目录
+            File file = context.getExternalCacheDir();
+            try {
+                bos = new BufferedOutputStream(new FileOutputStream(new File(
+                        file, fileName)));
+                if (fileName != null
+                        && (fileName.contains(".png") || fileName
+                        .contains(".PNG"))) {
+                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
+                } else {
+                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
+                }
+                bos.flush();
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                if (bos != null) {
+                    try {
+                        bos.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    // 从SD卡获取文件
+    public static byte[] loadFileFromSDCard(String fileDir) {
+        BufferedInputStream bis = null;
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        try {
+            bis = new BufferedInputStream(
+                    new FileInputStream(new File(fileDir)));
+            byte[] buffer = new byte[8 * 1024];
+            int c = 0;
+            while ((c = bis.read(buffer)) != -1) {
+                baos.write(buffer, 0, c);
+                baos.flush();
+            }
+            return baos.toByteArray();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                baos.close();
+                bis.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+
+    // 从SDCard中寻找指定目录下的文件,返回Bitmap
+    public Bitmap loadBitmapFromSDCard(String filePath) {
+        byte[] data = loadFileFromSDCard(filePath);
+        if (data != null) {
+            Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);
+            if (bm != null) {
+                return bm;
+            }
+        }
+        return null;
+    }
+
+    // 获取SD卡公有目录的路径
+    public static String getSDCardPublicDir(String type) {
+        return Environment.getExternalStoragePublicDirectory(type).toString();
+    }
+
+    // 获取SD卡私有Cache目录的路径
+    public static String getSDCardPrivateCacheDir(Context context) {
+        return context.getExternalCacheDir().getAbsolutePath();
+    }
+
+    // 获取SD卡私有Files目录的路径
+    public static String getSDCardPrivateFilesDir(Context context, String type) {
+        return context.getExternalFilesDir(type).getAbsolutePath();
+    }
+
+    public static boolean isFileExist(String filePath) {
+        File file = new File(filePath);
+        return file.isFile();
+    }
+
+    // 从sdcard中删除文件
+    public static boolean removeFileFromSDCard(String filePath) {
+        File file = new File(filePath);
+        if (file.exists()) {
+            try {
+                file.delete();
+                return true;
+            } catch (Exception e) {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    public static File getFile(String dir, String fileName) {
+        if (isSDCardMounted()) {
+            File file = new File(getSDCardBaseDir() + File.separator + dir, fileName);
+            return file;
+        }
+        return null;
+    }
+
+    /**
+     * 文件转byte
+     * @param file
+     * @return
+     */
+    public static byte[] readFileToByte(File file) {
+        if (!file.exists()) {
+            return null;
+        }
+        RandomAccessFile rf = null;
+        byte[] data;
+        try {
+            rf = new RandomAccessFile(file, "r");
+            data = new byte[(int) rf.length()];
+            rf.readFully(data);
+        } catch (Exception exception) {
+            exception.printStackTrace();
+            return null;
+        } finally {
+            try {
+                if (rf != null) {
+                    rf.close();
+                }
+            } catch (Exception exception) {
+                exception.printStackTrace();
+            }
+        }
+        return data;
+    }
+}

+ 226 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/SelectListSinglePopupWindow.java

@@ -0,0 +1,226 @@
+package com.ys.bdtp.adm.mvvm.ui.examine;
+
+/**
+ * Created by cunwen on 16/3/25.
+ */
+
+import android.app.Activity;
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnTouchListener;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.animation.Animation;
+import android.view.inputmethod.EditorInfo;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
+import android.widget.TextView;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import com.ys.bdtp.adm.R;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+
+public class SelectListSinglePopupWindow extends PopupWindow {
+    DisplayMetrics dm;
+
+    private TextView title;
+    public TextView chooseSpace;
+    private Button btn1, btn_cancel;
+    private RecyclerView recyclerview;
+    private View mMenuView;
+
+    private Context context;
+    private static final long DISMISSDELAYED = 2000;
+
+    private Animation inAnim;
+    private Animation outAnim;
+
+    PersonalSelectSingleAdapter adapter;
+    public ArrayList<String> list = new ArrayList<String>();
+    public int position = -1;
+
+    public SelectListSinglePopupWindow(Context context) {
+        super(context);
+        this.context = context;
+
+        dm = new DisplayMetrics();
+        ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
+
+        LayoutInflater inflater = (LayoutInflater) context
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        mMenuView = inflater.inflate(R.layout.dialog_list_choice, null);
+        title = (TextView) mMenuView.findViewById(R.id.title);
+        btn1 = (Button) mMenuView.findViewById(R.id.btn1);
+        btn1.setVisibility(View.GONE);
+        btn_cancel = (Button) mMenuView.findViewById(R.id.btn_cancel);
+        chooseSpace = (TextView) mMenuView.findViewById(R.id.chooseSpace);
+        //取消按钮
+        btn_cancel.setOnClickListener(new OnClickListener() {
+
+            public void onClick(View v) {
+                //销毁弹出框
+                dismiss();
+                mMenuView.startAnimation(outAnim);
+            }
+        });
+        //设置按钮监听
+        btn1.setOnClickListener(view -> {
+            if (mOnItemClickListener != null) {
+                mOnItemClickListener.onItemClick(-1);
+            }
+            dismiss();
+        });
+        btn1.setTag(0);
+
+        recyclerview = (RecyclerView) mMenuView.findViewById(R.id.recyclerview);
+
+        recyclerview.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false));
+        recyclerview.setFocusable(false);
+        recyclerview.setVerticalScrollBarEnabled(true);
+        recyclerview.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
+        adapter = new PersonalSelectSingleAdapter();
+        adapter.setOnItemClickListener(new PersonalSelectSingleAdapter.OnRecyclerViewItemClickListener() {
+            @Override
+            public void onItemClick(View view, int position) {
+                if (mOnItemClickListener != null) {
+                    mOnItemClickListener.onItemClick(position);
+                }
+                dismiss();
+            }
+        });
+        recyclerview.setAdapter(adapter);
+
+        //设置SelectPicPopupWindow的View
+        this.setContentView(mMenuView);
+        //设置SelectPicPopupWindow弹出窗体的宽
+        this.setWidth(LayoutParams.MATCH_PARENT);
+        //设置SelectPicPopupWindow弹出窗体的高
+        this.setHeight(LayoutParams.WRAP_CONTENT);
+        //设置SelectPicPopupWindow弹出窗体可点击
+        this.setFocusable(true);
+        //设置SelectPicPopupWindow弹出窗体动画效果
+//        this.setAnimationStyle(R.style.AnimBottom);
+        //实例化一个ColorDrawable颜色为半透明
+//        ColorDrawable dw = new ColorDrawable(0xb0000000);
+        //设置SelectPicPopupWindow弹出窗体的背景
+
+        //mMenuView添加OnTouchListener监听判断获取触屏位置如果在选择框外面则销毁弹出框
+        mMenuView.setOnTouchListener(new OnTouchListener() {
+
+            public boolean onTouch(View v, MotionEvent event) {
+
+                int height = mMenuView.findViewById(R.id.pop_layout).getTop();
+                int y = (int) event.getY();
+                if (event.getAction() == MotionEvent.ACTION_UP) {
+                    if (y < height) {
+                        dismiss();
+                    }
+                }
+                return true;
+            }
+        });
+
+
+    }
+
+    public void setBtn(Boolean flag, String textBtn1) {
+        if (flag) {
+            btn1.setVisibility(View.VISIBLE);
+            btn1.setText(textBtn1);
+        } else {
+            btn1.setVisibility(View.GONE);
+        }
+    }
+
+    public void setBtnbottom(Boolean flag, String textBtn1) {
+        if (flag) {
+            btn_cancel.setVisibility(View.VISIBLE);
+            btn_cancel.setText(textBtn1);
+        } else {
+            btn_cancel.setVisibility(View.GONE);
+        }
+    }
+
+    public void setTitle(Boolean flag, String text) {
+        adapter.setFlag(flag);
+        if (flag) {
+            title.setVisibility(View.VISIBLE);
+            title.setText(text);
+            btn1.setGravity(Gravity.START);
+        } else {
+            title.setVisibility(View.GONE);
+            btn1.setGravity(Gravity.CENTER);
+        }
+    }
+
+    public void setGenList(List<?> list, String type) {
+        adapter.setItems(list, context, position, type);
+        LayoutParams mParams1 = recyclerview.getLayoutParams();
+        mParams1.height = (int) (55 * (list.size() >= 6 ? 6 : list.size()) * dm.density);
+        recyclerview.setLayoutParams(mParams1);
+        recyclerview.setVerticalScrollBarEnabled(true);
+        recyclerview.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
+        adapter.notifyDataSetChanged();
+    }
+
+    public void setChooseSpace(){
+        chooseSpace.setVisibility(View.VISIBLE);
+    }
+
+
+    private int gravity = Gravity.BOTTOM;
+
+
+    Animation.AnimationListener outAnimListener = new Animation.AnimationListener() {
+        @Override
+        public void onAnimationStart(Animation animation) {
+
+        }
+
+        @Override
+        public void onAnimationEnd(Animation animation) {
+            dismissImmediately();
+        }
+
+        @Override
+        public void onAnimationRepeat(Animation animation) {
+
+        }
+    };
+
+    public void dismissImmediately() {
+        dismiss();
+        context = null;
+    }
+
+
+    private OnRecyclerViewItemClickListener mOnItemClickListener = null;
+
+    public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
+        this.mOnItemClickListener = listener;
+    }
+
+    public void setRedText(int i) {
+        adapter.setRedText(i, true);
+    }
+
+    public interface OnRecyclerViewItemClickListener {
+        void onItemClick(int position);
+    }
+
+}

+ 380 - 109
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/examine/Space3DActivity.kt

@@ -1,44 +1,68 @@
 package com.ys.bdtp.adm.mvvm.ui.examine
 
+import android.Manifest
 import android.annotation.SuppressLint
 import android.content.Context
 import android.content.Intent
+import android.content.pm.PackageManager
+import android.graphics.Color
+import android.os.Build
 import android.os.Bundle
+import android.util.Log
 import android.view.View
 import android.webkit.JavascriptInterface
 import android.webkit.WebSettings
 import android.webkit.WebView
 import android.webkit.WebViewClient
-import android.widget.ImageView
-import android.widget.LinearLayout
-import android.widget.TextView
-import android.widget.Toast
-import androidx.activity.ComponentActivity
+import android.widget.*
+import androidx.annotation.RequiresApi
 import androidx.cardview.widget.CardView
+import androidx.core.app.ActivityCompat
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
 import com.google.gson.Gson
 import com.google.gson.reflect.TypeToken
+import com.sybotan.android.demo.adapter.ExpandAdapter
+import com.trello.rxlifecycle2.components.support.RxAppCompatActivity
 import com.ys.bdtp.adm.R
-import com.ys.bdtp.adm.mvvm.model.vo.Object
+import com.ys.bdtp.adm.mvvm.model.db.entity.config.ProblemInfoConfigEntity
+import com.ys.bdtp.adm.mvvm.model.db.entity.task.FloorEntity
 import com.ys.bdtp.adm.mvvm.model.vo.*
-import com.ys.bdtp.adm.mvvm.vm.offline.OfflineViewModel
+import com.ys.bdtp.adm.mvvm.ui.examine.LocalDataOperation.*
+import com.ys.bdtp.adm.mvvm.vm.examine.Space3DViewModel
+import com.yuyh.library.imgsel.ImageLoader
+import com.yuyh.library.imgsel.ImgSelConfig
+import io.reactivex.ObservableEmitter
 import org.kodein.di.DI
 import org.kodein.di.DIAware
 import org.kodein.di.android.closestDI
-import org.kodein.di.instance
+import org.kodein.di.android.x.viewmodel.viewModel
+import java.io.File
+import java.util.HashMap
 
-class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
+class Space3DActivity : RxAppCompatActivity(), DIAware, View.OnClickListener {
 
     override val di: DI by closestDI()
-    val vm by instance<OfflineViewModel>()
+    private val mVm: Space3DViewModel by viewModel()
     var isLastSpace = false
     var isLockCamera = false
     var meshObject: MeshObjectModel? = null
-    private lateinit var buildingId: String
-    private lateinit var floorId: String
+    var pointZModel: PointZ? = null
+    var lineModel: ArrayList<PointZ?>? = ArrayList()
+    var isClose = false
     private lateinit var projectId: String
     private var objTypeCode: String = ""
     private var problemTypeCode: String = ""
-    private lateinit var floorEntity: Object
+    private lateinit var floorEntity: FloorEntity
+    private var info: ProblemInfoConfigEntity? = null
+    private var currentPosition: Int? = 0
+    val beans: ArrayList<Photos> = ArrayList()
+
+    //选择图片
+    private val REQUEST_CODE_PIC = 0X102
+    private lateinit var adapter: InfoAdapter
+
     private lateinit var tv2d: TextView
     private lateinit var tv3d: TextView
     private lateinit var compass: TextView
@@ -62,6 +86,7 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
     private lateinit var quitTools: LinearLayout
     private lateinit var mapTools: LinearLayout
     private lateinit var cameraTypeTools: LinearLayout
+    private lateinit var reviseLl: LinearLayout
     private lateinit var point: TextView
     private lateinit var pline: TextView
     private lateinit var close: TextView
@@ -70,6 +95,8 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
     private lateinit var delete: TextView
     private lateinit var quit: TextView
     private lateinit var problemDone: TextView
+    private lateinit var projectName: TextView
+    private lateinit var signProblemTitle: TextView
 
     private lateinit var less: TextView
     private lateinit var more: TextView
@@ -81,12 +108,25 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
     private lateinit var floorslabLess: TextView
     private lateinit var plantHoleLess: TextView
     private lateinit var floorslabHeightError: TextView
+    private lateinit var saveProblem: TextView
+    private lateinit var detailClose: ImageView
+    private lateinit var detailContent: TextView
     private lateinit var signProblem: CardView
     private lateinit var closeProblem: ImageView
+    private lateinit var deleteProblem: ImageView
+    private lateinit var back: ImageView
+    private lateinit var infoRv: RecyclerView
+    private lateinit var expandLv: ExpandableListView
+    private lateinit var detailRl: RelativeLayout
 
     companion object {
         private lateinit var webview: WebView
 
+        private var FLOORINFO =
+            "{\"FloorElevation\":-5.5,\"FloorHeight\":5.5,\"FloorID\":\"Pj11010806656c41de285cd811ecbf08c3f8f21bae69B1\",\"PorjectID\":\"Pj1101080665\"}"
+
+        private var FLOORNAME = "京东科技大厦 负一层"
+
         /*lateinit var viewModel: Space3DVM*/
         val gson = Gson()
 
@@ -101,6 +141,7 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
         }
     }
 
+    @RequiresApi(Build.VERSION_CODES.R)
     @SuppressLint("SetJavaScriptEnabled")
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -109,7 +150,7 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
          buildingId = floor.getString("buildingId", "")
          floorId = floor.getString("floorId", "")
          projectId = floor.getString("projectId", "")*/
-        projectId = intent.getStringExtra("projectId") ?: ""
+        projectId = intent.getStringExtra("projectId") ?: "Pj1101080665"
         initView()
         webview.clearCache(true)
         WebView.setWebContentsDebuggingEnabled(true)
@@ -123,14 +164,18 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
             loadWithOverviewMode = true
             domStorageEnabled = true
             databaseEnabled = true
+            setSupportZoom(false)
+            setBuiltInZoomControls(false)
+            setUseWideViewPort(false)
             mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
         }
+        WebView.setWebContentsDebuggingEnabled(true)
         webview.addJavascriptInterface(this, "android")
         webview.webViewClient = MyWebViewClient()
         webview.loadUrl("http://60.205.177.43:8000/APP/")
+//        webview.loadUrl("http://60.205.177.43:8000/APP_1/#/")
+//        webview.loadUrl("http://172.16.5.17:8080/")
 //        webview.loadUrl("file:///android_asset/dist/index.html")
-
-
         /*viewModel = Space3DVM(this.application, { name, param ->
             when (name) {
                 Space3DVM.FLOOR_SPACE -> {
@@ -166,6 +211,44 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                 }
             }
         }, this, projectId, buildingId, floorId)*/
+        mVm.getBuildingFloor(projectId, success = { buildingList, floorList ->
+            val exAdapter = ExpandAdapter(this, buildingList, floorList)
+            for (floors in floorList) {
+                floors.sortByDescending { floor ->
+                    (gson.fromJson(
+                        floor.infos, InfosforFloor::class.java
+                    )).floorSequenceID
+                }
+                for (floor in floors) {
+                    if (floor.id == "Fl99099900021206b35236df4465845b9dae69ae45bf") {
+                        floorEntity = floor
+                    }
+                }
+            }
+            expandLv.setAdapter(exAdapter)
+            expandLv.setOnChildClickListener { parent, v, groupPosition, childPosition, id ->
+                floorEntity = floorList[groupPosition][childPosition]
+                projectName.text = "${buildingList[groupPosition].localName}  ${floorEntity.localName}"
+                FLOORNAME = "${buildingList[groupPosition].localName}  ${floorEntity.localName}"
+                expandLv.visibility = View.GONE
+                runOnUiThread {
+                    mVm.getFloorSpace(success = {
+//                        webview.loadUrl("javascript:SetSpaceData('${""}')")
+                        val floorInfo = gson.fromJson(floorEntity.infos, InfosforFloor::class.java)
+                        val model = SetFloorPathModel(
+                            projectId, floorInfo.bimIdPre, floorInfo.floorElevation, floorInfo.height
+                        )
+                        val toJson = gson.toJson(model)
+                        webview.loadUrl("javascript:SetFloorPath('${toJson}')")
+                        FLOORINFO = toJson
+                        chooseObject.performClick()
+
+                    })
+                }
+                true
+            }
+        })
+        checkStoragePermission()
     }
 
     private fun initView() {
@@ -216,7 +299,19 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
         floorslabHeightError = findViewById(R.id.floorslabHeightError)
         signProblem = findViewById(R.id.signProblem)
         closeProblem = findViewById(R.id.closeProblem)
-
+        infoRv = findViewById(R.id.infoRv)
+        expandLv = findViewById(R.id.expandLv)
+        expandLv.setGroupIndicator(null)
+        projectName = findViewById(R.id.projectName)
+        saveProblem = findViewById(R.id.saveProblem)
+        signProblemTitle = findViewById(R.id.signProblemTitle)
+        reviseLl = findViewById(R.id.reviseLl)
+        deleteProblem = findViewById(R.id.deleteProblem)
+        back = findViewById(R.id.back)
+        detailRl = findViewById(R.id.detailRl)
+        detailClose = findViewById(R.id.detailClose)
+        detailContent = findViewById(R.id.detailContent)
+        infoRv.layoutManager = LinearLayoutManager(this)
         less.setOnClickListener(this)
         more.setOnClickListener(this)
         materialError.setOnClickListener(this)
@@ -250,6 +345,12 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
         quit.setOnClickListener(this)
         closeProblem.setOnClickListener(this)
         save.setOnClickListener(this)
+        delete.setOnClickListener(this)
+        record.setOnClickListener(this)
+        projectName.setOnClickListener(this)
+        back.setOnClickListener(this)
+        saveProblem.setOnClickListener(this)
+        detailClose.setOnClickListener(this)
     }
 
 
@@ -259,21 +360,57 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
             forwardTools.visibility = View.GONE
             reverseTools.visibility = View.GONE
             meshObject = gson.fromJson(meshObjectString, MeshObjectModel::class.java)
-            Toast.makeText(this, meshObject!!.ID, Toast.LENGTH_LONG).show()
+            if (meshObject?.ID!!.contains("Door")) {
+                detailContent.text = "设备类型:CFCSDR普通门\nBimID:\n数字化交付编码:\n尺寸:900x2000mm\n材质:常规"
+            } else if (meshObject?.ID!!.contains("Window")) {
+                detailContent.text = "设备类型:CFCSWN普通窗\nBimID:\n数字化交付编码:\n尺寸:800x1600mm"
+            } else if (meshObject?.ID!!.contains("Column")) {
+                detailContent.text = "设备类型:CFCSCL柱\nBimID:\n数字化交付编码:\n尺寸:800x800mm"
+            }
+            detailRl.visibility = View.VISIBLE
+        }
+    }
+
+    @JavascriptInterface
+    fun OutMeshClick(meshObjectString: String) {
+        runOnUiThread {
+            forwardTools.visibility = View.GONE
+            reverseTools.visibility = View.GONE
+            meshObject = null
+            detailRl.visibility = View.GONE
+            signProblem.visibility = View.GONE
+//            Toast.makeText(this, meshObject!!.ID, Toast.LENGTH_LONG).show()
         }
     }
 
     @JavascriptInterface
     fun EndDrawPointModel(pointModel: String) {
         runOnUiThread {
-            val point = gson.fromJson(pointModel, PointZ::class.java)
+            val fromJson = gson.fromJson(pointModel, PointModel::class.java)
+            pointZModel = fromJson.Position
         }
     }
 
     @JavascriptInterface
     fun EndDrawLineModel(lineObject: String) {
         runOnUiThread {
-            val line = gson.fromJson<ArrayList<PointZ?>?>(lineObject, object : TypeToken<ArrayList<PointZ?>?>() {}.type)
+            lineModel = gson.fromJson(lineObject, LineObject::class.java).Points
+        }
+    }
+
+    @JavascriptInterface
+    fun TipViewClick(tipObjectString: String) {
+        runOnUiThread {
+//            Toast.makeText(this, tipObjectString, Toast.LENGTH_LONG).show()
+            val tipObject = gson.fromJson(tipObjectString, TipArray.Param()::class.java)
+            mVm.getProblemByObjId(tipObject, success = {
+                signProblem.visibility = View.VISIBLE
+                initShowInfo()
+                objTypeCode = it.objTypeCode
+                problemTypeCode = it.typeCode
+                val hashMap = gson.fromJson(it.info, HashMap::class.java) as HashMap<String, Any>
+                initInfo(hashMap)
+            })
         }
     }
 
@@ -282,24 +419,35 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
         val nameObject = gson.fromJson(name, FunctionEndBlockModel::class.java)
         when (nameObject.Name) {
             "OpenPage" -> {
+                /* runOnUiThread {
+                     webview.loadUrl("javascript:OpenTestData()")
+                 }*/
+                /*runOnUiThread {
+                    mVm.getFloorSpace(success = {
+                        webview.loadUrl("javascript:SetSpaceData('${""}')")
+                    })
+                }*/
                 runOnUiThread {
-                    webview.loadUrl("javascript:OpenTestData()")
+                    webview.loadUrl("javascript:SetFloorPath('${FLOORINFO}')")
+                    projectName.text = FLOORNAME
+                    chooseObject.performClick()
                 }
-                /*runOnUiThread { viewModel.getFloorSpace() }*/
             }
             "SetSpaceData" -> {
 //                if (isLastSpace) {
-//                    runOnUiThread {
-//                        val floorInfo = gson.fromJson(floorEntity.infos, InfosforFloor::class.java)
-//                        val model = SetFloorPathModel(projectId, floorInfo.bimIdPre, floorInfo.floorElevation)
-//                        webview.loadUrl("javascript:SetFloorPath('${gson.toJson(model)}')")
-//                    }
+                runOnUiThread {
+                    val floorInfo = gson.fromJson(floorEntity.infos, InfosforFloor::class.java)
+                    val model = SetFloorPathModel(
+                        projectId, floorInfo.bimIdPre, floorInfo.floorElevation, floorInfo.height
+                    )
+                    webview.loadUrl("javascript:SetFloorPath('${gson.toJson(model)}')")
+                }
 //                }
             }
             "SetFloorPath" -> {
-//                runOnUiThread {
-//                    webview.loadUrl("javascript:LoadAllModelWithFloor()")
-//                }
+                runOnUiThread {
+                    webview.loadUrl("javascript:LoadAllModelWithFloor()")
+                }
             }
             "OpenTestData" -> {
                 runOnUiThread {
@@ -307,6 +455,18 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
 
                 }
             }
+            "LoadAllModelWithFloor" -> {
+                runOnUiThread {
+                    Thread.sleep(500)
+                    mVm.getProblems(floorEntity.id, success = { s1, s2, lineArrayString ->
+                        webview.loadUrl("javascript:SetStyleWithMeshID('${s2}')")
+                        Thread.sleep(300)
+                        webview.loadUrl("javascript:ShowAllLine('${lineArrayString}')")
+                        Thread.sleep(300)
+                        webview.loadUrl("javascript:AddTipView('${s1}')")
+                    })
+                }
+            }
         }
     }
 
@@ -353,30 +513,21 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
             R.id.overall -> {
                 webview.loadUrl("javascript:LookAtAllFloorWidth2D()")
                 overall.setCompoundDrawablesWithIntrinsicBounds(
-                    null,
-                    resources.getDrawable(R.drawable.icon_overall_blue),
-                    null,
-                    null
+                    null, resources.getDrawable(R.drawable.icon_overall_blue), null, null
                 )
             }
             R.id.vertical -> {
                 webview.loadUrl("javascript:UpdateCameraAngle(${0})")
                 resetState()
                 vertical.setCompoundDrawablesWithIntrinsicBounds(
-                    null,
-                    resources.getDrawable(R.drawable.icon_vertical_blue),
-                    null,
-                    null
+                    null, resources.getDrawable(R.drawable.icon_vertical_blue), null, null
                 )
             }
             R.id.degree -> {
                 webview.loadUrl("javascript:UpdateCameraAngle(${1})")
                 resetState()
                 degree.setCompoundDrawablesWithIntrinsicBounds(
-                    null,
-                    resources.getDrawable(R.drawable.icon_degree_blue),
-                    null,
-                    null
+                    null, resources.getDrawable(R.drawable.icon_degree_blue), null, null
                 )
             }
             R.id.lock -> {
@@ -394,10 +545,7 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                 resetState()
                 webview.loadUrl("javascript:IsFirstCamera(${true})")
                 angle.setCompoundDrawablesWithIntrinsicBounds(
-                    null,
-                    resources.getDrawable(R.drawable.icon_angle_blue),
-                    null,
-                    null
+                    null, resources.getDrawable(R.drawable.icon_angle_blue), null, null
                 )
             }
             R.id.chooseObject -> {
@@ -424,10 +572,7 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                 materialError.visibility = View.VISIBLE
                 pline.visibility = View.VISIBLE
                 pline.setCompoundDrawablesWithIntrinsicBounds(
-                    null,
-                    resources.getDrawable(R.drawable.icon_pline_blue),
-                    null,
-                    null
+                    null, resources.getDrawable(R.drawable.icon_pline_blue), null, null
                 )
                 resetReverseTools()
                 wall.setTextColor(getColor(R.color.blue_0091FF))
@@ -440,14 +585,12 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                 resetDrawTools()
                 webview.loadUrl("javascript:InDrawPointModel()")
                 point.visibility = View.VISIBLE
+                save.visibility = View.GONE
                 point.setCompoundDrawablesWithIntrinsicBounds(
-                    null,
-                    resources.getDrawable(R.drawable.icon_point_blue),
-                    null,
-                    null
+                    null, resources.getDrawable(R.drawable.icon_point_blue), null, null
                 )
-                door.setTextColor(getColor(R.color.blue_0091FF))
-                door.background = getDrawable(R.drawable.bg_blue_e1f2ff_round)
+//                door.setTextColor(getColor(R.color.blue_0091FF))
+//                door.background = getDrawable(R.drawable.bg_blue_e1f2ff_round)
             }
             R.id.pillar -> {
                 objTypeCode = "CFCSCL"
@@ -456,11 +599,9 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                 resetDrawTools()
                 webview.loadUrl("javascript:InDrawPointModel()")
                 point.visibility = View.VISIBLE
+                save.visibility = View.GONE
                 point.setCompoundDrawablesWithIntrinsicBounds(
-                    null,
-                    resources.getDrawable(R.drawable.icon_point_blue),
-                    null,
-                    null
+                    null, resources.getDrawable(R.drawable.icon_point_blue), null, null
                 )
                 pillar.setTextColor(getColor(R.color.blue_0091FF))
                 pillar.background = getDrawable(R.drawable.bg_blue_e1f2ff_round)
@@ -472,11 +613,9 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                 resetDrawTools()
                 webview.loadUrl("javascript:InDrawPointModel()")
                 point.visibility = View.VISIBLE
+                save.visibility = View.GONE
                 point.setCompoundDrawablesWithIntrinsicBounds(
-                    null,
-                    resources.getDrawable(R.drawable.icon_point_blue),
-                    null,
-                    null
+                    null, resources.getDrawable(R.drawable.icon_point_blue), null, null
                 )
                 window.setTextColor(getColor(R.color.blue_0091FF))
                 window.background = getDrawable(R.drawable.bg_blue_e1f2ff_round)
@@ -487,11 +626,9 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                 resetDrawTools()
                 webview.loadUrl("javascript:InDrawPointModel()")
                 point.visibility = View.VISIBLE
+                save.visibility = View.GONE
                 point.setCompoundDrawablesWithIntrinsicBounds(
-                    null,
-                    resources.getDrawable(R.drawable.icon_point_blue),
-                    null,
-                    null
+                    null, resources.getDrawable(R.drawable.icon_point_blue), null, null
                 )
                 parking.setTextColor(getColor(R.color.blue_0091FF))
                 parking.background = getDrawable(R.drawable.bg_blue_e1f2ff_round)
@@ -507,6 +644,8 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                 floorslab.background = getDrawable(R.drawable.bg_blue_e1f2ff_round)
             }
             R.id.addProblem -> {
+                pointZModel = null
+                lineModel = null
                 if (reverseTools.visibility == View.VISIBLE || forwardTools.visibility == View.VISIBLE) {
                     forwardTools.visibility = View.GONE
                     reverseTools.visibility = View.GONE
@@ -525,7 +664,7 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                         } else if (meshObject?.ID!!.contains("Door")) {
                             objTypeCode = "CFBEDR"
                             more.visibility = View.VISIBLE
-                            materialError.visibility = View.VISIBLE
+                            propertyError.visibility = View.VISIBLE
                             positionError.visibility = View.VISIBLE
                         } else if (meshObject?.ID!!.contains("Window")) {
                             objTypeCode = "CFBEWN"
@@ -549,10 +688,11 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                 drawTools.visibility = View.GONE
                 quitTools.visibility = View.GONE
                 problemDone.visibility = View.GONE
-                cameraTypeTools.visibility = View.VISIBLE
+//                cameraTypeTools.visibility = View.VISIBLE
                 mapTools.visibility = View.VISIBLE
                 webview.loadUrl("javascript:UpdateCameraType(${1})")
                 resetReverseTools()
+                isClose = false
             }
             R.id.problemDone -> {
                 //TODO save
@@ -563,14 +703,19 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
             }
             R.id.save -> {
                 if (problemTypeCode == "CFCSWL_MORE" || problemTypeCode == "CFCSWL_MATERIAL_ERROR" || objTypeCode == "CFCSFL") {
-//                    val lineStyleModel = LineStyleModel("#ff0000", true)
                     val lineStyleModel = "{'Color':'#ff0000', 'IsLoop':'true'}"
-                    webview.loadUrl("javascript:SetDrawLineModel(${lineStyleModel})")
+                    webview.loadUrl("javascript:SetDrawLineModel(${"{'Color':'#ff0000', 'IsLoop':'true'}"})")
+                    isClose = true
+//                    Thread.sleep(300)
+//                    webview.loadUrl("javascript:OutDrawLineModel()")
+                    Thread.sleep(300)
+                    webview.loadUrl("javascript:EndDrawLineModel()")
+                } else if (problemTypeCode == "CFCSWL_LESS") {
+                    webview.loadUrl("javascript:EndDrawLineModel()")
+                } else {
+                    webview.loadUrl("javascript:OutDrawPointModel()")
+                    webview.loadUrl("javascript:EndDrawPointModel()")
                 }
-//                webview.loadUrl("javascript:OutDrawPointModel()")
-//                webview.loadUrl("javascript:OutDrawLineModel()")
-//                webview.loadUrl("javascript:EndDrawPointModel()")
-//                webview.loadUrl("javascript:EndDrawLineModel()")
             }
             //缺少
             R.id.less -> {
@@ -595,28 +740,32 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                     //柱子
                     "CFCSCL" -> {
                         problemTypeCode = "CFCSCL_MORE"
-                        signProblem.visibility = View.VISIBLE
+                        initAddProblem()
+                        initInfo(null)
                         addProblem.visibility = View.GONE
                         forwardTools.visibility = View.GONE
                     }
                     //门
                     "CFBEDR" -> {
                         problemTypeCode = "CFBEDR_MORE"
-                        signProblem.visibility = View.VISIBLE
+                        initAddProblem()
+                        initInfo(null)
                         addProblem.visibility = View.GONE
                         forwardTools.visibility = View.GONE
                     }
                     //窗
                     "CFBEWN" -> {
                         problemTypeCode = "CFBEWN_MORE"
-                        signProblem.visibility = View.VISIBLE
+                        initAddProblem()
+                        initInfo(null)
                         addProblem.visibility = View.GONE
                         forwardTools.visibility = View.GONE
                     }
                     //停车位
                     "CFPKPS" -> {
                         problemTypeCode = "CFPKPS_MORE"
-                        signProblem.visibility = View.VISIBLE
+                        initAddProblem()
+                        initInfo(null)
                         addProblem.visibility = View.GONE
                         forwardTools.visibility = View.GONE
                     }
@@ -642,14 +791,17 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                     }
 
                 }
+                initAddProblem()
+                initInfo(null)
+                addProblem.visibility = View.GONE
+                forwardTools.visibility = View.GONE
                 resetForwardTools()
-                propertyError.setTextColor(getColor(R.color.blue_0091FF))
-                propertyError.background = getDrawable(R.drawable.bg_blue_e1f2ff_round)
             }
             //截面形状错误
             R.id.crossSectionError -> {
                 problemTypeCode = "CFCSCL_SECTION_SHAPE_ERROR"
-                signProblem.visibility = View.VISIBLE
+                initAddProblem()
+                initInfo(null)
                 addProblem.visibility = View.GONE
                 forwardTools.visibility = View.GONE
             }
@@ -660,7 +812,8 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                         problemTypeCode = "CFCSCL_SIZE_ERROR"
                     }
                 }
-                signProblem.visibility = View.VISIBLE
+                initAddProblem()
+                initInfo(null)
                 addProblem.visibility = View.GONE
                 forwardTools.visibility = View.GONE
             }
@@ -678,6 +831,10 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
 
                 }
                 resetForwardTools()
+                initAddProblem()
+                initInfo(null)
+                addProblem.visibility = View.GONE
+                forwardTools.visibility = View.GONE
                 positionError.setTextColor(getColor(R.color.blue_0091FF))
                 positionError.background = getDrawable(R.drawable.bg_blue_e1f2ff_round)
             }
@@ -703,19 +860,29 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
                 resetForwardTools()
             }
             R.id.record -> {
-                signProblem.visibility = View.VISIBLE
+                webview.loadUrl("javascript:EndDrawPointModel()")
+                initAddProblem()
+                initInfo(null)
             }
             R.id.closeProblem -> {
-                signProblem.visibility = View.GONE
-                addProblem.visibility = View.VISIBLE
-                drawTools.visibility = View.GONE
-                quitTools.visibility = View.GONE
-                problemDone.visibility = View.GONE
-                cameraTypeTools.visibility = View.VISIBLE
-                mapTools.visibility = View.VISIBLE
+                refresh3DView()
+                isClose = false
             }
 
-        }
+    private fun initInfo(hashMap: HashMap<String, Any>?) {
+        mVm.getProblemConfig(problemTypeCode, success = {
+            adapter = InfoAdapter(this, it)
+            infoRv.adapter = adapter
+            if (hashMap != null) {
+                adapter.hashMap = hashMap
+                adapter.isDetail = true
+            }
+            adapter.setOnAddPic { info, currentPosition ->
+                addPic()
+                this@Space3DActivity.info = info
+                this@Space3DActivity.currentPosition = currentPosition
+            }
+        })
     }
 
     private fun resetReverseTools() {
@@ -744,23 +911,14 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
 
     private fun resetState() {
         vertical.setCompoundDrawablesWithIntrinsicBounds(
-            null,
-            resources.getDrawable(R.drawable.icon_vertical),
-            null,
-            null
+            null, resources.getDrawable(R.drawable.icon_vertical), null, null
         )
         degree.setCompoundDrawablesWithIntrinsicBounds(
-            null,
-            resources.getDrawable(R.drawable.icon_degree),
-            null,
-            null
+            null, resources.getDrawable(R.drawable.icon_degree), null, null
         )
 //        lock.setCompoundDrawablesWithIntrinsicBounds(null, resources.getDrawable(R.drawable.icon_lock), null, null)
         angle.setCompoundDrawablesWithIntrinsicBounds(
-            null,
-            resources.getDrawable(R.drawable.icon_angle),
-            null,
-            null
+            null, resources.getDrawable(R.drawable.icon_angle), null, null
         )
         webview.loadUrl("javascript:IsFirstCamera(${false})")
     }
@@ -772,10 +930,7 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
         lock.visibility = View.VISIBLE
         angle.visibility = View.VISIBLE
         overall.setCompoundDrawablesWithIntrinsicBounds(
-            null,
-            resources.getDrawable(R.drawable.icon_overall_white),
-            null,
-            null
+            null, resources.getDrawable(R.drawable.icon_overall_white), null, null
         )
     }
 
@@ -808,6 +963,7 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
         forwardTools.visibility = View.GONE
         reverseTools.visibility = View.GONE
         point.visibility = View.GONE
+        save.visibility = View.VISIBLE
         pline.visibility = View.GONE
         close.visibility = View.GONE
         cameraTypeTools.visibility = View.GONE
@@ -816,4 +972,119 @@ class Space3DActivity : ComponentActivity(), DIAware, View.OnClickListener {
         quitTools.visibility = View.VISIBLE
         problemDone.visibility = View.VISIBLE
     }
+
+    // 自定义图片加载器
+    private val loader = ImageLoader { context: Context?, path: String?, imageView: ImageView? ->
+        Glide.with(
+            context
+        ).load(path).into(imageView)
+    }
+
+    private fun addPic() {
+        val config: ImgSelConfig = ImgSelConfig.Builder(this, loader) // 是否多选
+            .multiSelect(true) // 是否记住上次选中记录, 仅当multiSelect为true的时候配置,默认为true
+            .rememberSelected(false) // 确定按钮文字颜色
+            .btnTextColor(Color.WHITE) // 使用沉浸式状态栏
+            .statusBarColor(resources.getColor(R.color.blue_2E3679)) // 返回图标ResId
+            .backResId(R.drawable.icon_back).title("选择图片").titleColor(Color.WHITE).titleBgColor(
+                resources.getColor(R.color.blue_2E3679)
+            ) //                .allImagesText("All Images")
+            .needCrop(false).cropSize(1, 1, 200, 200) // 第一个是否显示相机
+            .needCamera(true) // 最大选择图片数量
+            .maxNum(3).build()
+        //选择图片activity
+        //选择图片activity
+        Repair_ImgSelActivity.startActivity(this, config, REQUEST_CODE_PIC)
+    }
+
+    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+        super.onActivityResult(requestCode, resultCode, data)
+        if (resultCode == RESULT_OK && requestCode == REQUEST_CODE_PIC) {
+            if (data != null) {
+                val pathList: List<String>? = data.getStringArrayListExtra(Repair_ImgSelActivity.INTENT_RESULT)
+                doPicDatas(pathList)
+            }
+        }
+    }
+
+    private fun doPicDatas(pathList: List<String>?) {
+        getInstance().dealLocalData<Photos>(this) { name, params ->
+            when (name) {
+                SHOW_DIALOG_IN_MAIN -> {
+                    //ToastUtils.showMyToast("图片上传中")
+                }
+                DEAL_IO_DATA -> {
+                    val emitter = params as ObservableEmitter<String>
+                    for (s in pathList!!) {
+                        Log.e("已选择图片的路径为-----", s!!)
+                        val path: String = PictureUtils.compressImage(s, getOfflineImagePath(), 100)
+                        val picFile = File(path)
+                        if (picFile.exists()) {
+                            val key = picFile.name
+
+                            val photos = Photos()
+                            photos.itemType = 0
+                            photos.path = path
+                            photos.key = key
+                            if (info == null) {
+                                beans.add(photos)
+                            } else {
+                                val photosList = ArrayList<Photos>()
+                                if (adapter.hashMap[info!!.code] != null) {
+                                    val value = Gson().fromJson<ArrayList<Photos>>(
+                                        Gson().toJson(adapter.hashMap[info!!.code]),
+                                        object : TypeToken<List<Photos?>?>() {}.type
+                                    )
+                                    photosList.addAll(value)
+                                }
+                                photosList.add(photos)
+                                adapter.hashMap.put(info!!.code, photosList)
+                                adapter.valueList.remove(info?.code)
+                                runOnUiThread { adapter.notifyItemChanged(currentPosition!!) }
+                            }
+
+                        }
+                    }
+                    emitter.onNext("")
+                }
+                DEAL_DATA_NEXT -> {
+//                    ToastUtils.showMyToast("图片上传完毕")
+//                    if (info != null) {
+//                        staticInfoAdapter.hashMap.put(info.code, beans)
+//                    }
+                }
+                DEAL_DATA_ERROR -> {
+//                    ToastUtils.showMyToast("图片上传失败")
+                }
+                else -> {
+                }
+            }
+        }
+    }
+
+    /**
+     * 获取图片路径-离线缓存模块的图片存储
+     */
+    fun getOfflineImagePath(): String? {
+        val saveDir = getInstance().getOfflineImageFilePath(this)
+        // 新建目录
+        val dir = File(saveDir)
+        if (!dir.exists()) dir.mkdirs()
+        return saveDir + File.separator + System.currentTimeMillis() + ".png"
+    }
+
+    @RequiresApi(Build.VERSION_CODES.R)
+    private fun checkStoragePermission() {
+        if (ActivityCompat.checkSelfPermission(
+                this, Manifest.permission.WRITE_EXTERNAL_STORAGE
+            ) != PackageManager.PERMISSION_GRANTED
+        ) {
+            ActivityCompat.requestPermissions(
+                this, arrayOf(
+                    Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.MANAGE_EXTERNAL_STORAGE
+                ), 1
+            )
+        }
+    }
+
 }

+ 52 - 1
app/src/main/java/com/ys/bdtp/adm/mvvm/vm/examine/Space3DRepository.kt

@@ -1,5 +1,56 @@
 package com.ys.bdtp.adm.mvvm.vm.examine
 
+import com.ys.bdtp.adm.mvvm.model.db.AdmDatabase
+import com.ys.bdtp.adm.mvvm.model.db.entity.config.ProblemInfoConfigEntity
+import com.ys.bdtp.adm.mvvm.model.db.entity.config.ProblemTypeConfigEntity
+import com.ys.bdtp.adm.mvvm.model.db.entity.task.BuildingEntity
+import com.ys.bdtp.adm.mvvm.model.db.entity.task.FloorEntity
+import com.ys.bdtp.adm.mvvm.model.db.entity.task.ProblemEntity
 import com.ys.bdtp.adm.mvvm.model.nt.Api
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
 
-class Space3DRepository(private val api: Api)
+class Space3DRepository(private val api: Api, private val db: AdmDatabase) {
+
+    suspend fun getProblemInfo(problemTypeCode: String): List<ProblemInfoConfigEntity>? {
+        return withContext(Dispatchers.IO) {
+            db.problemInfoConfigDao().getProblemInfoByTypeCode(problemTypeCode)
+        }
+    }
+
+    suspend fun getBuilding(projectId: String): List<BuildingEntity>? {
+        return withContext(Dispatchers.IO) {
+            db.buildingDao().getBuildingByProjectId(projectId)
+        }
+    }
+
+    suspend fun getFloors(buildingId: String): List<FloorEntity>? {
+        return withContext(Dispatchers.IO) {
+            db.floorDao().getFloorsByBuildingId(buildingId)
+        }
+    }
+
+    suspend fun insProblem(entity: ProblemEntity) {
+        return withContext(Dispatchers.IO) {
+            db.problemDao().insProblem(entity)
+        }
+    }
+
+    suspend fun getProblemsByFloorId(floorId: String): List<ProblemEntity> {
+        return withContext(Dispatchers.IO) {
+            db.problemDao().getProblemsByFloorId(floorId)
+        }
+    }
+
+    suspend fun getProblemsTypeInfoByTypeCode(typeCode: String): ProblemTypeConfigEntity? {
+        return withContext(Dispatchers.IO) {
+            db.problemTypeConfigDao().getProblemsTypeInfoByTypeCode(typeCode)
+        }
+    }
+
+    suspend fun getProblemByObjId(id: String): ProblemEntity {
+        return withContext(Dispatchers.IO) {
+            db.problemDao().getProblemByObjId(id)
+        }
+    }
+}

+ 214 - 1
app/src/main/java/com/ys/bdtp/adm/mvvm/vm/examine/Space3DViewModel.kt

@@ -1,5 +1,218 @@
 package com.ys.bdtp.adm.mvvm.vm.examine
 
+import android.text.TextUtils
 import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import cn.hutool.core.util.IdUtil
+import com.google.gson.Gson
+import com.google.gson.internal.LinkedTreeMap
+import com.ys.bdtp.adm.mvvm.model.db.entity.config.ProblemInfoConfigEntity
+import com.ys.bdtp.adm.mvvm.model.db.entity.task.BuildingEntity
+import com.ys.bdtp.adm.mvvm.model.db.entity.task.FloorEntity
+import com.ys.bdtp.adm.mvvm.model.db.entity.task.ProblemEntity
+import com.ys.bdtp.adm.mvvm.model.db.entity.task.SpaceEntity
+import com.ys.bdtp.adm.mvvm.model.vo.*
+import com.ys.bdtp.adm.mvvm.ui.examine.Space3DActivity
+import kotlinx.coroutines.launch
+import java.io.File
+import java.util.HashMap
 
-class Space3DViewModel(private val repo: Space3DRepository) : ViewModel()
+
+class Space3DViewModel(private val repo: Space3DRepository) : ViewModel() {
+
+    val gson = Gson()
+    fun getProblemConfig(
+        problemTypeCode: String,
+        success: (List<ProblemInfoConfigEntity>) -> Unit
+    ) {
+        viewModelScope.launch {
+            val problemInfos = repo.getProblemInfo(problemTypeCode)
+            problemInfos?.let { success(it) }
+        }
+    }
+
+    fun getBuildingFloor(
+        projectId: String,
+        success: (List<BuildingEntity>, ArrayList<ArrayList<FloorEntity>>) -> Unit
+    ) {
+        viewModelScope.launch {
+            val buildingList = ArrayList<BuildingEntity>()
+            val floorList = ArrayList<ArrayList<FloorEntity>>()
+            val buildings = repo.getBuilding(projectId)
+//            buildingList.addAll(buildings)
+            for (building in buildings!!) {
+                var floors = repo.getFloors(building.id)
+                var sortFloors = ArrayList<FloorEntity>()
+//                for (floor in floors!!) {
+//                    val floorSequenceID = (gson.fromJson(
+//                        floor.infos,
+//                        InfosforFloor::class.java
+//                    )).floorSequenceID
+//                    for (sortFl in sortFloors) {
+//                        val sortFlSequenceID = (gson.fromJson(
+//                            sortFl.infos,
+//                            InfosforFloor::class.java
+//                        )).floorSequenceID
+//                        if (floorSequenceID < sortFlSequenceID) {
+//
+//                        }
+//                    }
+//                }
+
+                floors!!.sortedByDescending { floor ->
+                    (gson.fromJson(
+                        floor.infos,
+                        InfosforFloor::class.java
+                    )).floorSequenceID
+                }
+                if (isNull(floors)) {
+                    floorList.add(ArrayList<FloorEntity>())
+                } else {
+                    floorList.add(floors!! as ArrayList<FloorEntity>)
+                }
+            }
+            success(buildings, floorList)
+        }
+    }
+
+
+    fun isNull(`object`: Any?): Boolean {
+        if (null == `object`) {
+            return true
+        } else {
+            if (`object` is String) {
+                if (TextUtils.isEmpty(`object` as String?)) {
+                    return true
+                }
+            } else if (`object` is List<*>) {
+                if (`object`.size <= 0) {
+                    return true
+                }
+            } else if (`object` is Map<*, *>) {
+                if (`object`.size <= 0) {
+                    return true
+                }
+            } else if (`object` is Set<*>) {
+                if (`object`.size <= 0) {
+                    return true
+                }
+            }
+        }
+        return false
+    }
+
+    fun getFloorSpace(success: (List<SpaceEntity>) -> Unit) {
+        success(ArrayList())
+    }
+
+    fun fileUpload(param: MutableMap<String, String>, file: File) {
+
+    }
+
+    fun insProblem(
+        objTypeCode: String,
+        problemTypeCode: String,
+        meshObject: MeshObjectModel?,
+        buildingId: String,
+        floorId: String,
+        hashMap: HashMap<String, Any>,
+        pointZModel: PointZ?,
+        lineModel: ArrayList<PointZ?>?,
+        isClose: Boolean,
+        projectId: String,
+        success: () -> Unit
+    ) {
+        viewModelScope.launch {
+            if (meshObject != null) {
+                hashMap["position"] = meshObject.CenterPosition
+            } else if (pointZModel != null) {
+                hashMap["position"] = pointZModel
+            } else if (lineModel != null) {
+                hashMap["position"] = lineModel
+            }
+            hashMap["isClose"] = isClose
+            val problemTypeEntity = repo.getProblemsTypeInfoByTypeCode(problemTypeCode)
+            val uuid = IdUtil.simpleUUID()
+            val entity = ProblemEntity(
+                id = uuid,
+                groupCode = null,
+                projectId = projectId,
+                buildingId = buildingId,
+                floorId = floorId,
+                fileId = "",
+                checkType = 2,
+                objTypeCode = objTypeCode,
+                objTypeName = problemTypeEntity!!.objTypeName!!,
+                objId = meshObject?.ID ?: uuid,
+                objName = "",
+                typeCode = problemTypeCode,
+                typeName = problemTypeEntity.problemTypeName!!,
+                info = gson.toJsonTree(hashMap),
+                status = 1,
+                valid = 1,
+                creator = "",
+                creationTime = "",
+                modifier = "",
+                modifiedTime = "",
+                ts = 0
+            )
+            repo.insProblem(entity)
+            success()
+        }
+    }
+
+    fun getProblems(floorId: String, success: (String, String, String) -> Unit) {
+        viewModelScope.launch {
+            val problems = repo.getProblemsByFloorId(floorId)
+            val tipArrayList = ArrayList<TipArray>()
+            val lineArrayList = ArrayList<LineArray>()
+            val iDList = ArrayList<String>()
+            for (problem in problems) {
+                val info = gson.fromJson(problem.info, HashMap::class.java) as HashMap<String, Any>
+                if (!TextUtils.isEmpty(problem.objId)) {
+                    iDList.add(problem.objId)
+                }
+                if (info["position"] != null && info["position"] is LinkedTreeMap<*, *>) {
+                    val tipArray = TipArray()
+                    tipArray.ID = problem.objId
+                    val pointZ = info["position"] as LinkedTreeMap<String, Double>
+                    tipArray.Position =
+                        PointZ(pointZ["X"]!!.toFloat(), pointZ["Y"]!!.toFloat(), pointZ["Z"]!!.toFloat())
+                    tipArray.Param = TipArray.Param(problem.typeName, 1, problem.objId)
+                    tipArrayList.add(tipArray)
+                } else if (info["position"] != null && info["position"] is ArrayList<*> && !isNull(info["position"])) {
+                    val lineArray = LineArray()
+                    lineArray.ID = problem.objId
+                    lineArray.Points = info["position"] as java.util.ArrayList<PointZ>?
+                    lineArray.IsLoop = info["isClose"] as Boolean?
+                    lineArray.IsLaQi = info["isClose"] as Boolean?
+                    lineArrayList.add(lineArray)
+
+                    val tipArray = TipArray()
+                    tipArray.ID = problem.objId
+                    tipArray.Param = TipArray.Param(problem.typeName, 1, problem.objId)
+                    tipArrayList.add(tipArray)
+                }
+            }
+            val toJson = Space3DActivity.gson.toJson(tipArrayList)
+            val replace = toJson.replace("\"", "\\\"")
+
+            val styleObjectList = ArrayList<StyleObject>()
+            val styleObject = StyleObject()
+            styleObject.ID.addAll(iDList)
+            styleObjectList.add(styleObject)
+            val styleObjectString = gson.toJson(styleObjectList).replace("\"", "\\\"")
+            val lineArrayString = gson.toJson(lineArrayList).replace("\"", "\\\"")
+
+            success(replace, styleObjectString, lineArrayString)
+        }
+    }
+
+    fun getProblemByObjId(tipObject: TipArray.Param?, success: (ProblemEntity) -> Unit) {
+        viewModelScope.launch {
+            val problemEntity = repo.getProblemByObjId(tipObject!!.ID)
+            success(problemEntity)
+        }
+    }
+
+}

BIN
app/src/main/res/drawable-xxhdpi/add_pic.png


BIN
app/src/main/res/drawable-xxhdpi/choseicon_gray.png


BIN
app/src/main/res/drawable-xxhdpi/icon_lock.png


BIN
app/src/main/res/drawable-xxhdpi/icon_lock_blue.png


BIN
app/src/main/res/drawable-xxhdpi/icon_takephoto.png


BIN
app/src/main/res/drawable-xxhdpi/image_error_icon.png


BIN
app/src/main/res/drawable-xxhdpi/image_loading_icon.png


+ 8 - 0
app/src/main/res/drawable/bg_edt_gray_eff0f1.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape android:shape="rectangle"
+       xmlns:android="http://schemas.android.com/apk/res/android">
+    <stroke
+            android:width="2dp"
+            android:color="#EFF0F1"/>
+    <corners android:radius="4dp"/>
+</shape>

+ 6 - 0
app/src/main/res/drawable/bg_gray_f2f3f6.xml

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

BIN
app/src/main/res/drawable/checkbox_selected.png


+ 7 - 0
app/src/main/res/drawable/checkbox_style.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/checkbox_selected" android:state_checked="true" />
+    <item android:drawable="@drawable/checkbox_unselected" android:state_checked="false" />
+
+    <item android:drawable="@drawable/checkbox_unselected" />
+</selector>

BIN
app/src/main/res/drawable/checkbox_unselected.png


+ 16 - 0
app/src/main/res/drawable/corners_line_black.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <corners
+        android:bottomLeftRadius="4dip"
+        android:bottomRightRadius="4dip"
+        android:topLeftRadius="4dip"
+        android:topRightRadius="4dip" />
+
+    <stroke
+        android:color="#e6e6e6"
+        android:width="0.8dp" />
+
+    <solid android:color="#ffffff" />
+
+</shape>

+ 12 - 0
app/src/main/res/drawable/shape_rectangle_green_3.xml

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

+ 19 - 0
app/src/main/res/layout/activity_look_big_pic.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout 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:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="#f5f6f7">
+
+
+    <ImageView
+            android:id="@+id/look_big_pic_iv"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_alignParentBottom="true"
+            android:layout_centerInParent="true"
+            android:scaleType="fitXY"/>
+
+
+</RelativeLayout>

+ 74 - 0
app/src/main/res/layout/activity_newcreate_dialog.xml

@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="290dp"
+    android:layout_height="wrap_content"
+    android:background="@drawable/corners_line_black"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/contentTV"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="25dp"
+        android:layout_marginTop="20dp"
+        android:layout_marginRight="25dp"
+        android:gravity="bottom|center_horizontal"
+        android:lineSpacingExtra="8dp"
+        android:text="提示"
+        android:textColor="#272727"
+        android:textSize="17sp"
+        android:textStyle="bold" />
+
+    <TextView
+        android:id="@+id/tv_info"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="25dp"
+        android:layout_marginTop="20dp"
+        android:layout_marginRight="25dp"
+        android:gravity="bottom|center_horizontal"
+        android:lineSpacingExtra="8dp"
+        android:text="提示"
+        android:textColor="#666666"
+        android:textSize="14sp"
+        android:visibility="gone" />
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_gravity="center_horizontal"
+        android:layout_marginTop="5dp"
+        android:layout_marginBottom="5dp"
+        android:orientation="horizontal"
+        android:visibility="gone">
+
+        <CheckBox
+            android:id="@+id/check_single"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:button="@drawable/checkbox_style" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="12dp"
+            android:text="不再提示"
+            android:textColor="#272727"
+            android:textSize="16sp" />
+    </LinearLayout>
+
+    <TextView
+        android:id="@+id/IKnowTV"
+        android:layout_width="match_parent"
+        android:layout_height="40dp"
+        android:layout_marginLeft="10dp"
+        android:layout_marginTop="20dp"
+        android:layout_marginRight="10dp"
+        android:layout_marginBottom="10dp"
+        android:background="@drawable/shape_rectangle_green_3"
+        android:gravity="center"
+        android:text="我知道了"
+        android:textColor="#ffffff"
+        android:textSize="15sp" />
+</LinearLayout>

+ 111 - 19
app/src/main/res/layout/activity_space3d_activity.xml

@@ -35,7 +35,7 @@
         <TextView
                 android:id="@+id/projectName"
                 android:layout_marginLeft="19dp"
-                android:text="京东科技大厦 地下1F"
+                android:text=""
                 android:layout_width="wrap_content"
                 android:layout_centerVertical="true"
                 android:layout_height="wrap_content"
@@ -151,6 +151,12 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent">
 
+        <WebView
+                android:id="@+id/webview"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                tools:context=".activities.Space3DActivity"/>
+
         <ExpandableListView
                 android:visibility="gone"
                 android:id="@+id/expandLv"
@@ -165,12 +171,6 @@
                 android:layout_height="match_parent"
                 android:background="#EFF0F1"/>
 
-        <WebView
-                android:layout_toRightOf="@+id/line3"
-                android:id="@+id/webview"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                tools:context=".activities.Space3DActivity"/>
 
         <TextView
                 android:id="@+id/addProblem"
@@ -408,6 +408,7 @@
         </LinearLayout>
 
         <LinearLayout
+                android:visibility="gone"
                 android:id="@+id/cameraTypeTools"
                 android:layout_marginRight="30dp"
                 android:layout_alignParentRight="true"
@@ -516,7 +517,7 @@
                     android:gravity="center"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:text="保存"
+                    android:text="完成"
                     android:textSize="12sp"
                     android:textColor="@android:color/white"/>
 
@@ -531,7 +532,7 @@
                     android:gravity="center"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:text="除"
+                    android:text="除"
                     android:textSize="12sp"
                     android:textColor="@android:color/white"/>
         </LinearLayout>
@@ -594,6 +595,7 @@
                 android:orientation="vertical">
 
             <TextView
+                    android:visibility="gone"
                     android:id="@+id/compass"
                     android:drawableTop="@drawable/icon_compass"
                     android:layout_marginLeft="3dp"
@@ -653,7 +655,7 @@
                     android:layout_width="match_parent"
                     android:drawablePadding="3dp"
                     android:layout_height="wrap_content"
-                    android:text="锁定视角"
+                    android:text="禁止翻转"
                     android:textSize="12sp"
                     android:textColor="@android:color/white"/>
 
@@ -693,9 +695,9 @@
 
         <androidx.cardview.widget.CardView
                 android:id="@+id/signProblem"
+                android:visibility="gone"
                 android:layout_alignParentRight="true"
                 android:layout_width="400dp"
-                android:visibility="gone"
                 android:elevation="8dp"
                 android:layout_height="match_parent">
 
@@ -711,9 +713,10 @@
                         android:orientation="horizontal">
 
                     <TextView
+                            android:id="@+id/signProblemTitle"
                             android:layout_marginLeft="32dp"
                             android:layout_marginTop="16dp"
-                            android:text="记问题"
+                            android:text="记问题"
                             android:textSize="16sp"
                             android:textColor="#1F2329"
                             android:layout_width="wrap_content"
@@ -721,15 +724,27 @@
 
                     <ImageView
                             android:id="@+id/closeProblem"
-                            android:paddingTop="21dp"
+                            android:paddingTop="16dp"
                             android:paddingRight="25dp"
-                            android:paddingLeft="25dp"
-                            android:paddingBottom="21dp"
+                            android:paddingLeft="5dp"
+                            android:paddingBottom="16dp"
                             android:layout_alignParentRight="true"
                             android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
                             android:src="@drawable/icon_delete"
                             />
+
+                    <ImageView
+                            android:layout_toLeftOf="@+id/closeProblem"
+                            android:id="@+id/deleteProblem"
+                            android:paddingTop="16dp"
+                            android:paddingLeft="25dp"
+                            android:paddingRight="5dp"
+                            android:paddingBottom="16dp"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:src="@drawable/icon_delete_white"
+                            />
                 </RelativeLayout>
 
                 <View
@@ -737,12 +752,12 @@
                         android:layout_height="1px"
                         android:background="#E4E5E7"/>
 
-                <ScrollView
+                <androidx.recyclerview.widget.RecyclerView
+                        android:paddingBottom="10dp"
+                        android:id="@+id/infoRv"
                         android:layout_width="match_parent"
                         android:layout_height="0dp"
-                        android:layout_weight="1">
-
-                </ScrollView>
+                        android:layout_weight="1"/>
 
 
                 <LinearLayout
@@ -769,10 +784,87 @@
                             android:layout_marginTop="16dp"
                             android:layout_marginBottom="16dp"
                             android:background="@drawable/bg_blue_round"/>
+
+                    <LinearLayout
+                            android:id="@+id/reviseLl"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:orientation="horizontal">
+
+
+                        <TextView
+                                android:id="@+id/reviseProblem"
+                                android:text="重新修改记录问题"
+                                android:gravity="center"
+                                android:layout_width="0dp"
+                                android:layout_weight="1"
+                                android:layout_height="48dp"
+                                android:textSize="14sp"
+                                android:layout_marginLeft="16dp"
+                                android:textColor="@color/black_1F2329"
+                                android:layout_marginTop="16dp"
+                                android:layout_marginBottom="16dp"
+                                android:background="@drawable/bg_gray_eff0f1"/>
+
+
+                        <TextView
+                                android:id="@+id/reviseInfo"
+                                android:text="保存"
+                                android:gravity="center"
+                                android:layout_width="0dp"
+                                android:layout_weight="1"
+                                android:layout_height="48dp"
+                                android:textSize="14sp"
+                                android:layout_marginLeft="20dp"
+                                android:layout_marginRight="16dp"
+                                android:textColor="@android:color/white"
+                                android:layout_marginTop="16dp"
+                                android:layout_marginBottom="16dp"
+                                android:background="@drawable/bg_blue_round"/>
+                    </LinearLayout>
                 </LinearLayout>
             </LinearLayout>
         </androidx.cardview.widget.CardView>
 
+        <RelativeLayout
+                android:visibility="gone"
+                android:id="@+id/detailRl"
+                android:layout_marginTop="50dp"
+                android:layout_marginLeft="50dp"
+                android:paddingTop="16dp"
+                android:paddingBottom="16dp"
+                android:background="@drawable/bg_black_round"
+                android:paddingLeft="16dp"
+                android:layout_width="200dp"
+                android:layout_height="wrap_content">
+
+            <TextView
+                    android:id="@+id/detailTitle"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="设备详情"
+                    android:textSize="14sp"
+                    android:textColor="#FFFFFF"/>
+
+            <ImageView
+                    android:id="@+id/detailClose"
+                    android:paddingRight="16dp"
+                    android:layout_alignParentRight="true"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:src="@drawable/icon_delete"/>
+
+            <TextView
+                    android:id="@+id/detailContent"
+                    android:layout_marginTop="12dp"
+                    android:lineSpacingExtra="5dp"
+                    android:layout_below="@+id/detailTitle"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textColor="#FFFFFF"
+                    android:text=""/>
+        </RelativeLayout>
+
     </RelativeLayout>
 
 </LinearLayout>

+ 34 - 0
app/src/main/res/layout/child_expand_space.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="48dp">
+
+    <TextView
+        android:id="@+id/itemSpaceTV"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="32dp"
+        android:text="#F"
+        android:textColor="#272727"
+        android:textSize="16sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/numTV"
+        android:layout_width="58dp"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="16dp"
+        android:gravity="end"
+        android:text="15"
+        android:textColor="#272727"
+        android:visibility="invisible"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="1.0"
+        app:layout_constraintStart_toEndOf="@+id/itemSpaceTV"
+        app:layout_constraintTop_toTopOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 68 - 0
app/src/main/res/layout/common_fragment_img_sel.xml

@@ -0,0 +1,68 @@
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/rvImageList"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginBottom="?android:attr/actionBarSize"/>
+
+        <RelativeLayout
+            android:id="@+id/rlBottom"
+            android:layout_width="match_parent"
+            android:layout_height="?android:attr/actionBarSize"
+            android:layout_alignParentBottom="true"
+            android:background="@color/bottom_bg"
+            android:clickable="true">
+
+            <Button
+                android:id="@+id/btnAlbumSelected"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_centerVertical="true"
+                android:background="@null"
+                android:drawablePadding="5dp"
+                android:drawableRight="@drawable/ic_album"
+                android:ellipsize="end"
+                android:gravity="center_vertical"
+                android:paddingLeft="16dp"
+                android:paddingRight="16dp"
+                android:singleLine="true"
+                android:textAllCaps="false"
+                android:textColor="@android:color/white"
+                android:textSize="16sp"/>
+            <Button
+                android:id="@+id/btn_certain"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_alignParentRight="true"
+                android:layout_centerVertical="true"
+                android:layout_marginBottom="5dp"
+                android:layout_marginRight="16dp"
+                android:layout_marginTop="5dp"
+                android:background="#3BACB2"
+                android:paddingLeft="16dp"
+                android:paddingRight="16dp"
+                android:singleLine="true"
+                android:text="添加 (3)"
+                android:textAllCaps="false"
+                android:textColor="@android:color/white"
+                android:textSize="15sp"
+                android:visibility="gone"/>
+        </RelativeLayout>
+
+    </RelativeLayout>
+
+    <com.yuyh.library.imgsel.widget.CustomViewPager
+        android:id="@+id/viewPager"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@android:color/black"
+        android:visibility="gone"/>
+</FrameLayout>

+ 28 - 0
app/src/main/res/layout/common_item_img_sel.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.yuyh.library.imgsel.widget.SquareRelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/ivImage"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_centerInParent="true"
+        android:scaleType="centerCrop"
+        android:src="@drawable/ic_default_image"/>
+
+    <ImageView
+        android:id="@+id/ivPhotoCheaked"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:layout_alignParentTop="true"
+        android:layout_marginRight="1dp"
+        android:layout_marginTop="1dp"
+        android:contentDescription="@null"
+        android:paddingBottom="20dp"
+        android:paddingLeft="20dp"
+        android:src="@drawable/choseicon_gray"/>
+
+</com.yuyh.library.imgsel.widget.SquareRelativeLayout>

+ 83 - 0
app/src/main/res/layout/dialog_list_choice.xml

@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical">
+
+    <LinearLayout
+            android:id="@+id/pop_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentStart="true"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentBottom="true"
+            android:background="@color/white"
+            android:gravity="center_horizontal"
+            android:orientation="vertical">
+
+        <RelativeLayout
+                android:layout_width="match_parent"
+                android:layout_height="55dp">
+
+            <TextView
+                    android:id="@+id/title"
+                    android:layout_width="match_parent"
+                    android:layout_height="55dp"
+                    android:background="@color/white"
+                    android:gravity="center"
+                    android:paddingLeft="10dp"
+                    android:text="请选择"
+                    android:textColor="#a6a6a6"
+                    android:textSize="15sp"/>
+
+            <TextView
+                    android:id="@+id/chooseSpace"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignParentRight="true"
+                    android:layout_centerVertical="true"
+                    android:layout_marginRight="16dp"
+                    android:background="@drawable/bg_gray_f2f3f6"
+                    android:paddingLeft="6dp"
+                    android:paddingTop="5dp"
+                    android:paddingRight="6dp"
+                    android:paddingBottom="5dp"
+                    android:text="平面图选择"
+                    android:textColor="#272727"
+                    android:visibility="gone"/>
+        </RelativeLayout>
+
+        <Button
+                android:id="@+id/btn1"
+                style="?android:attr/borderlessButtonStyle"
+                android:layout_width="match_parent"
+                android:layout_height="55dp"
+                android:layout_marginLeft="16dp"
+                android:layout_marginRight="16dp"
+                android:background="#ffffff"
+                android:gravity="center"
+                android:text="确定"
+                android:textColor="#272727"
+                android:textSize="16sp"/>
+
+        <androidx.recyclerview.widget.RecyclerView
+                android:id="@+id/recyclerview"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:background="#ffffff"
+                android:overScrollMode="never"
+                android:scrollbars="vertical"/>
+
+        <Button
+                android:id="@+id/btn_cancel"
+                style="?android:attr/borderlessButtonStyle"
+                android:layout_width="match_parent"
+                android:layout_height="55dp"
+                android:gravity="center"
+                android:text="取消"
+                android:textColor="#272727"
+                android:textSize="16sp"
+                android:visibility="gone"/>
+    </LinearLayout>
+</RelativeLayout>

+ 6 - 0
app/src/main/res/layout/empty.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                                                   android:layout_width="wrap_content"
+                                                   android:layout_height="wrap_content">
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 20 - 0
app/src/main/res/layout/group_expand_space.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="wrap_content"
+    android:layout_height="56dp">
+
+    <TextView
+        android:id="@+id/groupSpaceTV"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginEnd="16dp"
+        android:text="Group"
+        android:textColor="#272727"
+        android:textSize="18sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 23 - 0
app/src/main/res/layout/item_img_sel_take_photo.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.yuyh.library.imgsel.widget.SquareRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/sql"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center">
+
+    <ImageView
+        android:id="@+id/ivTakePhoto"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:scaleType="centerCrop" />
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@+id/ivTakePhoto"
+        android:layout_centerHorizontal="true"
+        android:text="@string/takephoto" />
+
+</com.yuyh.library.imgsel.widget.SquareRelativeLayout>

+ 33 - 0
app/src/main/res/layout/item_node_nine_pic.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_marginTop="20dp"
+    android:layout_marginBottom="20dp">
+
+    <ImageView
+        android:id="@+id/node_nine_pic_iv"
+        android:layout_width="104dp"
+        android:layout_height="104dp"
+        android:scaleType="centerCrop"
+        android:src="@drawable/add_pic"/>
+
+    <ImageView
+        android:id="@+id/node_nine_pic_delete"
+        android:layout_width="32dp"
+        android:layout_height="32dp"
+        android:layout_alignRight="@+id/node_nine_pic_iv"
+        android:paddingTop="8dp"
+        android:paddingRight="8dp"
+        android:src="@drawable/icon_delete_white"
+        android:visibility="gone" />
+
+    <TextView
+        android:id="@+id/node_nine_pic_position"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="8dp"
+        android:textColor="@color/white"
+        android:textSize="18sp" />
+</RelativeLayout>

+ 31 - 0
app/src/main/res/layout/personal_select_text_single_item.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/choice_layout"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="#ffffff"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="55dp"
+        android:layout_gravity="center"
+        android:background="#ffffff"
+        android:orientation="horizontal">
+
+        <TextView
+            android:id="@+id/choice_name"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="16dp"
+            android:layout_marginRight="16dp"
+            android:gravity="center_vertical"
+            android:singleLine="true"
+            android:text="维修"
+            android:textColor="#272727"
+            android:textSize="16sp" />
+
+    </LinearLayout>
+
+
+</LinearLayout>

+ 52 - 0
app/src/main/res/layout/view_enum.xml

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+        android:background="#ffffff"
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:paddingLeft="32dp"
+        android:paddingRight="32dp"
+        android:orientation="vertical"
+        android:layout_height="wrap_content">
+
+    <TextView
+            android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="移动距离"
+            android:layout_marginTop="16dp"
+            android:textSize="14sp"
+            android:textColor="@color/black_1F2329"/>
+
+    <LinearLayout
+            android:layout_marginTop="12dp"
+            android:gravity="center_vertical"
+            android:background="@drawable/bg_edt_gray_eff0f1"
+            android:layout_width="match_parent"
+            android:layout_height="30dp"
+            android:orientation="horizontal">
+
+        <TextView
+                android:id="@+id/tv"
+                android:gravity="center_vertical"
+                android:text=""
+                android:layout_marginLeft="16dp"
+                android:background="@null"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:layout_marginRight="8dp"
+                android:singleLine="true"
+                android:textSize="14sp"
+                android:textColor="@color/black_1F2329"
+                android:textColorHint="@color/gray_C3C7CB"/>
+
+        <ImageView
+                android:id="@+id/unit"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:src="@drawable/icon_arrow_down"
+                android:layout_marginRight="16dp"
+                android:textColor="@color/black_1F2329"
+                android:textSize="14sp"/>
+    </LinearLayout>
+</LinearLayout>

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

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+        android:background="#ffffff"
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:paddingLeft="32dp"
+        android:paddingRight="32dp"
+        android:orientation="vertical"
+        android:layout_height="wrap_content">
+
+    <TextView
+            android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="照片"
+            android:layout_marginTop="16dp"
+            android:textSize="14sp"
+            android:textColor="@color/black_1F2329"/>
+
+    <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/rv"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+</LinearLayout>

+ 225 - 0
app/src/main/res/layout/view_position.xml

@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingLeft="32dp"
+        android:paddingRight="32dp"
+        android:orientation="vertical">
+
+    <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="移动方向"
+            android:layout_marginTop="16dp"
+            android:textSize="14sp"
+            android:textColor="@color/black_1F2329"/>
+
+    <LinearLayout
+            android:layout_marginTop="10dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+
+        <LinearLayout
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:orientation="vertical">
+
+            <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="左边"
+                    android:layout_marginTop="16dp"
+                    android:textSize="14sp"
+                    android:textColor="@color/black_1F2329"/>
+
+            <LinearLayout
+                    android:layout_marginTop="12dp"
+                    android:gravity="center_vertical"
+                    android:background="@drawable/bg_edt_gray_eff0f1"
+                    android:layout_width="match_parent"
+                    android:layout_height="30dp"
+                    android:orientation="horizontal">
+
+                <EditText
+                        android:id="@+id/left"
+                        android:gravity="center_vertical"
+                        android:layout_marginLeft="16dp"
+                        android:background="@null"
+                        android:layout_width="0dp"
+                        android:layout_height="match_parent"
+                        android:layout_weight="1"
+                        android:hint="请输入"
+                        android:text="0"
+                        android:layout_marginRight="8dp"
+                        android:singleLine="true"
+                        android:textSize="14sp"
+                        android:textColor="@color/black_1F2329"
+                        android:textColorHint="@color/gray_C3C7CB"/>
+
+                <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="mm"
+                        android:layout_marginRight="16dp"
+                        android:textColor="@color/black_1F2329"
+                        android:textSize="14sp"/>
+            </LinearLayout>
+        </LinearLayout>
+
+        <LinearLayout
+                android:layout_marginLeft="16dp"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:orientation="vertical">
+
+            <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="右边"
+                    android:layout_marginTop="16dp"
+                    android:textSize="14sp"
+                    android:textColor="@color/black_1F2329"/>
+
+            <LinearLayout
+                    android:layout_marginTop="12dp"
+                    android:gravity="center_vertical"
+                    android:background="@drawable/bg_edt_gray_eff0f1"
+                    android:layout_width="match_parent"
+                    android:layout_height="30dp"
+                    android:orientation="horizontal">
+
+                <EditText
+                        android:id="@+id/right"
+                        android:gravity="center_vertical"
+                        android:layout_marginLeft="16dp"
+                        android:background="@null"
+                        android:layout_width="0dp"
+                        android:layout_height="match_parent"
+                        android:layout_weight="1"
+                        android:text="0"
+                        android:hint="请输入"
+                        android:layout_marginRight="8dp"
+                        android:singleLine="true"
+                        android:textSize="14sp"
+                        android:textColor="@color/black_1F2329"
+                        android:textColorHint="@color/gray_C3C7CB"/>
+
+                <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="mm"
+                        android:layout_marginRight="16dp"
+                        android:textColor="@color/black_1F2329"
+                        android:textSize="14sp"/>
+            </LinearLayout>
+        </LinearLayout>
+    </LinearLayout>
+
+
+    <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+
+        <LinearLayout
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:orientation="vertical">
+
+            <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="上"
+                    android:layout_marginTop="16dp"
+                    android:textSize="14sp"
+                    android:textColor="@color/black_1F2329"/>
+
+            <LinearLayout
+                    android:layout_marginTop="12dp"
+                    android:gravity="center_vertical"
+                    android:background="@drawable/bg_edt_gray_eff0f1"
+                    android:layout_width="match_parent"
+                    android:layout_height="30dp"
+                    android:orientation="horizontal">
+
+                <EditText
+                        android:id="@+id/up"
+                        android:gravity="center_vertical"
+                        android:layout_marginLeft="16dp"
+                        android:background="@null"
+                        android:layout_width="0dp"
+                        android:layout_height="match_parent"
+                        android:layout_weight="1"
+                        android:text="0"
+                        android:hint="请输入"
+                        android:layout_marginRight="8dp"
+                        android:singleLine="true"
+                        android:textSize="14sp"
+                        android:textColor="@color/black_1F2329"
+                        android:textColorHint="@color/gray_C3C7CB"/>
+
+                <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="mm"
+                        android:layout_marginRight="16dp"
+                        android:textColor="@color/black_1F2329"
+                        android:textSize="14sp"/>
+            </LinearLayout>
+        </LinearLayout>
+
+        <LinearLayout
+                android:layout_marginLeft="16dp"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:orientation="vertical">
+
+            <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="下"
+                    android:layout_marginTop="16dp"
+                    android:textSize="14sp"
+                    android:textColor="@color/black_1F2329"/>
+
+            <LinearLayout
+                    android:layout_marginTop="12dp"
+                    android:gravity="center_vertical"
+                    android:background="@drawable/bg_edt_gray_eff0f1"
+                    android:layout_width="match_parent"
+                    android:layout_height="30dp"
+                    android:orientation="horizontal">
+
+                <EditText
+                        android:id="@+id/down"
+                        android:gravity="center_vertical"
+                        android:layout_marginLeft="16dp"
+                        android:background="@null"
+                        android:layout_width="0dp"
+                        android:layout_height="match_parent"
+                        android:layout_weight="1"
+                        android:hint="请输入"
+                        android:text="0"
+                        android:layout_marginRight="8dp"
+                        android:singleLine="true"
+                        android:textSize="14sp"
+                        android:textColor="@color/black_1F2329"
+                        android:textColorHint="@color/gray_C3C7CB"/>
+
+                <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="mm"
+                        android:layout_marginRight="16dp"
+                        android:textColor="@color/black_1F2329"
+                        android:textSize="14sp"/>
+            </LinearLayout>
+        </LinearLayout>
+    </LinearLayout>
+</LinearLayout>

+ 77 - 0
app/src/main/res/layout/view_text.xml

@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+        android:background="#ffffff"
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:paddingLeft="32dp"
+        android:paddingRight="32dp"
+        android:orientation="vertical"
+        android:layout_height="wrap_content"
+        xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <TextView
+            android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="移动距离"
+            android:layout_marginTop="16dp"
+            android:textSize="14sp"
+            android:textColor="@color/black_1F2329"/>
+
+    <LinearLayout
+            android:layout_marginTop="12dp"
+            android:gravity="center_vertical"
+            android:background="@drawable/bg_edt_gray_eff0f1"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+
+        <EditText
+                android:id="@+id/edt"
+                android:gravity="top"
+                android:paddingTop="5dp"
+                android:paddingBottom="5dp"
+                android:layout_marginLeft="16dp"
+                android:background="@null"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:hint="请输入"
+                android:minHeight="30dp"
+                android:layout_marginRight="8dp"
+                android:singleLine="true"
+                android:textSize="14sp"
+                android:textColor="@color/black_1F2329"
+                android:textColorHint="@color/gray_C3C7CB"/>
+
+        <TextView
+                android:id="@+id/unit"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="mm"
+                android:layout_marginRight="16dp"
+                android:textColor="@color/black_1F2329"
+                android:textSize="14sp"/>
+    </LinearLayout>
+
+    <LinearLayout
+            android:visibility="gone"
+            android:id="@+id/switchLl"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+        <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="问题已解决"
+                android:layout_marginTop="16dp"
+                android:textSize="14sp"
+                android:textColor="@color/black_1F2329"/>
+
+        <androidx.appcompat.widget.SwitchCompat
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                />
+    </LinearLayout>
+</LinearLayout>

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

@@ -11,5 +11,7 @@
     <color name="gray_C3C7CB">#C3C7CB</color>
     <color name="trans">#00000000</color>
     <color name="blue_0091FF">#0091FF</color>
+    <color name="blue_2E3679">#2E3679</color>
+    <color name="gray_a6a6a6">#a6a6a6</color>
 
 </resources>

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

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

+ 21 - 0
buildSrc/src/main/kotlin/Build.kt

@@ -165,4 +165,25 @@ object Deps {
         const val Espresso = "androidx.test.espresso:espresso-core:3.4.0"
         const val UI = "androidx.ui:ui-test:1.0.0-alpha07"
     }
+
+    object Glide {
+        const val Glide = "com.github.bumptech.glide:glide:4.2.0"
+        const val Compiler = "com.github.bumptech.glide:compiler:4.2.0"
+        const val Okhttp3 = "com.github.bumptech.glide:okhttp3-integration:4.0.0"
+        const val Logging = "com.squareup.okhttp3:logging-interceptor:4.9.0"
+        const val annotations = "com.androidx.support:support-annotations:28.0.0"
+        const val Rxjava = "io.reactivex.rxjava2:rxjava:2.2.9"
+        const val Rxandroid = "io.reactivex.rxjava2:rxandroid:2.1.1"
+        const val Components = "com.trello.rxlifecycle2:rxlifecycle-components:2.2.1"
+    }
+
+    object Tools {
+        const val DebugDB = "com.amitshekhar.android:debug-db:1.0.6"
+        const val hutool = "cn.hutool:hutool-all:5.4.7"
+        const val Autosize = "me.jessyan:autosize:1.2.1"
+    }
+
+    object Imgsel {
+        const val Imgsel = "com.yuyh.imgsel:library:1.3.8"
+    }
 }

+ 4 - 0
settings.gradle.kts

@@ -2,7 +2,9 @@ pluginManagement {
     repositories {
         gradlePluginPortal()
         google()
+        jcenter()
         mavenCentral()
+        maven { setUrl("https://maven.google.com") }
     }
     plugins {
         id("com.android.application") version "7.0.4"
@@ -14,10 +16,12 @@ dependencyResolutionManagement {
     repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
     repositories {
         google()
+        jcenter()
         mavenCentral()
         maven {
             isAllowInsecureProtocol = true
             setUrl("""http://dev.dp.sagacloud.cn:8082/repository/maven-public/""")
+            setUrl("https://maven.google.com")
         }
     }
 }