Browse Source

@task: Data Framework

bai 3 years ago
parent
commit
844a02618c
60 changed files with 1643 additions and 94 deletions
  1. 39 4
      demo/build.gradle
  2. 49 40
      demo/src/main/AndroidManifest.xml
  3. 31 1
      demo/src/main/java/com/framework/app/api/Api.kt
  4. 0 20
      demo/src/main/java/com/framework/app/http/Request.kt
  5. 0 22
      demo/src/main/java/com/framework/app/http/Respose.kt
  6. 83 0
      demo/src/main/java/com/framework/di/Di.kt
  7. 19 0
      demo/src/main/java/com/framework/mvvm/model/data/AbsentLiveData.kt
  8. 35 0
      demo/src/main/java/com/framework/mvvm/model/data/Data.kt
  9. 104 0
      demo/src/main/java/com/framework/mvvm/model/data/DataSource.kt
  10. 45 0
      demo/src/main/java/com/framework/mvvm/model/data/Http.kt
  11. 10 0
      demo/src/main/java/com/framework/mvvm/model/data/Model.kt
  12. 65 0
      demo/src/main/java/com/framework/mvvm/model/db/AdmDatabase.kt
  13. 22 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/ConfigDao.kt
  14. 22 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/EquipmentDao.kt
  15. 22 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/FileDao.kt
  16. 22 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/InfosConfigDao.kt
  17. 22 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/M2dEquipDao.kt
  18. 23 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/MajorDao.kt
  19. 26 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/ObjectDao.kt
  20. 22 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/PipeConfigDao.kt
  21. 23 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/ProblemArchDao.kt
  22. 22 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/ProblemEquipDao.kt
  23. 23 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/ProjectDao.kt
  24. 22 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/QrCodeDao.kt
  25. 22 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/RelConfigDao.kt
  26. 23 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/RelationDao.kt
  27. 22 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/RelationDictDao.kt
  28. 22 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/SpaceDao.kt
  29. 17 0
      demo/src/main/java/com/framework/mvvm/model/db/dao/SystemDao.kt
  30. 19 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/ConfigEntity.kt
  31. 30 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/EquipmentEntity.kt
  32. 32 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/FileEntity.kt
  33. 21 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/InfosConfigEntity.kt
  34. 22 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/InfosEntity.kt
  35. 19 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/M2dEquipEntity.kt
  36. 21 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/MajorEntity.kt
  37. 56 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/ObjectEntity.kt
  38. 14 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/OutlineEntity.kt
  39. 21 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/PipeConfigEntity.kt
  40. 28 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/ProblemArchEntity.kt
  41. 28 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/ProblemEquipEntity.kt
  42. 26 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/ProjectEntity.kt
  43. 30 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/QrCodeEntity.kt
  44. 22 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/RelConfigEntity.kt
  45. 31 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/RelationDictEntity.kt
  46. 41 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/RelationEntity.kt
  47. 41 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/SpaceEntity.kt
  48. 32 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/SystemEntity.kt
  49. 20 0
      demo/src/main/java/com/framework/mvvm/model/db/entity/rel/MajorSysRelation.kt
  50. 38 0
      demo/src/main/java/com/framework/mvvm/model/repository/FrameRepository.kt
  51. 19 0
      demo/src/main/java/com/framework/mvvm/model/vo/Config.kt
  52. 25 0
      demo/src/main/java/com/framework/mvvm/model/vo/Define.kt
  53. 18 0
      demo/src/main/java/com/framework/mvvm/model/vo/Floor.kt
  54. 13 0
      demo/src/main/java/com/framework/mvvm/model/vo/Frame.kt
  55. 10 0
      demo/src/main/java/com/framework/mvvm/model/vo/FrameRequest.kt
  56. 37 0
      demo/src/main/java/com/framework/mvvm/mv/FrameViewModel.kt
  57. 25 0
      demo/src/main/java/com/framework/mvvm/mv/ViewModelFactory.kt
  58. 15 1
      demo/src/main/java/com/sybotan/android/demo/DemoApp.kt
  59. 31 5
      demo/src/main/java/com/sybotan/android/demo/activities/PocActivity.kt
  60. 1 1
      gradle.properties

+ 39 - 4
demo/build.gradle

@@ -35,12 +35,12 @@ plugins {
 }
 
 android {
-    compileSdkVersion 30
+    compileSdkVersion 31
     // buildToolsVersion ANDROID_BUILD_TOOLS_VERSION
 
     defaultConfig {
         minSdkVersion 28
-        targetSdkVersion 30
+        targetSdkVersion 31
         versionCode SAGA_CODE.toInteger()
         versionName SAGA_ANDROID_VERSION
 
@@ -53,6 +53,12 @@ android {
             // 还可以添加 abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'x86_64', 'mips', 'mips64', 'arm64-v8a'
 
         }
+
+        javaCompileOptions {
+            annotationProcessorOptions {
+                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
+            }
+        }
     }
 
     buildTypes {
@@ -81,8 +87,14 @@ android {
             jniLibs.srcDirs = ['libs']
         }
     }
+
+    configurations {
+        cleanedAnnotations
+        compile.exclude group: 'com.intellij', module: 'annotations'
+    }
 }
 
+
 dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
     implementation files('libs/zbardecoder.jar')
@@ -183,8 +195,11 @@ dependencies {
     implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
 
     implementation 'org.kodein.di:kodein-di:7.8.0'
-    implementation 'org.kodein.di:kodein-di-framework-android-support:7.8.0'
-    //implementation 'org.kodein.di:kodein-di-framework-android-x-viewmodel:7.8.0'
+    //implementation 'org.kodein.di:kodein-di-framework-android-support:7.8.0'
+    implementation 'org.kodein.di:kodein-di-framework-android-x:7.8.0'
+    implementation 'org.kodein.di:kodein-di-framework-android-x-viewmodel:7.8.0'
+
+    // kotlin
     implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.0-RC'
 
     implementation 'com.arashivision.sdk:sdkcamera:1.3.10'
@@ -192,5 +207,25 @@ dependencies {
     implementation 'com.lzy.net:okgo:3.0.4'
     implementation 'com.afollestad.material-dialogs:core:0.9.6.0'
 
+    androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', {
+        exclude group: 'com.android.support', module: 'support-annotations'
+    })
+
+    // room
+    implementation('androidx.room:room-runtime:2.4.0-alpha05', {
+        exclude group: 'com.intellij', module: 'annotations'
+    })
+    kapt('androidx.room:room-compiler:2.4.0-alpha05', {
+        exclude group: 'com.intellij', module: 'annotations'
+    })
+    implementation('androidx.room:room-ktx:2.4.0-alpha05', {
+        exclude group: 'com.intellij', module: 'annotations'
+    })
 
+    // lifecycle
+    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
+    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
+    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0-rc01'
+    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
+    implementation 'com.squareup.okhttp3:logging-interceptor:3.14.4'
 }

+ 49 - 40
demo/src/main/AndroidManifest.xml

@@ -1,62 +1,71 @@
 <?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.sybotan.android.demo">
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.sybotan.android.demo">
 
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.INTERNET"/>
-    <uses-permission android:name="android.permission.BLUETOOTH"/> <!-- SD卡中创建与删除文件权限 -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.BLUETOOTH" /> <!-- SD卡中创建与删除文件权限 -->
     <uses-permission
-            android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
-            tools:ignore="ProtectedPermissions"/> <!-- 向SDCard写入数据权限 -->
-    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!-- 摄像头 -->
-    <uses-permission android:name="android.permission.CAMERA"/>
+        android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
+        tools:ignore="ProtectedPermissions" /> <!-- 向SDCard写入数据权限 -->
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 摄像头 -->
+    <uses-permission android:name="android.permission.CAMERA" />
 
-    <uses-feature android:name="android.hardware.camera"/>
-    <uses-feature android:name="android.hardware.camera.autofocus"/>
+    <uses-feature android:name="android.hardware.camera" />
+    <uses-feature android:name="android.hardware.camera.autofocus" />
 
 
     <application
-            android:name=".DemoApp"
-            android:allowBackup="true"
-            android:icon="@mipmap/ic_launcher"
-            android:label="@string/app_name"
-            android:networkSecurityConfig="@xml/network_security_config"
-            android:roundIcon="@mipmap/ic_launcher_round"
-            android:supportsRtl="true"
-            android:theme="@style/AppTheme">
-        <activity android:name=".activities.poc.RelationActivity">
-        </activity>
+        android:name=".DemoApp"
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:networkSecurityConfig="@xml/network_security_config"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme">
         <activity
-                android:name=".activities.poc.RecordInfoActivity"
-                android:exported="true"/>
+            android:name=".activities.poc.RelationActivity"
+            android:exported="true"></activity>
         <activity
-                android:name=".activities.poc.DeviceTypeActivity"
-                android:exported="true"/>
+            android:name=".activities.poc.RecordInfoActivity"
+            android:exported="true" />
         <activity
-                android:name=".activities.poc.DeviceActivity"
-                android:exported="true">
-        </activity>
+            android:name=".activities.poc.DeviceTypeActivity"
+            android:exported="true" />
         <activity
-                android:name=".activities.poc.SceneActivity"
-                android:exported="true"/>
+            android:name=".activities.poc.DeviceActivity"
+            android:exported="true"></activity>
         <activity
-                android:name=".activities.poc.SpaceActivity"
-                android:exported="true"/>
-        <activity android:name=".activities.MainActivity">
-        </activity>
-        <activity android:name=".activities.GraphyActivity"/>
-        <activity android:name=".activities.WebViewActivity"/>
-        <activity android:name=".activities.PocActivity">
+            android:name=".activities.poc.SceneActivity"
+            android:exported="true" />
+        <activity
+            android:name=".activities.poc.SpaceActivity"
+            android:exported="true" />
+        <activity
+            android:name=".activities.MainActivity"
+            android:exported="true"></activity>
+        <activity
+            android:name=".activities.GraphyActivity"
+            android:exported="true" />
+        <activity
+            android:name=".activities.WebViewActivity"
+            android:exported="true" />
+        <activity
+            android:name=".activities.PocActivity"
+            android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
+                <action android:name="android.intent.action.MAIN" />
 
-                <category android:name="android.intent.category.LAUNCHER"/>
+                <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-        <activity android:name="com.zbar.lib.CaptureActivity"/>
+        <activity
+            android:name="com.zbar.lib.CaptureActivity"
+            android:exported="true" />
     </application>
 
 </manifest>

+ 31 - 1
demo/src/main/java/com/framework/app/api/Api.kt

@@ -1,4 +1,34 @@
 package com.framework.app.api
 
+import com.framework.mvvm.model.data.Model
+import com.framework.mvvm.model.vo.Define
+import com.framework.mvvm.model.vo.Floor
+import com.framework.mvvm.model.vo.Frame
+import com.framework.mvvm.model.vo.FrameRequest
+import retrofit2.http.Body
+import retrofit2.http.POST
+
 interface Api {
-}
+    /**
+     * 获取自字典数据
+     */
+    @POST("adm/dict")
+    suspend fun getDefine(): Model<Define>
+
+    /**
+     * 获取框架数据
+     */
+    @POST("adm/frame")
+    suspend fun getFrame(): Model<Frame>
+
+    @POST("adm/frame")
+    suspend fun getFrame(@Body request: FrameRequest): Model<Frame>
+
+    /**
+     * 获取楼层数据
+     */
+    @POST("adm/download")
+    suspend fun getFloor(): Model<Floor>
+
+}
+

+ 0 - 20
demo/src/main/java/com/framework/app/http/Request.kt

@@ -1,20 +0,0 @@
-package com.framework.app.http
-
-
-/**
- * 发起网络请求, 封装返回结果
- *
- * @param         block : 实际请求数据的函数, 是挂起函数
- * @return  Response<T> : 封装 block() 结果
- * */
-suspend fun <T> request(block: suspend () -> T): Response<T> {
-    var result: Response<T> = EmptyResponse()
-    runCatching {
-        block()
-    }.onSuccess {
-        result = Response.create(it)
-    }.onFailure {
-        result = Response.create(it)
-    }
-    return result
-}

+ 0 - 22
demo/src/main/java/com/framework/app/http/Respose.kt

@@ -1,22 +0,0 @@
-package com.framework.app.http
-
-/**
- * 封装网络返回的数据
- */
-sealed class Response<T> {
-    companion object {
-        fun <T> create(t: Throwable): FailureResponse<T> {
-            return FailureResponse(t.message ?: "you know nothing")
-        }
-
-        fun <T> create(data: T): Response<T> {
-            return SuccessResponse(data)
-        }
-
-        fun <T> create(): Response<T> = EmptyResponse()
-    }
-}
-
-class EmptyResponse<T> : Response<T>()
-data class SuccessResponse<T>(val data: T) : Response<T>()
-data class FailureResponse<T>(val msg: String) : Response<T>()

+ 83 - 0
demo/src/main/java/com/framework/di/Di.kt

@@ -1,2 +1,85 @@
 package com.framework.di
 
+import android.util.Log
+import androidx.room.Room
+import com.framework.app.api.Api
+import com.framework.mvvm.model.db.AdmDatabase
+import com.framework.mvvm.model.repository.FrameRepository
+import com.framework.mvvm.mv.FrameViewModel
+import okhttp3.OkHttpClient
+import okhttp3.logging.HttpLoggingInterceptor
+import org.kodein.di.*
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
+import java.io.UnsupportedEncodingException
+import java.net.URLDecoder
+import java.util.concurrent.TimeUnit
+
+
+val httpModule = DI.Module("netModule") {
+    // 构建 Retrofit 对象
+    bind {
+        singleton {
+            Retrofit.Builder()
+                .baseUrl("http://192.168.0.48:8876/")
+                .client(instance())
+                .addConverterFactory(GsonConverterFactory.create())
+                .build()
+        }
+    }
+
+    // 构建 OkHttpClient 对象
+    bind {
+        singleton {
+            OkHttpClient.Builder()
+                .connectTimeout(10, TimeUnit.SECONDS)
+                .addInterceptor(instance<HttpLoggingInterceptor>())
+                .build()
+        }
+    }
+
+    // 构建 HttpLoggingInterceptor 对象
+    bind {
+        singleton {
+            HttpLoggingInterceptor { message ->
+                try {
+                    val text: String = URLDecoder.decode(message, "utf-8")
+                    Log.e("OKHttp-----", text)
+                } catch (e: UnsupportedEncodingException) {
+                    e.printStackTrace()
+                    Log.e("OKHttp-----", message)
+                }
+            }.setLevel(HttpLoggingInterceptor.Level.BODY)
+        }
+    }
+
+    // Api 对象
+    bind {
+        singleton { instance<Retrofit>().create(Api::class.java) }
+    }
+}
+
+val repositoryModule = DI.Module("repository") {
+    bindSingleton { FrameRepository(instance(), instance()) }
+}
+
+val viewModelModule = DI.Module("viewModel") {
+    bindProvider { FrameViewModel(instance()) }
+}
+
+/*
+val factoryModule = DI.Module("factory") {
+    bindSingleton(tag = "FrameViewModel") { ViewModelFactory(instance<FrameRepository>()) }
+}
+*/
+
+val databaseModule = DI.Module("database") {
+    bindSingleton {
+        AdmDatabase.getDatabase(instance())
+       /* Room.databaseBuilder(
+            instance(),
+            AdmDatabase::class.java,
+            "adm_db"
+        ).build()*/
+    }
+}

+ 19 - 0
demo/src/main/java/com/framework/mvvm/model/data/AbsentLiveData.kt

@@ -0,0 +1,19 @@
+package com.framework.mvvm.model.data
+
+import androidx.lifecycle.LiveData
+
+/**
+ * 占位 LiveData
+ */
+class AbsentLiveData<T : Any?> private constructor() : LiveData<T>() {
+    init {
+        // use post instead of set since this can be created on any thread
+        postValue(null)
+    }
+
+    companion object {
+        fun <T> create(): LiveData<T> {
+            return AbsentLiveData()
+        }
+    }
+}

+ 35 - 0
demo/src/main/java/com/framework/mvvm/model/data/Data.kt

@@ -0,0 +1,35 @@
+package com.framework.mvvm.model.data
+
+/**
+ * ③ UI 数据类
+ *
+ * 数据最终包装类,无论数据来自本地还是网路;有状态
+ *
+ * @param state : 数据状态
+ * @param  data : 真实数据
+ * @param   msg : 提示信息
+ */
+data class Data<out T>(val state: State, val data: T? = null, val msg: String = "") {
+    companion object {
+        fun <T> success(data: T?): Data<T> {
+            return Data(State.SUCCESS, data, "")
+        }
+
+        fun <T> failure(msg: String): Data<T> {
+            return Data(State.FAILURE, null, msg)
+        }
+
+        fun <T> loading(): Data<T> {
+            return Data(State.LOADING, null, "")
+        }
+    }
+}
+
+/**
+ * 数据状态
+ */
+sealed interface State {
+    object SUCCESS : State
+    object LOADING : State
+    object FAILURE : State
+}

+ 104 - 0
demo/src/main/java/com/framework/mvvm/model/data/DataSource.kt

@@ -0,0 +1,104 @@
+package com.framework.mvvm.model.data
+
+import androidx.annotation.MainThread
+import androidx.lifecycle.*
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+
+
+/**
+ * 数据源函数
+ *
+ * @param     fromDb: 数据库获取数据
+ * @param     fromNt: 网络获取数据
+ * @param   isFromNt: 判断是否需要从网络获取数据
+ * @param  onSuccess: 获取资源成功回调
+ * @param  onFailure: 获取资源失败回调
+ *
+ * @param <RequestType> : 网络请求返回类型的封装
+ * @param  <ResultType> : 最终数据返回类型的封装
+ *
+ */
+fun <RequestType, ResultType> dataSource(
+    fromDb: suspend () -> LiveData<ResultType>,
+    fromNt: suspend () -> Response<RequestType>,
+    isFromNt: (ResultType) -> Boolean = { true },
+    onSuccess: suspend (RequestType) -> Unit,
+    onFailure: ((FailureResponse<RequestType>) -> Unit)? = null,
+): LiveData<Data<ResultType>> {
+    return DataSource(
+        fromDb = fromDb,
+        fromNt = fromNt,
+        isFromNt = isFromNt,
+        onSuccess = onSuccess,
+        onFailure = onFailure
+    ).asLiveData().distinctUntilChanged()
+}
+
+
+/**
+ * 数据源
+ */
+private class DataSource<RequestType, ResultType> @MainThread constructor(
+    private val fromDb: suspend () -> LiveData<ResultType>,          // 磁盘获取数据
+    private val fromNt: suspend () -> Response<RequestType>,      // 远程获取数据
+    private val isFromNt: (ResultType) -> Boolean = { true },        // 是否获取数据
+    private val onSuccess: suspend (RequestType) -> Unit,                    // 远程数据回调
+    private val onFailure: ((FailureResponse<RequestType>) -> Unit)? = null
+) {
+    private val result = liveData<Data<ResultType>> {
+        if (latestValue?.state != State.SUCCESS) {
+            emit(Data.loading())
+        }
+        val db: LiveData<ResultType> = fromDb()
+        val init = db.await()
+        val isFromNt = init == null || isFromNt(init)
+
+        if (!isFromNt) {
+            emitSource(db.map { Data.success(it) })
+        } else {
+            doFromNt(db, this)
+        }
+    }
+
+    private suspend fun doFromNt(
+        db: LiveData<ResultType>,
+        scope: LiveDataScope<Data<ResultType>>
+    ) {
+        val dbSource = scope.emitSource(db.map { Data.loading() })
+        when (val response = fromNt()) {
+            is EmptyResponse -> {
+                scope.emitSource(fromDb().map { Data.success(it) })
+            }
+            is SuccessResponse -> {
+                val data = response.data
+                dbSource.dispose()
+                onSuccess(data)
+                scope.emitSource(fromDb().map { Data.success(it) })
+            }
+            is FailureResponse -> {
+                onFailure?.invoke(response)
+                scope.emitSource(db.map { Data.failure(response.msg) })
+            }
+        }
+    }
+
+    fun asLiveData(): LiveData<Data<ResultType>> = result
+
+    private suspend fun <T> LiveData<T>.await() = withContext(Dispatchers.Main) {
+        val deferred = CompletableDeferred<T?>()
+        val observer = Observer<T> {
+            if (deferred.isActive) {
+                deferred.complete(it)
+            }
+        }
+
+        try {
+            observeForever(observer)
+            return@withContext deferred.await()
+        } finally {
+            removeObserver(observer)
+        }
+    }
+}

+ 45 - 0
demo/src/main/java/com/framework/mvvm/model/data/Http.kt

@@ -0,0 +1,45 @@
+package com.framework.mvvm.model.data
+
+/**
+ * 发起网络请求, 封装返回结果
+ *
+ * @param         block : 实际请求数据的函数, 是挂起函数
+ * @return  Response<T> : 封装 block() 结果
+ * */
+suspend fun <T> request(block: suspend () -> Model<T>): Response<T> {
+    var result: Response<T> = EmptyResponse()
+    runCatching {
+        block()
+    }.onSuccess {
+        // "000000" 代表数据请求成功
+        result = if (it.code == "00000") {
+            Response.create(it.data)
+        } else {
+            Response.create(it.message ?: "http request Ok, but don't have data")
+        }
+    }.onFailure {
+        result = Response.create(it.message ?: "you know nothing")
+    }
+    return result
+}
+
+/**
+ * ② Http 数据容器
+ */
+sealed class Response<T> {
+    companion object {
+        fun <T> create(message: String): FailureResponse<T> {
+            return FailureResponse(message)
+        }
+
+        fun <T> create(data: T): Response<T> {
+            return SuccessResponse(data)
+        }
+
+        fun <T> create(): Response<T> = EmptyResponse()
+    }
+}
+
+class EmptyResponse<T> : Response<T>()
+data class SuccessResponse<T>(val data: T) : Response<T>()
+data class FailureResponse<T>(val msg: String) : Response<T>()

+ 10 - 0
demo/src/main/java/com/framework/mvvm/model/data/Model.kt

@@ -0,0 +1,10 @@
+package com.framework.mvvm.model.data
+
+/**
+ * ① Api 返回数据容器
+ */
+data class Model<T>(
+    val code: String,
+    val message: String? = null,
+    val data: T
+)

+ 65 - 0
demo/src/main/java/com/framework/mvvm/model/db/AdmDatabase.kt

@@ -0,0 +1,65 @@
+package com.framework.mvvm.model.db
+
+import android.content.Context
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
+import com.framework.mvvm.model.db.dao.*
+import com.framework.mvvm.model.db.entity.*
+
+@Database(
+    entities = [
+        MajorEntity::class,
+        SystemEntity::class,
+        RelationDictEntity::class,
+        EquipmentEntity::class,
+        InfosConfigEntity::class,
+        PipeConfigEntity::class,
+        RelConfigEntity::class,
+        M2dEquipEntity::class,
+        ConfigEntity::class,
+        FileEntity::class,
+        SpaceEntity::class,
+        QrCodeEntity::class,
+        ObjectEntity::class,
+        ProjectEntity::class,
+        RelationEntity::class,
+        ProblemArchEntity::class,
+        ProblemEquipEntity::class,
+    ], version = 1, exportSchema = true
+)
+
+abstract class AdmDatabase : RoomDatabase() {
+    abstract fun configDao(): ConfigDao
+    abstract fun equipmentDao(): EquipmentDao
+    abstract fun fileDao(): FileDao
+    abstract fun infosConfigDao(): InfosConfigDao
+    abstract fun m2dEquipDao(): M2dEquipDao
+    abstract fun majorDao(): MajorDao
+    abstract fun objectDao(): ObjectDao
+    abstract fun pipeConfigDao(): PipeConfigDao
+    abstract fun problemArch(): ProblemArchDao
+    abstract fun problemEquipDao(): ProblemEquipDao
+    abstract fun projectDao(): ProjectDao
+    abstract fun qrCodeDao(): QrCodeDao
+    abstract fun relationDao(): RelationDao
+    abstract fun relationDictDao(): RelationDictDao
+    abstract fun relConfigDao(): RelConfigDao
+    abstract fun spaceDao(): SpaceDao
+    abstract fun systemDao(): SystemDao
+
+    companion object {
+        @Volatile
+        private var instance: AdmDatabase? = null
+
+        fun getDatabase(context: Context): AdmDatabase {
+            return instance ?: synchronized(this) {
+                instance ?: Room.databaseBuilder(
+                    context,
+                    AdmDatabase::class.java,
+                    "adm_db"
+                ).build().also { instance = it }
+            }
+        }
+    }
+}

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

@@ -0,0 +1,22 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.ConfigEntity
+
+/**
+ * 表 config Dao
+ */
+@Dao
+interface ConfigDao {
+    @Query("select * from config")
+    suspend fun getConfigs(): List<ConfigEntity>
+
+    @Query("select * from config where id = :id")
+    suspend fun getConfigById(id: String): ConfigEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insConfig(config: ConfigEntity)
+
+    @Delete
+    suspend fun delConfig(config: ConfigEntity)
+}

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

@@ -0,0 +1,22 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.EquipmentEntity
+
+/**
+ * 表 equipment Dao
+ */
+@Dao
+interface EquipmentDao {
+    @Query("select * from equipment")
+    suspend fun getEquipments(): List<EquipmentEntity>
+
+    @Query("select * from equipment where id = :id")
+    suspend fun getEquipmentById(id: String): EquipmentEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insEquipment(equipment: EquipmentEntity)
+
+    @Delete
+    suspend fun delEquipment(equipment: EquipmentEntity)
+}

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

@@ -0,0 +1,22 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.FileEntity
+
+/**
+ * 表 file Dao
+ */
+@Dao
+interface FileDao {
+    @Query("select * from file")
+    suspend fun getFiles(): List<FileEntity>
+
+    @Query("select * from file where id = :id")
+    suspend fun getFileById(id: String): FileEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insFile(file: FileEntity)
+
+    @Delete
+    suspend fun delFile(file: FileEntity)
+}

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

@@ -0,0 +1,22 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.InfosConfigEntity
+
+/**
+ * 表 infos_config Dao
+ */
+@Dao
+interface InfosConfigDao {
+    @Query("select * from infos_config")
+    suspend fun getConfigs(): List<InfosConfigEntity>
+
+    @Query("select * from infos_config where id = :id")
+    suspend fun getConfigById(id: String): InfosConfigEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insConfig(config: InfosConfigEntity)
+
+    @Delete
+    suspend fun delConfig(config: InfosConfigEntity)
+}

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

@@ -0,0 +1,22 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.M2dEquipEntity
+
+/**
+ * table m2d_equip Dao
+ */
+@Dao
+interface M2dEquipDao {
+    @Query("select * from m2d_equip")
+    suspend fun getM2ds(): List<M2dEquipEntity>
+
+    @Query("select * from m2d_equip where id = :id")
+    suspend fun getM2dById(id: String): M2dEquipEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insM2d(m2d: M2dEquipEntity)
+
+    @Delete
+    suspend fun delM2d(m2d: M2dEquipEntity)
+}

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

@@ -0,0 +1,23 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.MajorEntity
+
+/**
+ * 表 maj_dict Dao
+ */
+@Dao
+interface MajorDao {
+    @Query("select * from major")
+    suspend fun getMajors(): List<MajorEntity>
+
+    @Query("select * from major where id = :id")
+    suspend fun getMajorById(id: String): MajorEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insMajor(major: MajorEntity)
+
+    @Delete
+    suspend fun delMajor(major: MajorEntity)
+
+}

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

@@ -0,0 +1,26 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.ObjectEntity
+
+/**
+ * 表 object Dao
+ */
+@Dao
+interface ObjectDao {
+    @Query("select * from object")
+    suspend fun getObjects(): List<ObjectEntity>
+
+    @Query("select * from object where id = :id")
+    suspend fun getObjectById(id: String): ObjectEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insObject(obj: ObjectEntity)
+
+    @Delete
+    suspend fun delObject(obj: ObjectEntity)
+
+    // @Transaction
+    // @Query("select * from object")
+    // fun getObjectAndInfosWithOutlines() : List<ObjectAndInfosWithOutlines>
+}

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

@@ -0,0 +1,22 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.PipeConfigEntity
+
+/**
+ * 表 pipe_config Dao
+ */
+@Dao
+interface PipeConfigDao {
+    @Query("select * from pipe_config")
+    suspend fun getConfigs(): List<PipeConfigEntity>
+
+    @Query("select * from pipe_config where id = :id")
+    suspend fun getConfigById(id: String): PipeConfigEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insConfig(config: PipeConfigEntity)
+
+    @Delete
+    suspend fun delConfig(config: PipeConfigEntity)
+}

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

@@ -0,0 +1,23 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.ProblemArchEntity
+
+/**
+ * 表 problem_arch Dao
+ */
+@Dao
+interface ProblemArchDao {
+    @Query("select * from problem_arch")
+    suspend fun getProblems(): List<ProblemArchEntity>
+
+    @Query("select * from problem_arch where id = :id")
+    suspend fun getProblemById(id: String): ProblemArchEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insProblem(problem: ProblemArchEntity)
+
+    @Delete
+    suspend fun delProblem(problem: ProblemArchEntity)
+
+}

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

@@ -0,0 +1,22 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.ProblemEquipEntity
+
+/**
+ * 表 problem_equip Dao
+ */
+@Dao
+interface ProblemEquipDao {
+    @Query("select * from problem_equip")
+    suspend fun getProblems(): List<ProblemEquipEntity>
+
+    @Query("select * from problem_equip where id = :id")
+    suspend fun getProblemById(id: String): ProblemEquipEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insProblem(config: ProblemEquipEntity)
+
+    @Delete
+    suspend fun delProblem(config: ProblemEquipEntity)
+}

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

@@ -0,0 +1,23 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.lifecycle.LiveData
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.ProjectEntity
+
+/**
+ * 表 project Dao
+ */
+@Dao
+interface ProjectDao {
+    @Query("select * from project")
+    fun getProjects(): LiveData<List<ProjectEntity>>
+
+    @Query("select * from project where id = :id")
+    suspend fun getProjectById(id: String): ProjectEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insProject(project: ProjectEntity)
+
+    @Delete
+    suspend fun delProject(project: ProjectEntity)
+}

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

@@ -0,0 +1,22 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.QrCodeEntity
+
+/**
+ * 表 qr_code Dao
+ */
+@Dao
+interface QrCodeDao {
+    @Query("select * from qr_code")
+    suspend fun getQrCodes(): List<QrCodeEntity>
+
+    @Query("select * from qr_code where id = :id")
+    suspend fun getQrCodeById(id: String): QrCodeEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insQrCode(qrCode: QrCodeEntity)
+
+    @Delete
+    suspend fun delQrCode(qrCode: QrCodeEntity)
+}

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

@@ -0,0 +1,22 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.RelConfigEntity
+
+/**
+ * 表 rel_config Dao
+ */
+@Dao
+interface RelConfigDao {
+    @Query("select * from rel_config")
+    suspend fun getConfigs(): List<RelConfigEntity>
+
+    @Query("select * from rel_config where id = :id")
+    suspend fun getConfigById(id: String): RelConfigEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insConfig(config: RelConfigEntity)
+
+    @Delete
+    suspend fun delConfig(config: RelConfigEntity)
+}

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

@@ -0,0 +1,23 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.ObjectEntity
+import com.framework.mvvm.model.db.entity.RelationEntity
+
+/**
+ * 表 relation Dao
+ */
+@Dao
+interface RelationDao {
+    @Query("select * from relation")
+    suspend fun getRelations(): List<RelationEntity>
+
+    @Query("select * from relation where id = :id")
+    suspend fun getRelationById(id: String): RelationEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insRelation(relation: RelationEntity)
+
+    @Delete
+    suspend fun delRelation(relation: RelationEntity)
+}

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

@@ -0,0 +1,22 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.RelationDictEntity
+
+/**
+ * 表 relation_dict Dao
+ */
+@Dao
+interface RelationDictDao {
+    @Query("select * from relation_dict")
+    suspend fun getRelationDicts(): List<RelationDictEntity>
+
+    @Query("select * from relation_dict where id = :id")
+    suspend fun getRelationDictById(id: String): RelationDictEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insRelationDict(relationDict: RelationDictEntity)
+
+    @Delete
+    suspend fun delRelationDict(relationDict: RelationDictEntity)
+}

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

@@ -0,0 +1,22 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.*
+import com.framework.mvvm.model.db.entity.SpaceEntity
+
+/**
+ * 表 space Dao
+ */
+@Dao
+interface SpaceDao {
+    @Query("select * from space")
+    suspend fun getSpaces(): List<SpaceEntity>
+
+    @Query("select * from space where id = :id")
+    suspend fun getSpaceById(id: String): SpaceEntity
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insSpace(space: SpaceEntity)
+
+    @Delete
+    suspend fun delSpace(space: SpaceEntity)
+}

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

@@ -0,0 +1,17 @@
+package com.framework.mvvm.model.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import com.framework.mvvm.model.db.entity.SystemEntity
+
+/**
+ * 表 sys_dict Dao
+ */
+@Dao
+interface SystemDao {
+    @Query("select * from system")
+    suspend fun getEqus(): List<SystemEntity>
+
+    @Query("select * from system where id = :id")
+    suspend fun getEquById(id: String): SystemEntity
+}

+ 19 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/ConfigEntity.kt

@@ -0,0 +1,19 @@
+package com.framework.mvvm.model.db.entity
+
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 基本配置 表
+ */
+@Entity(tableName = "config")
+@Serializable
+data class ConfigEntity(
+    @PrimaryKey val id: String,
+    @ColumnInfo(name = "name") val name: String,   // 配置项名名称
+    @ColumnInfo(name = "code") val code: String,   // 配置项代码
+    @ColumnInfo(name = "data") val data: String    // 配置项的具体内容, 内容是 Json 格式,
+)

+ 30 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/EquipmentEntity.kt

@@ -0,0 +1,30 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+/**
+ * 设备字典表(远程无对应表)
+ */
+@Entity(tableName = "equipment")
+data class EquipmentEntity(
+    @PrimaryKey val id: String,
+    @ColumnInfo(name = "valid") val valid: Int,                  // 1 正常 0 删除
+    @ColumnInfo(name = "project_id") val projectId: String,      // 项目 id
+    @ColumnInfo(name = "code") val code: String,                 // 系统编码
+    @ColumnInfo(name = "name") val name: String,                 // 系统名称
+    @ColumnInfo(name = "obj_type") val objType: String,          // 对象类型 "system"
+    @ColumnInfo(name = "group_code") val groupCode: String,      // 集团编码
+    @ColumnInfo(name = "major_code") val majorCode: String,      // 专业编码
+    @ColumnInfo(name = "system_code") val systemCode: String,       // 系统编码
+    @ColumnInfo(name = "parent_code") val parentCode: String,    // 父编码
+    @ColumnInfo(name = "equipment_code") val equipmentCode: String, // 设备编码
+    @ColumnInfo(name = "creator") val creator: String,           // 创建人
+    @ColumnInfo(name = "creation_time") val creationTime: Long,  // 创建时间
+    @ColumnInfo(name = "modifier") val modifier: String,            // 修改人
+    @ColumnInfo(name = "modified_time") val modifiedTime: String,   // 修改时间
+    @ColumnInfo(name = "alias_code") val aliasCode: String,      // 编码别名
+    @ColumnInfo(name = "alias_name") val aliasName: String,      // 名称别名
+    @ColumnInfo(name = "version") val version: String,              // 版本
+)

+ 32 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/FileEntity.kt

@@ -0,0 +1,32 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 文件表
+ */
+@Entity(tableName = "file")
+@Serializable
+data class FileEntity(
+    @PrimaryKey(autoGenerate = false) val id: String,
+    @ColumnInfo(name = "file_type") val fileType: String,          // 文件类型(photo|video|file|...)
+    @ColumnInfo(name = "biz_type") val bizType: String,            // 业务类型(object:对象附件|problem_arch:空间问题附件|problem_equip:设备问题附件)
+    @ColumnInfo(name = "file_path") val filePath: String,          // 文件存储路径
+    @ColumnInfo(name = "client_path") val clientPath: String,      // app端文件存储路径
+    @ColumnInfo(name = "ref_obj_id") val refObjId: String,         // 关联的对象id
+    @ColumnInfo(name = "ref_info_code") val refInfoCode: String,   // 关联的对象信息点code
+    @ColumnInfo(name = "remark") val remark: String,               // 描述
+    @ColumnInfo(name = "order_num") val orderNum: Int,             // 文件附件(照片)的排序序号
+    @ColumnInfo(name = "project_id") val projectId: String,        // 项目id
+    @ColumnInfo(name = "building_id") val buildingId: String,      // 建筑id
+    @ColumnInfo(name = "floor_id") val floorId: String,            // 楼层id
+    @ColumnInfo(name = "creator") val creator: String,             // 创建人
+    @ColumnInfo(name = "creation_time") val creationTime: String,  // 创建时间
+    @ColumnInfo(name = "modifier") val modifier: String,           // 修改人
+    @ColumnInfo(name = "modified_time") val modifiedTime: String,  // 修改时间
+    @ColumnInfo(name = "valid") val valid: Int,                    // 合法标识
+    @ColumnInfo(name = "upload_flag") val uploadFlag: String,      // app端上传数据标记
+)

+ 21 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/InfosConfigEntity.kt

@@ -0,0 +1,21 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 信息配置 表
+ */
+@Entity(tableName = "infos_config")
+@Serializable
+data class InfosConfigEntity(
+    @PrimaryKey(autoGenerate = false) val id: String,
+    @ColumnInfo(name = "name") val name: String,               // 对象类型名称
+    @ColumnInfo(name = "obj_type") val objType: String,        // 对象类型(space|equipment)
+    @ColumnInfo(name = "class_code") val classCode: String,    // 对象class_code
+    @ColumnInfo(name = "major_code") val majorCode: String,    // 专业代码(类型为设备时)
+    @ColumnInfo(name = "system_code") val systemCode: String,  // 系统代码(类型为设备时)
+    @ColumnInfo(name = "infos") val infos: String,             // 对象类型的信息详情点配置
+)

+ 22 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/InfosEntity.kt

@@ -0,0 +1,22 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+/**
+ * Object 对象中的 infos 字段
+ */
+@Entity(tableName = "info")
+class InfosEntity(
+    @PrimaryKey(autoGenerate = true) var id: Int = 0,
+    @ColumnInfo(name = "bim_id_pre") val bimIdPre: String,
+    @ColumnInfo(name = "count") val count: String,
+    @ColumnInfo(name = "floor_elevation") val floorElevation: Double,
+    @ColumnInfo(name = "floor_map") val floorMap: String,
+    @ColumnInfo(name = "floor_sequence_id") val floorSequenceID: Int,
+    @ColumnInfo(name = "model_id") val modelId: String,
+    @ColumnInfo(name = "building_id") val buildingId: String,
+    @ColumnInfo(name = "floor_id") val floorId: String,
+    @ColumnInfo(name = "object_id") val objectId: String,
+)

+ 19 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/M2dEquipEntity.kt

@@ -0,0 +1,19 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 正向建模设备 表
+ */
+@Entity(tableName = "m2d_equip")
+@Serializable
+data class M2dEquipEntity(
+    @PrimaryKey(autoGenerate = false) val id: String,
+    @ColumnInfo(name = "name") val name: String,              //范围定义名称
+    @ColumnInfo(name = "major_code") val majorCode: String,   //专业代码
+    @ColumnInfo(name = "system_code") val systemCode: String, //系统代码
+    @ColumnInfo(name = "class_code") val classCode: String,   //设备类代码
+)

+ 21 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/MajorEntity.kt

@@ -0,0 +1,21 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 专业字典表(远程无对应表)
+ */
+@Entity(tableName = "major")
+@Serializable
+class MajorEntity(
+    @PrimaryKey val id: String,
+    @ColumnInfo(name = "label") val label: String,             // 专业标签
+    @ColumnInfo(name = "code") val code: String,               // 专业编码
+    @ColumnInfo(name = "type") val type: String,               // 专业类型
+    @ColumnInfo(name = "order_num") val orderNum: Int,         // 序号
+    @ColumnInfo(name = "dict_type_id") val dictTypeId: String, //字典类型id
+    @ColumnInfo(name = "valid") val valid: Int,                // 有效标识
+)

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

@@ -0,0 +1,56 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.annotation.NonNull
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 对象表
+ * 建筑,楼层,空间, 设备
+ */
+@Entity(tableName = "object")
+@Serializable
+data class ObjectEntity(
+    @NonNull
+    @PrimaryKey val id: String,
+    @ColumnInfo(name = "name") val name: String,
+    @ColumnInfo(name = "local_id") val localId: String,            // 对象位置编码
+    @ColumnInfo(name = "local_name") val localName: String,        // 对象位置名称
+    @ColumnInfo(name = "group_code") val groupCode: String,        // 集团编码
+    @ColumnInfo(name = "grouping") val grouping: Int,              // 1 表示单个对象,2 表示对象组
+    @ColumnInfo(name = "project_id") val projectId: String,        // 项目id
+    @ColumnInfo(name = "building_id") val buildingId: String,      // 建筑id
+    @ColumnInfo(name = "floor_id") val floorId: String,            // 建筑id
+    @ColumnInfo(name = "obj_type") val objType: String,            // 对象类型
+    @ColumnInfo(name = "class_code") val classCode: String,        // 对象类型编码
+    @ColumnInfo(name = "creator") val creator: String,             // 创建人
+    @ColumnInfo(name = "create_app") val createApp: String,        // 创建对象的应用
+    @ColumnInfo(name = "creation_time") val creationTime: Long,  // 创建时间
+    @ColumnInfo(name = "modifier") val modifier: String,           // 修改人
+    @ColumnInfo(name = "modified_time") val modifiedTime: Long,  // 修改时间
+    @ColumnInfo(name = "client_device") val clientDevice: String,  // 标识客户端设备
+    @ColumnInfo(name = "client_id") val clientId: String,          // 客户端生成id
+    @ColumnInfo(name = "update_app") val updateApp: String,        // 更新对象的应用
+    @ColumnInfo(name = "upload_flag") val uploadFlag: String,      // app端上传数据标记
+    @ColumnInfo(name = "valid") val valid: Int,                    // 合法标识: 1 合法, 0 非法
+    @ColumnInfo(name = "delivery_state") val deliveryState: Int,   // BDTP交付状态: 1 已交付, 0 待交付
+    @ColumnInfo(name = "d2m_state") val d2mState: Int,             // 逆向数据的数模同步状态(0:未同步;1:已同步)
+    @ColumnInfo(name = "virtual_codes") val virtualCodes: String,   // 虚点清单: Json 数据格式
+    @ColumnInfo(name = "infos") val infos: String                 // 信息点数据: Json 数据格式
+    // @ColumnInfo(name = "parent_id") val parentId: String,          // 上级对象id,为数据操作提供便利(设备:楼层;空间:楼层;楼层:建筑;竖井:建筑;)
+)
+
+/*
+data class Infos(
+    val bimId: String,
+    val bimLocation: String,
+    val codeType: Int,
+    val height: Int,
+    val modelId: String,
+    val outline: List<List<List<Outline>>>,
+    val schemeId: String,
+    val state: String
+)
+ */

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

@@ -0,0 +1,14 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "outline")
+data class OutlineEntity(
+    @PrimaryKey(autoGenerate = true) var id: Int = 0,
+    @ColumnInfo(name = "x") val x: Double,
+    @ColumnInfo(name = "y") val y: Double,
+    @ColumnInfo(name = "z") val z: Double,
+    @ColumnInfo(name = "infos_id") val infosId: String,
+)

+ 21 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/PipeConfigEntity.kt

@@ -0,0 +1,21 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 管道配置 表
+ */
+@Entity(tableName = "pipe_config")
+@Serializable
+data class PipeConfigEntity(
+    @PrimaryKey(autoGenerate = false) val id: String,
+    @ColumnInfo(name = "class_code_from") val classCodeFrom: String,    // from 端设备对象class_code
+    @ColumnInfo(name = "class_code_to") val classCodeTo: String,        //  to  端设备对象class_code
+    @ColumnInfo(name = "pipe_type") val pipeType: String,               // 管道类型(数据字典定义)
+    @ColumnInfo(name = "pipe_sub_type") val pipeSubType: String,        // 管道用途(业务定义补充描述类型)
+    @ColumnInfo(name = "pipe_direction") val pipeDirection: Int,        // 管道方向(1:正向from->to;-1:反向to->from;0:无方向)
+    @ColumnInfo(name = "pipe_description") val pipeDescription: String, // 描述信息
+)

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

@@ -0,0 +1,28 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+/**
+ * 结构问题  表
+ */
+@Entity(tableName = "problem_arch")
+data class ProblemArchEntity(
+    @PrimaryKey val id: String,
+    @ColumnInfo(name = "work_id") val workId: String,              // 交付工作流程id
+    @ColumnInfo(name = "floor_id") val floorId: String,            // 问题所在楼层id
+    @ColumnInfo(name = "project_id") val projectId: String,        // 项目id
+    @ColumnInfo(name = "building_id") val buildingId: String,      // 建筑id
+    @ColumnInfo(name = "geom_type") val geomType: String,          // 问题记录的几何类型(point|line|polygon)
+    @ColumnInfo(name = "geom") val geom: String,                   // 问题记录的几何数据(Json)
+    @ColumnInfo(name = "problem_type") val problemType: String,    // 问题类型
+    @ColumnInfo(name = "problem_state") val problemState: Int,     // 建筑结构核查任务状态(0:删除;1:有效;2:已解决)
+    @ColumnInfo(name = "message") val message: String,             // 问题描述
+    @ColumnInfo(name = "creator") val creator: String,             // 创建人
+    @ColumnInfo(name = "creation_time") val creationTime: String,  // 创建时间
+    @ColumnInfo(name = "modifier") val modifier: String,           // 修改人
+    @ColumnInfo(name = "modified_time") val modifiedTime: String,  // 修改时间
+    @ColumnInfo(name = "upload_flag") val uploadFlag: String,      // app端上传数据标记
+    @ColumnInfo(name = "valid") val valid: Int                     // 1 有效,2 无效
+)

+ 28 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/ProblemEquipEntity.kt

@@ -0,0 +1,28 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+/**
+ * 设备问题 表
+ */
+@Entity(tableName = "problem_equip")
+data class ProblemEquipEntity(
+    @PrimaryKey val id: String,
+    @ColumnInfo(name = "work_id") val workId: String,              // 交付工作流程id
+    @ColumnInfo(name = "floor_id") val floorId: String,            // 问题所在楼层id
+    @ColumnInfo(name = "project_id") val projectId: String,        // 项目id
+    @ColumnInfo(name = "building_id") val buildingId: String,      // 建筑id
+    @ColumnInfo(name = "equip_id") val equipId: String,            // 设备id
+    @ColumnInfo(name = "problem_type") val problemType: String,    // 问题类型
+    @ColumnInfo(name = "problem_state") val problemState: Int,     // 建筑结构核查任务状态(0:删除;1:有效;2:已解决)
+    @ColumnInfo(name = "message") val message: String,             // 问题描述
+    @ColumnInfo(name = "creator") val creator: String,             // 创建人
+    @ColumnInfo(name = "creation_time") val creationTime: String,  // 创建时间
+    @ColumnInfo(name = "modifier") val modifier: String,           // 修改人
+    @ColumnInfo(name = "modified_time") val modifiedTime: String,  // 修改时间
+    @ColumnInfo(name = "upload_flag") val uploadFlag: String,      // app端上传数据标记
+    @ColumnInfo(name = "valid") val valid: Int                     // 1 有效,2 无效
+
+)

+ 26 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/ProjectEntity.kt

@@ -0,0 +1,26 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 项目表(远程无对应表)
+ */
+@Entity(tableName = "project")
+@Serializable
+data class ProjectEntity(
+    @PrimaryKey val id: String,
+    @ColumnInfo(name = "name") val name: String,
+    @ColumnInfo(name = "object_type") val objectType: String,
+    @ColumnInfo(name = "group_code") val groupCode: String,
+    @ColumnInfo(name = "local_id") val localId: String,
+    @ColumnInfo(name = "local_name") val localName: String,
+    @ColumnInfo(name = "create_time") val createTime: String,
+    @ColumnInfo(name = "last_update") val lastUpdate: String,
+    @ColumnInfo(name = "introduction") val introduction: String,
+    @ColumnInfo(name = "business_floor_num") val businessFloorNum: String,
+    @ColumnInfo(name = "office_floor_num") val officeFloorNum: String
+    // @ColumnInfo(name = "infos") val infos: String,
+)

+ 30 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/QrCodeEntity.kt

@@ -0,0 +1,30 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 二维码表
+ */
+@Entity(tableName = "qr_code")
+@Serializable
+data class QrCodeEntity(
+    @PrimaryKey val id: String,
+    @ColumnInfo(name = "qr_code") val qrCode: String,              // 二维码数据值
+    @ColumnInfo(name = "obj_id") val objId: String,                // 二维码对应的对象id
+    @ColumnInfo(name = "floor_id") val floorId: String,            // 楼层id
+    @ColumnInfo(name = "location") val location: String,           // 位置坐标({x:1,y:1,z:1})
+    @ColumnInfo(name = "remark") val remark: String,               // 描述信息
+    @ColumnInfo(name = "project_id") val projectId: String,        // 项目id
+    @ColumnInfo(name = "building_id") val buildingId: String,      // 建筑id
+    @ColumnInfo(name = "creator") val creator: String,             // 创建人
+    @ColumnInfo(name = "creation_time") val creationTime: String,  // 创建时间
+    @ColumnInfo(name = "modifier") val modifier: String,           // 修改人
+    @ColumnInfo(name = "modified_time") val modifiedTime: String,  // 修改时间
+    @ColumnInfo(name = "valid") val valid: String,                 // 合法标识
+    @ColumnInfo(name = "upload_flag") val uploadFlag: String,      // app端上传数据标记
+
+
+)

+ 22 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/RelConfigEntity.kt

@@ -0,0 +1,22 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 关系配置 表
+ */
+@Entity(tableName = "rel_config")
+@Serializable
+data class RelConfigEntity(
+    @PrimaryKey val id: String,
+    @ColumnInfo(name = "obj_type_from") val objTypeFrom: String,      // from 端对象类型(space|equipment)
+    @ColumnInfo(name = "obj_type_to") val objTypeTo: String,          //  to  端对象类型(space|equipment)
+    @ColumnInfo(name = "class_code_from") val classCodeFrom: String,  // from 端对象class_code
+    @ColumnInfo(name = "class_code_to") val classCodeTo: String,      //  to  端对象class_code
+    @ColumnInfo(name = "graph_code") val graphCode: String,           // 关系的图类型代码
+    @ColumnInfo(name = "rel_code") val relCode: String,               // 关系的边类型代码
+
+)

+ 31 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/RelationDictEntity.kt

@@ -0,0 +1,31 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 关系字典表(关系定义)(远程无对应表)
+ */
+@Entity(tableName = "relation_dict")
+@Serializable
+class RelationDictEntity(
+    @PrimaryKey val id: String,
+    @ColumnInfo(name = "code") val code: String,                 // 关系编码
+    @ColumnInfo(name = "name") val name: String,                 // 关系名
+    @ColumnInfo(name = "graph_code") val graphCode: String,       // 图编码
+    @ColumnInfo(name = "valid") val valid: Int,                  // 有效标识
+    @ColumnInfo(name = "creator") val creator: String,           // 创建人
+    @ColumnInfo(name = "creation_time") val creationTime: String, // 创建时间
+    @ColumnInfo(name = "modifier") val modifier: String,         // 修改人
+    @ColumnInfo(name = "modified_time") val modifiedTime: String, // 修改时间
+    @ColumnInfo(name = "directional") val directional: Int,      // 方向
+    @ColumnInfo(name = "target_Objs") val targetObjs: String,     // 目标对象
+    @ColumnInfo(name = "attribute") val attribute: String,          // 属性
+    @ColumnInfo(name = "before_cal_rels") val beforeCalRels: String,
+    @ColumnInfo(name = "calRules") val calRules: String,
+    @ColumnInfo(name = "fromObjType") val fromObjType: String,
+    @ColumnInfo(name = "toObjType") val toObjType: String,
+    @ColumnInfo(name = "remark") val remark: String
+)

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

@@ -0,0 +1,41 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.annotation.NonNull
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 关系(业务)表
+ */
+@Entity(tableName = "relation")
+@Serializable
+data class RelationEntity(
+    @NonNull
+    @PrimaryKey(autoGenerate = false)
+    @ColumnInfo(name = "id") val id: String,                        // uuid
+    @ColumnInfo(name = "project_id") val projectId: String,         // 项目id
+    @ColumnInfo(name = "building_id") val buildingId: String,         // 项目id
+    @ColumnInfo(name = "floor_id") val floorId: String,             // 楼层id
+    @ColumnInfo(name = "group_code") val groupCode: String,         // 集团代码
+    @ColumnInfo(name = "graph_id") val graphId: String,             // 图id
+    @ColumnInfo(name = "graph_code") val graphCode: String,         // 图编码
+    @ColumnInfo(name = "rel_code") val relCode: String,             // 关系编码
+    @ColumnInfo(name = "rel_value") val relValue: String,           // 关系值
+    @ColumnInfo(name = "obj_from") val objFrom: String,             // 关系源对象
+    @ColumnInfo(name = "obj_to") val objTo: String,                 // 关系目标对象
+    @ColumnInfo(name = "create_app") val createApp: String,         // 创建关系的App
+    @ColumnInfo(name = "update_app") val updateApp: String,         // 更新关系的App
+    @ColumnInfo(name = "creator") val creator: String,              // 创建人
+    @ColumnInfo(name = "creation_time") val creationTime: String,   // 创建时间
+    @ColumnInfo(name = "modifier") val modifier: String,            // 更新人
+    @ColumnInfo(name = "modified_time") val modifiedTime: String,   // 修改时间
+    @ColumnInfo(name = "client_id") val clientId: String,           // 客户端生成id
+    @ColumnInfo(name = "client_device") val clientDevice: String,   // 标识客户端设备
+    @ColumnInfo(name = "upload_flag") val uploadFlag: String,       // app端上传数据标记
+    @ColumnInfo(name = "delivery_state") val deliveryState: Int,    // BDTP交付状态: 1 已交付, 0 待交付
+    @ColumnInfo(name = "valid") val valid: String,                  // 合法标识: 1 合法, 0 非法
+    @ColumnInfo(name = "d2m_state") val d2mState: String,           // 逆向数据的数模同步状态(0:未同步;1:已同步)
+
+)

+ 41 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/SpaceEntity.kt

@@ -0,0 +1,41 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 工作空间表
+ */
+@Entity(tableName = "space")
+@Serializable
+data class SpaceEntity(
+    @PrimaryKey val id: String,
+    @ColumnInfo(name = "work_id") val workId: String,                // 交付工作流程id
+    @ColumnInfo(name = "outline") val outline: String,               // 空间边界,模型更新空间变化时,用来做匹配计算
+    @ColumnInfo(name = "space_id") val spaceId: String,              // 空间id
+    @ColumnInfo(name = "space_type") val spaceType: String,          // 任务空间类型(base|sub)
+    @ColumnInfo(name = "parent_space_id") val parentSpaceId: String, // 父级空间id(空间类型为sub时)
+    @ColumnInfo(name = "arch_state") val archState: Int,             // 建筑结构核查任务状态(0:待核查;1:核查中;2:核查完毕)
+    @ColumnInfo(name = "equip_state") val equipState: Int,           // 设备勘测任务状态(0:待勘测;1:勘测中;2:勘测完毕)
+    @ColumnInfo(name = "project_id") val projectId: String,          // 项目id
+    @ColumnInfo(name = "building_id") val buildingId: String,        // 建筑id
+    @ColumnInfo(name = "floor_id") val floorId: String,              // 楼层id
+    @ColumnInfo(name = "creator") val creator: String,               // 创建人
+    @ColumnInfo(name = "creation_time") val creationTime: String,    // 创建时间
+    @ColumnInfo(name = "modifier") val modifier: String,             // 修改人
+    @ColumnInfo(name = "modified_time") val modifiedTime: String,    // 修改时间
+    @ColumnInfo(name = "valid") val valid: Int,                      // 合法标识
+    @ColumnInfo(name = "upload_flag") val uploadFlag: Int,           // app端上传数据标记
+)
+
+/*
+// 后期优化
+@Entity(tableName = "outline")
+data class OutLineEntity(
+    @PrimaryKey(autoGenerate = true) val id: Int,
+    @ColumnInfo(name = "x") val x: Double,
+    @ColumnInfo(name = "y") val y: Double,
+    @ColumnInfo(name = "z") val z: Double
+)*/

+ 32 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/SystemEntity.kt

@@ -0,0 +1,32 @@
+package com.framework.mvvm.model.db.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.serialization.Serializable
+
+/**
+ * 系统字典表(远程无对应表)
+ */
+@Entity(tableName = "system")
+@Serializable
+data class SystemEntity(
+    @PrimaryKey val id: String,
+    @ColumnInfo(name = "code") val code: String,                    // 系统编码
+    @ColumnInfo(name = "name") val name: String,                    // 系统名称
+    @ColumnInfo(name = "valid") val valid: Int,                     // 1 正常 0 删除
+    @ColumnInfo(name = "alias_code") val aliasCode: String,         // 编码别名
+    @ColumnInfo(name = "alias_name") val aliasName: String,         // 名称别名
+    @ColumnInfo(name = "project_id") val projectId: String,         // 项目 id
+    @ColumnInfo(name = "obj_type") val objType: String,             // 对象类型 "system"
+    @ColumnInfo(name = "group_code") val groupCode: String,         // 集团编码
+    @ColumnInfo(name = "major_code") val majorCode: String,         // 专业编码
+    @ColumnInfo(name = "system_code") val systemCode: String,       // 系统编码
+    @ColumnInfo(name = "parent_code") val parentCode: String,       // 父编码
+    @ColumnInfo(name = "equipment_code") val equipmentCode: String, // 设备编码
+    @ColumnInfo(name = "version") val version: String,              // 版本
+    @ColumnInfo(name = "creator") val creator: String,              // 创建人
+    @ColumnInfo(name = "creation_time") val creationTime: Long,     // 创建时间
+    @ColumnInfo(name = "modifier") val modifier: String,               // 修改人
+    @ColumnInfo(name = "modified_time") val modifiedTime: String,      // 修改时间
+)

+ 20 - 0
demo/src/main/java/com/framework/mvvm/model/db/entity/rel/MajorSysRelation.kt

@@ -0,0 +1,20 @@
+package com.framework.mvvm.model.db.entity.rel
+
+import androidx.room.Embedded
+import androidx.room.Entity
+import androidx.room.Relation
+import com.framework.mvvm.model.db.entity.MajorEntity
+import com.framework.mvvm.model.db.entity.SystemEntity
+
+/**
+ * 专业与系统一对多关系表
+ */
+@Entity(tableName = "major_sys_rel")
+data class MajorSysRel(
+    @Embedded val user: MajorEntity,
+    @Relation(
+        parentColumn = "id",
+        entityColumn = ""
+    )
+    val systems: List<SystemEntity>
+)

+ 38 - 0
demo/src/main/java/com/framework/mvvm/model/repository/FrameRepository.kt

@@ -0,0 +1,38 @@
+package com.framework.mvvm.model.repository
+
+import androidx.lifecycle.LiveData
+import com.framework.app.api.Api
+import com.framework.app.base.IRepository
+import com.framework.mvvm.model.data.Data
+import com.framework.mvvm.model.data.dataSource
+import com.framework.mvvm.model.data.request
+import com.framework.mvvm.model.db.AdmDatabase
+import com.framework.mvvm.model.db.entity.ProjectEntity
+import com.framework.mvvm.model.vo.FrameRequest
+
+class FrameRepository(
+    private val api: Api,
+    private val db: AdmDatabase
+) : IRepository {
+
+    fun getProjects(): LiveData<Data<List<ProjectEntity>>> {
+        return dataSource(
+            fromDb = { db.projectDao().getProjects() },
+            fromNt = { request { api.getFrame() } },
+            onSuccess = {
+                // TODO 拆分 api.getFrame()  返回的结果
+            }
+        )
+    }
+
+    fun getProjects(request: FrameRequest): LiveData<Data<List<ProjectEntity>>> {
+        return dataSource(
+            fromDb = { db.projectDao().getProjects() },
+            fromNt = { request { api.getFrame(request) } },
+            onSuccess = { frame ->
+                println("frame: $frame")
+            }
+        )
+    }
+
+}

+ 19 - 0
demo/src/main/java/com/framework/mvvm/model/vo/Config.kt

@@ -0,0 +1,19 @@
+package com.framework.mvvm.model.vo
+
+/**
+ * Config 对象
+ */
+data class Config(
+    val id: String,
+    val code: String,
+    val name: String,
+    val data: List<ConfigData>
+)
+
+/**
+ * Config 对象
+ */
+data class ConfigData(
+    val code: String,
+    val name: String
+)

+ 25 - 0
demo/src/main/java/com/framework/mvvm/model/vo/Define.kt

@@ -0,0 +1,25 @@
+package com.framework.mvvm.model.vo
+
+import com.framework.mvvm.model.db.entity.*
+
+/**
+ * 数据定义
+ */
+data class Define(
+    val config: List<ConfigEntity>,
+    val dict: Dict,
+    val m2dTypes: List<M2dEquipEntity>,
+    //val pipeConfig: List<Any>,
+    //val infosConfig: List<Any>,
+    //val relConfig: List<Any>
+)
+
+/**
+ * Dict 对象
+ */
+data class Dict(
+    val system: List<SystemEntity>,
+    val major: List<MajorEntity>,
+    val equipment: List<EquipmentEntity>,
+    val relation: List<RelationDictEntity>
+)

+ 18 - 0
demo/src/main/java/com/framework/mvvm/model/vo/Floor.kt

@@ -0,0 +1,18 @@
+package com.framework.mvvm.model.vo
+
+import com.framework.mvvm.model.db.entity.ObjectEntity
+import com.framework.mvvm.model.db.entity.SpaceEntity
+
+/**
+ * Floor 对象
+ */
+data class Floor(
+    val floorId: String,
+    val jobSpace: List<SpaceEntity>, // outline 需要处理
+    val objects: List<ObjectEntity>,
+    val file: List<Any>,
+    val qrCode: List<Any>,
+    val relations: List<Any>,
+    val problemArch: List<Any>,
+    val problemEquip: List<Any>
+)

+ 13 - 0
demo/src/main/java/com/framework/mvvm/model/vo/Frame.kt

@@ -0,0 +1,13 @@
+package com.framework.mvvm.model.vo
+
+import com.framework.mvvm.model.db.entity.ObjectEntity
+import com.framework.mvvm.model.db.entity.ProjectEntity
+
+/**
+ * 框架数据
+ */
+data class Frame(
+    val buildingsAndFloors: List<ObjectEntity>,
+    val projects: List<ProjectEntity>
+)
+

+ 10 - 0
demo/src/main/java/com/framework/mvvm/model/vo/FrameRequest.kt

@@ -0,0 +1,10 @@
+package com.framework.mvvm.model.vo
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class FrameRequest(
+    val userId: String,
+    val projectId: String,
+    val groupCode: String
+)

+ 37 - 0
demo/src/main/java/com/framework/mvvm/mv/FrameViewModel.kt

@@ -0,0 +1,37 @@
+package com.framework.mvvm.mv
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.Transformations
+import androidx.lifecycle.ViewModel
+import com.framework.mvvm.model.data.AbsentLiveData
+import com.framework.mvvm.model.data.Data
+import com.framework.mvvm.model.db.entity.ProjectEntity
+import com.framework.mvvm.model.repository.FrameRepository
+import com.framework.mvvm.model.vo.FrameRequest
+
+
+class FrameViewModel(private val repository: FrameRepository) : ViewModel() {
+    private val _frameRequest = MutableLiveData<FrameRequest>()
+
+    private var _projects = MutableLiveData<Data<List<ProjectEntity>>>()
+
+    val projects: LiveData<Data<List<ProjectEntity>>> =
+        Transformations.switchMap(_frameRequest) { request ->
+            if (request == null) {
+                AbsentLiveData.create()
+            } else {
+                repository.getProjects(request)
+            }
+        }
+
+    fun requestFrame(request: FrameRequest) {
+        _frameRequest.value = request
+    }
+
+    fun retry() {
+        _frameRequest.value?.let {
+            _frameRequest.value = it
+        }
+    }
+}

+ 25 - 0
demo/src/main/java/com/framework/mvvm/mv/ViewModelFactory.kt

@@ -0,0 +1,25 @@
+package com.framework.mvvm.mv
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.framework.app.base.IRepository
+import kotlin.reflect.KClass
+
+/**
+ * ViewModel 工厂
+ * 根据 repository 生成 ViewModel
+ */
+class ViewModelFactory(
+    private val repository: IRepository
+) : ViewModelProvider.Factory {
+    private val map = HashMap<KClass<out IRepository>, ViewModel>()
+    override fun <T : ViewModel> create(modelClass: Class<T>): T {
+        var vm = map[repository::class]
+        if (vm == null) {
+            val constructor = modelClass.getConstructor(repository.javaClass)
+            vm = constructor.newInstance(repository)
+            map[repository::class] = vm
+        }
+        return vm as T
+    }
+}

+ 15 - 1
demo/src/main/java/com/sybotan/android/demo/DemoApp.kt

@@ -29,12 +29,24 @@ import android.content.Context
 import android.util.Log
 import com.arashivision.sdkcamera.InstaCameraSDK
 import com.arashivision.sdkmedia.InstaMediaSDK
+import com.framework.di.*
 import com.sybotan.android.demo.tools.AssetsUtil
+import org.kodein.di.DI
+import org.kodein.di.DIAware
+import org.kodein.di.android.x.androidXModule
 import java.io.File
 
 
-class DemoApp : Application() {
+class DemoApp : Application(), DIAware {
 
+    override val di: DI by DI.lazy {
+        import(androidXModule(this@DemoApp))
+        import(databaseModule)
+        import(httpModule)
+        import(repositoryModule)
+        import(viewModelModule)
+        //import(factoryModule)
+    }
 
     companion object {
         private val TAG = DemoApp::class.java.name
@@ -44,9 +56,11 @@ class DemoApp : Application() {
         fun getContext(): DemoApp? {
             return mContext as DemoApp
         }
+
         fun getInstance(): DemoApp? {
             return sInstance
         }
+
         val COPY_DIR: String = getInstance()?.cacheDir.toString() + "/hdr_source"
     }
 

+ 31 - 5
demo/src/main/java/com/sybotan/android/demo/activities/PocActivity.kt

@@ -5,13 +5,22 @@ import android.os.Bundle
 import androidx.appcompat.app.AppCompatActivity
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.core.app.ActivityCompat
+import com.framework.mvvm.model.vo.FrameRequest
+import com.framework.mvvm.mv.FrameViewModel
 import com.sybotan.android.demo.R
 import com.sybotan.android.demo.activities.poc.SceneActivity
 import com.sybotan.android.demo.activities.poc.SpaceActivity
-import com.zbar.lib.CaptureActivity
 import org.jetbrains.anko.startActivity
+import org.kodein.di.DI
+import org.kodein.di.DIAware
+import org.kodein.di.android.closestDI
+import org.kodein.di.android.x.viewmodel.viewModel
+
+class PocActivity : AppCompatActivity(), DIAware {
+
+    override val di: DI by closestDI()
+    private val mVm: FrameViewModel by viewModel()
 
-class PocActivity : AppCompatActivity() {
     private val tag = "PocActivity"
     private val REQUEST_EXTERNAL_STORAGE = 1 // 不可改
 
@@ -28,11 +37,28 @@ class PocActivity : AppCompatActivity() {
         sceneCL.setOnClickListener {
             startActivity<SceneActivity>()
         }
+
+        mVm.projects.observe(this) { data ->
+            println("data:>:$data")
+        }
+
+        mVm.requestFrame(
+            FrameRequest(
+                userId = "bdtp",
+                projectId = "Pj0002220002",
+                groupCode = "BR"
+            )
+        )
     }
 
     private fun checkStoragePermission() {
-        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE,
-                Manifest.permission.WRITE_EXTERNAL_STORAGE),
-                REQUEST_EXTERNAL_STORAGE)
+        ActivityCompat.requestPermissions(
+            this, arrayOf(
+                Manifest.permission.READ_EXTERNAL_STORAGE,
+                Manifest.permission.WRITE_EXTERNAL_STORAGE
+            ),
+            REQUEST_EXTERNAL_STORAGE
+        )
     }
+
 }

+ 1 - 1
gradle.properties

@@ -40,7 +40,7 @@ ANDROID_SUPPORT_VERSION=28.0.0
 FASTJSON_VERSION=1.1.70.android
 DEVELOPER_NAME=Andy
 JDK_VERSION=8
-ANDROID_BUILD_TOOLS_VERSION=28.0.3
+ANDROID_BUILD_TOOLS_VERSION=30.0.2
 CONSTRAINT_VERSION=2.0.0-alpha2
 NEXUS_PASSWORD=saga
 ANKO_VERSION=0.10.8